初めまして、こんにちは。 セーフィー株式会社 プラットフォーム開発部の大友です。 サーバーサイド周りの開発を担当しています。
今回はユーザーより問い合わせを受け、システム内を調べなければならないとき、サーバーサイドはどのように対応しているのか!その一例を紹介したいと思います。
テーマはログ解析を用いた問い合わせ対応です。
Amazon Athena と お問い合わせ
今回の主役となるサービスです。
セーフィーではログ解析の一つに Amazon Athena を使用しています。 Athenaについて簡単に説明しますと、S3 に保存したログデータに対して SQL を実行し、ログの解析が行えるというサービスになります。解析したいログの形式に合わせた Athenaのテーブルを作成しておき、テーブルに対して SQL を発行することで結果を得えることが出来ます。
セーフィーでは、サーバーログを S3 に保管しているので、Athenaは打ってつけでした。
例えば、Safie Viewerを操作してカメラ映像の閲覧であったり、カメラ設定を変更したりすると、裏側ではRESTful APIが実行され、都度以下のようにJSON形式で実行ログが出力されています。 (重要なセキュリティ情報を含んだAPIパラメーターはマスキングを施してからログ出力しています。マスキングされたデータはセーフィーでも確認できません。そして、以下のログは完全なダミーです。)
{"timestamp": "2020-08-14T11:22:33+09:00", "camera_id": "camera1", "api": "/image", "method": "GET", "parameter": null, "user": "user1", "ua": "chrome"} {"timestamp": "2020-08-14T11:22:34+09:00", "camera_id": "camera2", "api": "/setting", "method": "POST" , "parameter": "name=hoge", "user": "share-user", "ua": "chrome"} {"timestamp": "2020-08-14T11:22:35+09:00", "camera_id": "camera3", "api": "/video", "method": "GET", "parameter": null, "user": "user2", "ua": "chrome"} (中略) {"timestamp": "2020-08-16T20:10:44+09:00", "camera_id": "camera1", "api": "/image", "method": "GET", "parameter": null, "user": "user1", "ua": "chrome"} {"timestamp": "2020-08-16T20:10:45+09:00", "camera_id": "camera2", "api": "/setting", "method": "POST" , "parameter": "name=camera2", "user": "owner-user", "ua": "chrome"} {"timestamp": "2020-08-16T20:10:46+09:00", "camera_id": "camera3", "api": "/video", "method": "GET", "parameter": null, "user": "user2", "ua": "chrome"}
camera_idというのは、ユーザーが所持しているカメラの固有IDになります。 もし「気づいたらcamera2の名前が変わっていたので元に戻しました。7月は名前は変わってなかったです。いつ名前が変わったのか調べて欲しい。」という問い合わせが発生したらAthenaで以下のSQLを実行します。
SELECT * FROM safie.test_log WHERE dt >= '2020-08-01' AND camera_id='camera2'
すると、camera2に対しての操作ログを取得できます。 (dt >= '2020-08-01'は 2020-08-01 以降に出力されたログから検索するという意味になります)
検索した結果以下のログが引っ掛かりました。
{"timestamp": "2020-08-14T11:22:34+09:00", "camera_id": "camera2", "api": "/setting", "method": "POST" , "parameter": "name=hoge", "user": "share-user", "ua": "chrome"} {"timestamp": "2020-08-16T20:10:45+09:00", "camera_id": "camera2", "api": "/setting", "method": "POST" , "parameter": "name=camera2", "user": "owner-user", "ua": "chrome"}
( ここで、/setting はカメラの名前を変更できるAPIだとします。) 名前が二回変更されていますね。ログを下から見ていきましょう。
名前を元に戻したとの事なので、二件目の 2020-08-16 20:10:45 の時間に記録されているログはカメラの名前を元に戻すために操作した履歴だと分かります。変更したユーザーは owner-user さんです。
次に一件目の 2020-08-14 11:22:34 の時間帯にも、カメラ名が変更されています。 名前を変更したのは share-user さんです。
セーフィーのカメラはシェアすることができるため、今回の問い合わせではカメラをシェアされたshare-userさんがカメラ名を変更したことが分かりました (カメラをシェアする際には、シェアの権限が設定できます)。
セーフィーでのAthenaを使った解析はおおまかにこのような流れになります。
(実運用では毎回 SQL を書いて実行するのは面倒なので、調べたい箇所だけを入力したら 検索する別Toolがあり、SQLを直接書くことは滅多にありません。)
上記例ではログのサンプルが少ないため便利さに疑問符が残るかもしれません。 セーフィーではAthena解析に使うことになるログは、一日辺り圧縮して平均2GBほど溜まります。そんなログの塊をAthenaで一か月分解析を行ったとしても、解析時間は1分程度も掛かりませんし、一か月分のログから、調査のための有意義な情報を得られると考えれば、Athenaの強力さが伝わるのではないでしょうか。
Athenaの注意点
Athenaを沢山褒めてしまいましたが、使う上で気を付けることがあります。 それはコストです。Athenaは使えば使うほどお金が取られる従量課金なので、きちんと パーティション を設定し、パーティションに合わせてログを保存する必要があります。
パーティションの設定が無いと、Athenaでの検索は都度全てのログデータに対して行われるため常に全検索となります。それではコストが嵩んでしまいます。
パーティションを設定すると、いつから~いつまで と検索する範囲を絞り込むことができます。絞り込むことで発生するコストは最小限に抑えられます。
文章だけだと中々イメージが湧きませんね。パーティション無と有の比較図を用意しました。
パーティション設定の有無でS3に保存するパスが若干異なっていることが分かります。設定有にある、dt=2020-08-01 は Apache Hive 形式と呼ばれ、パーティションを利用する時は、このHiveを用いてデータを保管していく必要があります。HiveのdtはSQLの条件式に書くことができるので、dt>='2020-08-03’ AND dt <= ‘2020-08-04’ とすると、8/3と8/4分のログのみに絞って、解析することが可能になるわけです。
次の章では、セーフィーがどのようにログをS3まで運んでいるのかを紹介したいと思います。
セーフィーの構成
セーフィーのサーバーは全てAWS上に構築されていて優に三桁の数のEC2インスタンスが立ち上がっています。
サーバーにも沢山の種類があり、カメラの制御や映像を扱うCamサーバー APIを提供するAPIサーバー、動画の配信を司る配信サーバー等が存在します。 (まだまだサーバーは存在しますが、ここでは割愛します)
ログを扱うのは、 logサーバーになります。
以下は構成図です。
構成図を見ると特に複雑なことはしていませんね。
logサーバーは全サーバーログのAggregatorです。ログを収集し、S3の保存からElastic searchへの転送を担っています。logサーバーが収集しているログは、Athenaで分析できるログのほかにも、各サーバーで動作している専用アプリケーションのログに監視ログなど、稼働ログ全般に渡ります。そして、ログ収集にはfluentdを利用しています。(一部 fluent bitも存在します)
Athenaのログはパーティションが働く形(s3://athena/logs/dt=2020-08-14/app.log.tar.gz.1)で保存されていきます。新しいパーティションが増えたら(dt=2020-08-15)、Athenaテーブルのパーティション情報を更新する必要があるため、セーフィーではCIの定期実行にてこれを 行っています。(コマンドは MSCK REPAIR TABLE です)
ここまでを行い、セーフィーでは日頃Athenaを問い合わせに活用しています。
パーティション更新はCIでなくても、AWS lambda や、最近ですと AWS Glueを利用した方法があります。いずれもコストが発生しますが、AWS Glueが良いようです。
さいごに
Athenaを活用した問い合わせ対応については以上となります。
今回はAthenaを用いてAPIの実行ログを遡って検索し、カメラに対しての操作履歴を確認することが出来ました。いつどうなった系の問い合わせには無類の強さを発揮するAthenaですが、カメラ映像が起因した問い合わせ(映像が暗すぎる、明るすぎる等)には活用場面があまり無く、あくまで解決するための一種のツールとして利用しています。(カメラ映像に起因した問い合わせは、サポートチームに映像をシェアして頂き、実際に映像を拝見した上で対処方法を案内しています。)
Athenaが便利でとても使えることが分かると、今ではAthenaで検索する前提で開発を行う場面もあり、まだまだ社内でも活躍の場は広がりそうです。
そして最後に。セーフィーは常により良いサービスにするべく、日々進化しています。セーフィーを更に良いサービスにしたい、自分のスキルで課題を解決したい。そんな意識をお持ちの方や、向上心が高い方を歓迎しています。ご興味のある方のご連絡をお待ちしてます。
ここまでお目通しいただき有難うございました。