この記事はCyberAgent Developers Advent Calendar 2017 6日目の記事です。
アドテクスタジオ Dynalyst開発チームの黒崎 (@kuro_m88) です。早いもので入社して3年目になりました。今年はDatadog Logsを一部本番に導入したので紹介しようと思います。
Dynalystではサーバやアプリケーション、AWSのマネージドサービスの監視やメトリクスの可視化にDatadogを使っています。
どんな風に使っているかは以前発表した資料があるのでこちらをご覧下さい。
そして、このスライドの最後に「ログのマネジメントもできるといいなぁ…?」と書いてありますが、なんとその願いが叶った結果、Datadog Logsが11月末に発表されました!!!!
何ができるのかは公式ドキュメントの図がわかりやすいです。
ログの収集と処理と出力、大きくわけて3つの概念があることがわかります。
ログの入力方法は、現時点では
- サーバにDatadog Agentをインストールし、
- アプリケーションログファイルを監視、転送する
- Dockerコンテナのログ出力を監視、転送する
- AWS CloudWatch Logsのログを転送する
- AWS LambdaやECS、EKSのログがDatadogで管理できます!
- fluent pluginによる転送
- rsyslogによる転送
が用意されています。サーバホストの監視用にDatadog Agentは全台にインストールしているので、そのエージェントをアップデートするだけでログの収集にも対応できるのは便利ですね!同様にログ転送に既にfluentdを使っている方も多いでしょうから、その場合はfluent pluginの設定を書き換えるだけでログの送り先としてDatadogを追加することも簡単そうです。
個人的に一番うれしかったのはCloudWatch Logsの対応です。AWS LambdaとECSのログは現状CloudWatch Logsに転送されていて、ログの調査が必要な時はAWS consoleを開いて検索していました。
現在もDynalystでは、CloudWatch側でログに”ERROR”という単語が含まれるの行数をカウントするメトリクスフィルタを設定し、そのメトリクスをDatadogに連携させるくらいはしているのですが、アプリケーションごとにメトリクスのキーの名前が変わってしまうので、Datadogの特徴であるタグによるメトリクスのグルーピング機能が使えずグラフによる可視化やアラート設定はやりずらさがあります。
これがDatadog側でログの管理ができるようになったことで使い慣れたUIで柔軟な管理ができるようになるとすれば非常に助かります。
そんなDatadog Logsですが、現在まだPublic Betaで、利用するには申請が必要です。本番運用に載せてガンガン使っていくにはまだ早そうですが、待ち望んでいた機能なのでさっそく検証してみました。
前述したとおりログの入力方法は色々あるのですが、今回はDatadog Agentによるログ収集と、CloudWatch LogsをDatadogに連携させる方法を紹介します。
Datadog Agentによるログの収集
agentのインストール
[ec2-user@ip-10-0-0-10 ~]$ DD_API_KEY=[YOUR_API_KEY] bash -c "$(curl -L https://raw.githubusercontent.com/DataDog/datadog-agent/master/cmd/agent/install_script.sh)"
Red Hat flavoredなディストリビューション(AmazonLinuxやCentOSなど)のdatadog-agentは今まではinit.dで管理されていましたが、v6からはupstartで管理されるようです。
よって、サービスが起動しているかどうかコマンドも代わって、以下のようになります。
[ec2-user@ip-10-0-0-10 ~]$ sudo status datadog-agent
datadog-agent start/running, process 3266
今まで sudo service datadog-agent status
と打って確認していた機能は、以下のようなコマンドに変わったようです。
[ec2-user@ip-10-0-0-10 ~]$ sudo /opt/datadog-agent/bin/agent/agent status
Getting the status from the agent.
=====================
Agent (v6.0.0-beta.5)
=====================
Status date: 2017-12-05 05:12:13.876586 UTC
以下略...
その他、ベータ版のDatadog Agentのインストール、既存のDatadog Agentからの移行方法は以下に記載されているので参考にしてください。
https://github.com/DataDog/datadog-agent/blob/master/docs/beta/upgrade.md
ログの転送機能を有効にするために、 /etc/datadog-agent/datadog.yaml
に以下の一行を追記します。
log_enabled: true
nginxのログを転送する
ここでは例としてnginxのアクセスログをDatadogに転送するようにしてみます。
nginxをインストールし、Datadog Agentがアクセスできるようにnginxのログディレクトリのパーミッションを変えておきます。
[ec2-user@ip-10-0-0-10 ~]$ sudo yum -y install nginx
[ec2-user@ip-10-0-0-10 ~]$ sudo chmod 755 /var/log/nginx/
/etc/datadog-agent/conf.d/nginx.d/conf.yaml
というファイルを以下の内容で作成します。
init_config:
instances:
logs:
- type: file
path: /var/log/nginx/access.log
service: nginx
source: nginx
sourcecategory: http_web_access
- type: file
path: /var/log/nginx/error.log
service: nginx
source: nginx
sourcecategory: http_web_access
Datadog Agentを再起動します。
[ec2-user@ip-10-0-0-10 ~]$ sudo restart datadog-agent
datadog-agent start/running, process 18089
ログを確認してみる
Datadogに転送されたログを確認してみましょう。ログを生成するためにcurlコマンドで適当にアクセスを行いました。
ログが表示されていますね!
ためしに1行のログをクリックしてみます。
TAGS
という欄に見慣れたDatadogのタグが並んでいます。これらは標準で付加されていて、インスタンス名やインスタンスタイプといったタグごとにログをフィルタしたりグルーピングするのに役立ちます。MESSAGE
というところがログの中身です。
そしてATTRIBUTES
という欄はMESSAGE
のログの中身がパースされ、nginxのログが構造化されています!自動でパースしてくれるのはありがたいですね。ログが構造化されているおかげでログから取り出した値をメトリクスにしたりできそうです。
AWS CloudWatch LogsをDatadogに連携させる
CloudWatch Logsの連携も試してみましょう。こちらはホストにAgentをインストールしたりする必要がないので、本番環境に導入して試してみました。
ボタンをポチッと押すだけで自動でログが連携されると便利でよいのですが、連携用のLambda Functionをデプロイする必要があります。デプロイといってもコピペで済みますが。
- CloudWatch Logsにログが上がる
- ログが追加されたのをきっかけにLambda Functionがキックされる
- Lambda Functionで受け取ったログをDatadog APIを叩いて転送する
という流れでデータは連携されます。
PythonのLambda functionを作成し、以下のコードをコピペします。
https://github.com/DataDog/dd-aws-lambda-functions/blob/master/Log/lambda_function.py
環境変数の追加も必要です。DD_API_KEY
というキーに対して、DatadogのAPIキーを値にセットします。
CloudWatch Logsのロググループの一覧から、Datadogに連携させたいアプリケーションのログを選択し、Lambdaサービスへのストリーミングを開始
を押します。その後先程作成したDatadogにログを転送するためのLambda Functionを選択すると連携が完了します。本番運用する時は設定の抜け漏れがないようにTerraform等で自動化できるとよさそうですね。
ちょうどタイミングよくアプリケーションが外部要因のエラーを出した時があり、その時のスクリーンショットがこちらです。エラーログが出力されているのがわかります。今回は自分たちで開発したアプリのログなので、自動でパースはされず、ATTRIBUTES
の中身はCloudWatchLogsのログストリーム名のみしかありませんでした。
severity
という項目にログレベルが、app
という項目でアプリケーション名が入っていますが、これらはこれから紹介するPipelineという機能を使ってログをパースしてattributeとして設定したものです。
Pipeline機能でログを加工する
Pipeline機能の画面はこのようになっています。
上から下へ、ログが入力され、Pipelineで加工、出力されるまでを表しています。NginxというPipelineはNginxのログが流れてきた時にDatadog側で自動で追加され、この機能によってNginxのログが自分で設定を書くことなくパースされたのだと思います。赤く囲った部分が自分で設定した部分です。プリセットのPipelineが豊富だと助かりますね。
1番から3番の順で何をしたのか紹介します。
1番: ログのログレベルを抽出する
アプリケーションログは以下のようなフォーマットで出力され、ログレベルは [ERROR]
や [INFO]
といった文字列で現れます。
17/12/05 14:39:19.045 [akka.actor.default-dispatcher-33] [ERROR] Flow - HTTP Response status code Error: 503 Service Unavailable
Grok Parserというログパーサの方式でパースの設定を書くことができます。
以下は、正規表現で取り出したログレベルをseverity
というキーでattributeに追加するという設定になります。
severity_map .*\[%{regex("OFF|ERROR|WARN|INFO|DEBUG|TRACE|ALL"):severity}\].*
詳細な書式は公式ドキュメントをご覧ください。IPアドレスや日付のパースもできて、だいたいのログはこれを使えばパースできるはずです。
2番: severityを設定する
Log Severity Remapperという機能です。1番でパースしたseverity
という項目をログレベルとして認識させるようにしました。このおかげで severity: ERRORだった場合にエラーログとして認識され、該当ログが赤くなったり、エラーログとしてカウントされたりします。
3番: アプリケーション名をattritubeにする
Attribute Remapperという機能です。この例で言うと、ログと一緒に送られてきた、aws.awslogs.logGroup
というattributeがログ送信元のアプリケーション名を表しているのですが、わかりづらいので、aws.awslogs.logGroup
をapp
というattributeにマッピングしてみました。
アプリケーションの実装を変えずに、ログレベルをマッピングするくらいなら簡単にできて便利でした。パースしなくても良いようにするにはログをJSONで吐くようにする必要があります。
JSONでログを出力しなくても、自前でパース方法さえ定義してあげれば好きなように値が取り出せるのは汎用性があって色々な使い方ができそうです。
To indices: for investigations, alerting & analytics
という部分と、 To archives: for future audits
という部分は選択できず、表示されているだけでしたが、Beta版なので機能がまだ開放されていないということでしょうか。
Pipelineで加工したログを元にアラートを上げる条件を指定したり、アラートとともにエラー内容も一緒に出力したり、S3にログをアーカイブできたりできると良いですね。
感想
まだ軽く触っただけですが、アプリケーションログをいい感じに管理できるツールをここ1年くらい探し求めていたので、がっつり使い始めたらアプリケーションを運用する上で欠かせないツールになりそうです。
Datadogは9月末にLogmatic.ioというログマネジメントサービスの会社を買収していて、 Datadog LogsはLogmatic.ioの機能をDatadogを取り込んだサービスかなと想像しています。今後統合が進むことでより便利になっていくのかなと思います。楽しみです!
明日は k_enoki さんが担当です。3年連続で僕の翌日が k_enoki さんです。よろしくお願いします!