AWSのサーバーレスコンピューティングサービスであるLambdaは、
ログ管理においてCloudWatch Logsを使用することが一般的です。
しかし、より高度な分析やアラートのために、Datadogなどの外部ログ管理サービスを利用するケースが増えています。
本記事では、Lambda関数のログをDatadogに送信する3つの方法を比較します。
3つの選択肢
AWS LambdaのログをDatadogに送信する主な方法には以下の3つがあります。
- Datadog Forwarder Lambdaを使う方法
- Datadog Lambdaレイヤーを使う方法
- Datadogログ収集APIを直接使う方法
それぞれのポイントを以下でまとめます。
Datadog Forwarder Lambdaを使う方法
- CloudWatch Logsからログを収集し、Datadogに転送する。
- 設定が比較的簡単で、既存のLambda関数に影響を与えない。
- CloudWatch Logsの料金が発生する。
- Datadogの設定が必要。
Datadog Lambdaレイヤーを使う方法
AWS Lambda 拡張機能と言われます。
英語だと、AWS Lambda Extensionsとなります。
- Lambda関数からログをDatadogに直接送信する。
- Lambda関数内でより細かい制御が可能。
- CloudWatch Logsの料金は発生しない。
- Lambda関数の実行時間が若干増加する可能性がある。
- AWSアカウントとDatadogアカウントの統合が必要。
Datadogログ収集APIを直接使う方法
- Lambda関数からDatadogのAPIに直接ログを送信する。
- 最も柔軟性が高く、きめ細かい制御が可能。
- CloudWatch Logsの料金は発生しない。
- Datadog側の設定が最小限。
- Lambda関数の実行時間が増加する可能性がある。
- ネットワーク通信料金が発生する可能性がある(ただし、月間1GBまでは無料)。
詳細は、次の記事で説明しています。
このAPIは、Lambda関数以外からでも利用可能です。
単なるHTTPアクセスに過ぎませんので。
どれを使えばよい?
比較のポイントとしては、以下が考えられます。
- コスト
- 設定の簡単さ
- 柔軟性と制御
「実装の手間」に関しては、ライブラリで吸収できます。
そのため、ここでは考慮外とします。
コスト的には、Datadog Lambdaレイヤーと直接APIを使う方法が有利と言えます。
Datadog Forwarderを利用する方法は、CloudWatch Logsの料金がネックになります。
設定の簡単さは、どうなのでしょうか?
Datadog Forwarderと直接APIがいい勝負ではないでしょうか。
確実に言えるのは、Datadog Lambdaレイヤーを使う方法が面倒だということです。
AWSアカウントとDatadogアカウントの統合が、そこそこ複雑と言えます。

上記ページの作業は、CloudFormationで簡単にできるようになっているらしいです。
でも、CloudFormationがまともに動いているようには思えません。
柔軟性と制御に関しては、直接APIを使う方法が最も柔軟です。
ライブラリの情報もそれなりに充実していると言えます。
では、結局はどれを利用すれば良いのでしょうか?
個人的には、まずはDatadog Lambdaレイヤーを利用する方法は却下です。
AWSアカウントとDatadogアカウントの統合が、面倒過ぎます。
正確には、統合以降の設定に関する情報が少なすぎです。
AWSとDatadogの統合自体は、マニュアル通りにできます。

ただ、それ以降のAWSとDatadogにおける設定に関する情報が少ないのです。
設定できたとしても、またコロコロと変わることが想定されます。
正直、インフラ側の設定で振り回されるのは解せません。
インフラの設定などは、ほぼ恒久的であって欲しいです。
よって、個人的にはDatadog Lambdaレイヤーを使う方法は真っ先に除外対象になります。
また、Datadog Forwarderを利用する方法はコスト的に避けたいです。
以上より、Datadogログ収集APIを直接使う方法がオススメとなります。
ただ、送信データ量があまりに多い場合は考え直す必要があります。
この場合、ネットワーク通信料金に影響が出てきますので。
【動作確認】Datadogログ収集APIを直接使う方法
まずは、以下の記事の内容を試してください。
Lambda上では、次のように環境変数を設定する必要があります。

ライブラリをLambda関数で利用できるようにします。

datadog-api-clientなどの外部ライブラリをLambda関数で利用するための方法は、次の記事で解説しています。
ここまで準備できたら、次のコードを実行してみましょう。
lambda_function.py
import time import json import random from datadog_api_client import ApiClient, Configuration from datadog_api_client.v2.api.metrics_api import MetricsApi from datadog_api_client.v2.model.metric_payload import MetricPayload from datadog_api_client.v2.model.metric_point import MetricPoint from datadog_api_client.v2.model.metric_series import MetricSeries def lambda_handler(event, context): # TODO implement # ランダムにAPIを選択 api_names = ["A", "B"] api_name = random.choice(api_names) # Datadog APIクライアントの初期化 configuration = Configuration() with ApiClient(configuration) as api_client: api_instance = MetricsApi(api_client) # メトリクスデータの作成 series = [ MetricSeries( metric="api.calls", points=[ MetricPoint( timestamp=int(time.time()), value=1.0 ) ], tags=[f"api:{api_name}", "environment:test", "service:api"] ) ] body = MetricPayload(series=series) # メトリクスの送信 response = api_instance.submit_metrics(body=body) print(f"メトリクスの送信結果: {response}") return { 'statusCode': 200, 'body': json.dumps([1]) }
実行して、以下のように表示されたらDatadogへのデータ送信が成功しているはずです。
メトリクスの送信結果: {'errors': []}
あとは、Datadogで確認。