X-RayでLambdaに注釈やカスタムメタデータを付与する
Posted On 2024-12-29
Lambda関数にX-Rayを導入し、注釈やカスタムメタデータを付与して環境変数や実行時間を記録する方法をまとめています。boto3を使ったトレースログの取得コード例も含め、実際のJSONデータの中身を確認できることを紹介しています。
目次
はじめに
- X-RayはLambdaなどプロファイリングに便利
- いくつかLambdaや実験、試行をしたときに実験条件をX-Rayのログと紐づけておきたい
- 環境変数の値や実行時間をカスタムメタデータとしてX-Rayに書き出す方法を考える
流れ
- 下の記事の続きとして書く。下はLambdaにX-RayをつけてOpenAIへのリクエストをプロファイリングしたもの
- 基本にX-RayのSDKの
patch_all
をやっただけで、独自の値(カスタムメタデータ、注釈)は付与していない - これに注釈とカスタムメタデータを付与して確認する
Lambda側のコード
import datetime
import os
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
# X-Ray SDK をパッチ
patch_all()
def lambda_handler(event, context):
xray_recorder.begin_subsegment('custom_metadata')
# カスタムの注釈を追加
xray_recorder.put_annotation('LambdaName', context.function_name)
xray_recorder.put_annotation('RequestId', context.aws_request_id)
# カスタムメタデータの追加
xray_recorder.put_metadata('Environment', os.environ.get('SAMPLE_VALUE'))
xray_recorder.put_metadata('RequestTime', datetime.datetime.now(datetime.timezone.utc).isoformat())
xray_recorder.end_subsegment()
user_input = event['user_input']
これだけでOK。セグメント区切ってメタデータ(put_metadata
)や注釈(put_annotation
)入れる感じ
X-Rayの画面ではどうなるのか
注釈
メタデータ
コピペのUIがついているのは注釈のほうらしい。
X-Rayトレースの生データ
生データは以下のようなJSONになっている(一部をChatGPTでマスクしている)。custom_metadata
に値が入っているが、そもそものLambdaの実行時間も入っていた。
{
"Id": "1-00000000-000000000000000000000000",
"Duration": 2.625,
"LimitExceeded": false,
"Segments": [
{
"Id": "1111111111111111",
"Document": {
"id": "1111111111111111",
"name": "dummy_lambda_with_xray",
"start_time": 1735396609.303078,
"trace_id": "1-00000000-000000000000000000000000",
"end_time": 1735396610.565696,
"parent_id": "2222222222222222",
"aws": {
"cloudwatch_logs": [
{
"log_group": "/aws/lambda/dummy_lambda_with_xray"
}
]
},
"annotations": {
"aws:responseLatency": 1261.368,
"aws:runtimeOverhead": 0.593,
"aws:responseDuration": 0.085
},
"origin": "AWS::Lambda::Function",
"subsegments": [
{
"id": "3333333333333333",
"name": "Request openai",
"start_time": 1735396609.302849,
"end_time": 1735396610.562036,
"in_progress": false,
"namespace": "local"
},
{
"id": "4444444444444444",
"name": "Init",
"start_time": 1735396608.2226489,
"end_time": 1735396609.298255
},
{
"id": "5555555555555555",
"name": "custom_metadata",
"start_time": 1735396609.3024364,
"end_time": 1735396609.3025641,
"in_progress": false,
"annotations": {
"RequestId": "00000000-0000-0000-0000-000000000000",
"LambdaName": "dummy_lambda_with_xray"
},
"metadata": {
"default": {
"Environment": "5",
"RequestTime": "2024-12-28T14:36:49.302518+00:00"
}
},
"namespace": "local"
},
{
"id": "6666666666666666",
"name": "Overhead",
"start_time": 1735396610.563,
"end_time": 1735396610.563593
}
]
}
},
{
"Id": "2222222222222222",
"Document": {
"id": "2222222222222222",
"name": "dummy_lambda_with_xray",
"start_time": 1735396607.943,
"trace_id": "1-00000000-000000000000000000000000",
"end_time": 1735396610.568,
"http": {
"response": {
"status": 200
}
},
"aws": {
"request_id": "00000000-0000-0000-0000-000000000000"
},
"origin": "AWS::Lambda",
"resource_arn": "arn:aws:lambda:ap-northeast-1:111111111111:function:dummy_lambda_with_xray"
}
}
]
}
boto3からJSONを取得
実験を行ったあとに、そのログをローカルからダウンロードするにはどうしたらいいのだろうか? 雑なコードであるが、以下のようにすればできた。
import boto3
import json
import datetime
def main():
# クライアントの初期化
session = boto3.Session(profile_name="hogehoge")
xray = session.client('xray')
# 取得する期間を設定(例: 過去1時間)
end_time = datetime.datetime.now(datetime.timezone.utc)
start_time = end_time - datetime.timedelta(hours=2)
# トレースのサマリーを取得
response = xray.get_trace_summaries(
StartTime=start_time,
EndTime=end_time,
# 必要に応じてフィルターを追加
)
trace_ids = [trace['Id'] for trace in response.get('TraceSummaries', [])]
if not trace_ids:
print("No traces found for the specified time range.")
return
# トレースデータを取得
traces_response = xray.batch_get_traces(TraceIds=trace_ids)
traces = traces_response.get('Traces', [])
# JSON形式にシリアライズ
traces_json = json.dumps(traces, default=str)
print(traces_json)
if __name__ == "__main__":
main()
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー