NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

配属後4ヶ月の新人がPythonとAWSを活用してSlackBotを作ってみた

本記事は  基盤デザインウィーク  5日目の記事です。
🌈  4日目  ▶▶ 本記事 ▶▶  6日目  💻

はじめに

こんにちは!基デザウィーク5日目を担当する、入社1年目の松尾と申します。

突然ですが道の譲り合いをしたことはありますか?通行人と反復横跳びをするアレです。微笑ましい一幕ですが、忙しい時にはできれば避けたいですよね。

しかし新人業務のひとつである毎日16時の宅配電話対応の際、固定電話が1台しかないため、私は鳴り響く電話を9名の新人と譲り合うことになります。事態は一刻を争い、電話が鳴った後に相談することは不可能です。

ああ...業務で使用するSlackにて電話対応に関する集計を取り、対応できる人のみにメンション付きリマインドをするBotさえあればこの状況を打破できるのに...。(to be continued...

ということで今回は新人業務の効率化を目的としてSlackBotの開発を行いました。

また配属3ヶ月目頃にオンプレサーバーで動作するSlackBotを開発をしており、その経験を活かしつつ今後の業務で使用するAWS技術の研鑽ができないかと考え、AWS上で動作するSlackBotの開発に挑戦することになりました。

今回は配属4ヶ月の新人がPythonやAWSを活用してどのような開発を行なったのかといった話や、開発を通じてどのように感じたか等をご紹介できればと思います。

開発したSlackBotの概要

開発したSlackBotは大きく分けて2つの機能を有しています。

1つ目は朝8:50に電話対応の可不可を集計する機能。対応可能な人はスタンプを押し、不可能な人は理由をスレッドで書き込むルールとしてBotがメッセージを送信します。この機能により「直前になって誰も対応できない!」という状況を防ぐこともできます。(滅多にありませんが...。)

2つ目は朝の集計で電話対応可能な人にのみメンションをつけて夕方15:45にリマインドする機能です。まず朝の通知で誰がスタンプを押したか取得し、その人物宛のメンション付きメッセージをBotが送信します。朝の予定から状況が変わった場合や立候補する場合はスレッドで相談するルールとしており、円滑な作業分担をサポートしてくれます。

使用技術

今回開発したSlackBotはSlackAPI、Python、AWSを利用しています。
難しく聞こえますが役割分担をしているだけです。簡単に説明していきます。

SlackAPI
SlackAPIは今回の場合、プログラムのコードからSlackにメッセージを送信する際に必要となります。PythonからSlackへの窓口のようなイメージです。

Python
Pythonはプログラミング言語の1つです。今回のSlackBotにおいて、前述のSlackAPIはPythonを介して呼び出され、Slackにメッセージを通知することになります。基本的に「こういう機能が作りたいな」という発想はプログラムを通じて実現することになるので、非常に重要な役割を担うことになります。

今回開発したSlackBotは朝と夕方でそれぞれ、以下のようなフローで動作しています。

AWS
AWSはAmazonが提供するクラウドサービスの総称です。Pythonを日次で実行するにあたって、使用したAWSサービスは以下の通りです。

  1. AWS Lambda
    今回はPythonを実行するために利用。
  2. Amazon EventBridge
    AWS Lambdaを日次で起動させるために利用。
  3. Amazon DynamoDB
    Slackメッセージに対して一意に割り振られる値(スレッド値)を保存するために利用。
  4. AWS SecretsManager
    SlackAPITokenやWebhookURL等の秘匿すべき情報を安全に参照するために利用。
  5. Amazon CloudWatch Logs
    動作に関して問題がないか確認するために利用。

これらのAWSサービスを組み合わせ、以下の図のような構成でAWS上にアプリケーションをデプロイしました。またデプロイの際にはコードからAWSリソースの作成ができるAWS CloudFormationの拡張ツール、AWS SAMを利用しています。

実装に関して困ったこと

実装に関していくつか困ったことがあったので書き留めておきます。

1. AWS Lambdaのトリガーを2つ指定できない
当初、現構成におけるAmazon DynamoDBの箇所はAmazon SNSとAmazon SQSにおけるファンアウト構成で実現するつもりでした。ですがAWS Lambdaは1トリガーからのみ引数を取得できるらしく、Amazon EventBridgeとAmazon SQSの両方から引数を取得する形になりうまく動作しませんでした。

困り果ててSlackチャンネルで相談してみたところ、弊社のすごい方々(Japan AWS Top EngineerとJapan AWS Ambassador)からアドバイスを頂き、Amazon DynamoDBでの実装に落ち着きました。

終わってみれば別の手段でええやんという単純な話ではありますが、人に相談しないと視野狭窄に陥ってしまいますね。

2. 時間がおかしい
Amazon EventBridgeで日次実行するために朝のAWS Lambdaの実行を8:50、夕方のAWS Lambdaを15:45に設定したのですが、なぜか時間がズレてしまう出来事がありました。これはAWSが一律でUTC(協定世界時)を採用しているが故に発生しており、正しくは9時間の時差を考慮して時間を設定してやる必要があります。

またAWS Lambda内で日付を取得してAmazon DynamoDBのキーとして使用する構成においても、同様に時差によるズレが発生しました。朝のAWS Lambdaの起動時刻をUTC8:50に指定したことにより、JSTでは前日の23:50となってしまい日付が1日分ズレていました。時刻ではなく日付で扱っていたため気づきにくい部分でしたが、AWSで時間データを扱う際はJSTではなくUTCとなることを念頭に置くべきでした。

UTCを考慮する必要性はこれまでの人生で感じたことが無かったので、今更ながら扱うサービスの規模の大きさに少しの感動を覚えました。

3. コードに問題がないのにAWS Lambdaが失敗する
よし、完璧だ!と思ってデプロイしたにも関わらず、ずっとAWS Lambdaの処理が失敗する出来事がありました。

結論としてはただタイムアウトしていただけなのですが、なかなか真相に辿りつけず苦労しました。どうやらAWS Lambdaはタイムアウトのデフォルト値が3.0秒なのに対し、Amazon DynamoDBを参照することでAWS Lambda全体の処理時間が4.0秒程度かかってしまっていたようです。開発時の私は「デフォルト値が3.0秒ならAWSにおけるほとんどの処理は3.0秒以内に終わるのだろう」と勘違いをしており、簡単な修正をしないまま時間を消費してしまいました。

実際に稼働させて

開発したSlackBotを稼働させてからというもの、電話が鳴った際に新人が一斉に立ち上がる光景は見なくなりました。この時点で当初の目的は達成しているのですが、他にも以下のような恩恵があったと感じました。

  1. 対応者以外が電話に注意を割く必要がなくなったため、自分の業務に集中することができるようになった。
  2. 誰が出社しているかが判別しやすくなり、コミュニケーションが取りやすくなった。
  3. 毎日通知が来るため、新人のSlackチャンネルが活性化した。
  4. 誰が対応したか明確になったので、率先した行動を評価しやすくなった。

またAWS技術研鑽のため開発に挑戦して、以下のような点から成長ができたと感じました。

  1. 0からAWSリソースの構成を組み立ることができた。
  2. コードからAWSリソースを作成する過程でAWSサービスの細かな仕様を調査して、実際に作成することができた。
  3. AWS CloudWatchLogsを見て、どのリソースのどの部分で問題が生じているか自分なりの見当がつけられるようになった。

おわりに

AWSは資格試験が豊富でインプットの手段には困らないと思います。ですがアウトプットの機会を掴むことは難しい印象です。そのためAWSサービスを組み合わせて実際に稼働させるという経験が新人のうちにできたことは、本当に幸運だったと感じます。

本経験を通じて大切だと感じたことは以下の3つです。
1. ノーリスクで挑戦できる機会は貴重、決して逃すな。
2. 方針を決めたらまずは有識者に相談、責任が伴いそうなら上司に相談。新人はとことんリスクを回避すべし。
3. 無駄な経験はない。

以上です。新人の皆さん、共に頑張りましょう!それでは。

執筆者:松尾遊宇 駆け出しインフラエンジニア。ヌオーを愛する男。