Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

CloudWatch Logs にバラバラのアプリケーションログを集約して幸福度が上がった話 #AWS #CloudWatchLogs

CloudWatch Logs

サーバーサイドエンジニアの鈴木です。社内で長く運用されつづけているアプリケーションのログの運用についていくつか課題を発見したので、CloudWatch Logs を使って改善を行いました。

現状と課題

これまではアプリケーションのログは、ログ出力を行うメソッドが用意されていたものの各エンジニアが任意のログファイル名で任意のフォーマットで自由にログを出力していました。そして各インスタンス内に出力されたログファイルを、定期的に自作のバッチスクリプトで分割された状態で S3 に転送を行っていました。そのため、S3 にログファイルは残ってはいるものの、ファイルが分割された状態かつログのフォーマットが統一されていないため目的のログを極めて探しづらい状態でした。

改善策

まずはバラバラになっているログを集約する方法として CloudWatch Logs、DataDog、スクリプトで集約して S3 に置いて Athena で検索できるようにするなどの方法の候補をあげました。運用コストの観点から fluentd や Elasticsearch を使って自前で仕組みを作る方法は見送りました。そして、

  • EC2 インタンスには CloudWatch Agent をインストールしやすく導入における設定作業コストが少ないこと( 該当のアプリケーションは EC2 で動いています )
  • 一度 CloudWatch Logs に格納することができれば AWS コンソールに標準で搭載されている検索機能や CloudWatch Logs Insight を使って検索を行いやすくなること
  • S3 へのエクスポートにも対応していて、必要になったらあとから設定が行えること

を踏まえて設定コストに対して得られるメリットが多いという理由から CloudWatch Logs に集約してみることにしました。1 点懸念される点としては CloudWatch Logs は料金が高めという噂を聞いてたいので、導入してから許容できないほど料金が上がる傾向が見られた場合はログの量を減らすなどので調整することを検討していました。

また、既存のログ出力メソッドはグローバル関数として定義されていたり、ログレベルが INFO で固定されていたりしたため、このタイミングで Monolog を簡易的にラップするロガークラスを使えるようにしました。このロガークラスから出力されるフォーマットは全て JSON 形式に統一するようにしています。

手順

一度に行うとリスクがありそうだったので、下記のようにいくつかの小さいステップに分けて改善を行うことにしました。

  1. アプリケーションが動いている EC2 インスタンスに CloudWatch Agent をインストールして、指定したファイルに出力されたログを CloudWatch Logs に転送するようにする。
  2. 既存のログ出力メソッドを同一の JSON 形式のフォーマットに変換して同一ファイルに出力するように書き換える。
  3. 新しいロガークラスを利用できるようにして、既存のログ出力メソッドを DEPLECATED にする。

インストール方法

EC2 へのインストールは簡単で yum コマンドを使うだけでした。( コードで構成管理が行われていないサーバーなので今回は手作業です )

sudo yum -y install awslogs

サービスの起動とインスタンスの再起動時に自動でサービスが起動するようにします。

sudo service awslogs start
sudo chkconfig awslogs on

設定ファイル

設定ファイルは 2 種類あり、下記のようなファイルを置きました。

/etc/awslogs/awscli.conf

[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1

/etc/awslogs/awslogs.conf

[/path/to/log/file.log]
datetime_format = %b %d %H:%M:%S
file = /path/to/log/file.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /path/to/log/file

アクセス権限の付与

EC2 のロールに CloudWatchAgentServerPolicy を付加しました。

結果

  • CloudWatch Logs の標準機能でログの検索を行えるようになり、行われた操作を追跡したり、エラーの調査を行いやすくなったりしました。また、出力フォーマットを JSON 形式に統一したので、JSON を検索する書式を使えるようになり、複雑な検索も行えるようになりました。
  • ちょうど移行を進めている最中に CloudWatch Logs Insight でロググループを横断した検索もできるようになったのでより便利に。下記は CloudWatch Logs Insight の検索画面の例です。1 時間以内のユーザーのあるデータを削除したログの一覧を得ています。

CloudWatch Insight の検索画面

  • CloudWatch Logs のメトリクスフィルターを使って特定のログが出力されたときに CloudWatch Alarm を起動することが容易になりました。
  • (副産物ですが) 意味もなく出力していたログを発見しやすくなり、掃除することができました。

まとめ

結果的に CloudWatch Logs に集約することで、いくつものメリットを同時に得ることができました。今後は「コスト削減をするには?」「よりログから情報を得やすくするには?」といった次の課題と向き合っていきたいと考えています。

積極採用中!!

子育て家族アプリFammを運営するTimers inc.では、現在エンジニアを積極採用中!
急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP: http://timers-inc.com/engineerings

プロダクトマネージャーも積極募集中です!

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる