こしあん
2024-12-29

X-RayでLambdaに注釈やカスタムメタデータを付与する


5{icon} {views}

Lambda関数にX-Rayを導入し、注釈やカスタムメタデータを付与して環境変数や実行時間を記録する方法をまとめています。boto3を使ったトレースログの取得コード例も含め、実際のJSONデータの中身を確認できることを紹介しています。

はじめに

  • X-RayはLambdaなどプロファイリングに便利
  • いくつかLambdaや実験、試行をしたときに実験条件をX-Rayのログと紐づけておきたい
  • 環境変数の値や実行時間をカスタムメタデータとしてX-Rayに書き出す方法を考える

流れ

  • 下の記事の続きとして書く。下はLambdaにX-RayをつけてOpenAIへのリクエストをプロファイリングしたもの
  • 基本にX-RayのSDKのpatch_allをやっただけで、独自の値(カスタムメタデータ、注釈)は付与していない
  • これに注釈とカスタムメタデータを付与して確認する

LambdaのX-Rayを試す

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の中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です