X-Ray Analyticsで実行ユーザーを表示させてデータをフィルタリングする方法

記事タイトルとURLをコピーする

こんにちは!サーバーワークスの松井です。

今回は、X-Ray Analytics画面にてUSERを表示させてデータをフィルタリングする方法について、紹介したいと思います。

USERとは

X-Rayは、トレーシングするプログラムを実行する際に、プログラムを実行するユーザーをデータに取り込んだ上でデータ送信することができます。

AWS X-Ray Analytics コンソールとのやり取り - AWS X-Ray

そうすることで、X-Rayのコンソール画面で確認する際に、USERの値によってフィルタリング検索することができるので、実行プログラムの状況を比較検証したりすることができます。

前提条件

本ブログは、このブログの延長戦になりますので、以下を実施してからご覧ください。

blog.serverworks.co.jp

実施方法

USERデータを送信するためには、セグメントにUSERのフィールドを取り込む必要があります。 

X-Ray SDK for Python を使用してセグメントに注釈とメタデータを追加する - AWS X-Ray

ローカル環境のプログラムに追記してみます。 

execute_lambda.py

import json
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch 
 
patch(['boto3'])
client = boto3.client('lambda') 
 
 
def main(event, context):
    document = xray_recorder.current_segment()
    document.set_user("U12345")
    data = {
                "id": "device_a",
                "data": [
                    {
                        "id": 0,
                        "temperature": 10
                    }
                ]
            }    
 
    #Lambdaを実行
    client.invoke(
        FunctionName='put-dynamodb',
        InvocationType='RequestResponse',
        LogType='Tail',
        Payload= json.dumps(data)
    ) 
 
    return
 
 
if __name__ == '__main__':
    xray_recorder.begin_segment("local-x-ray")
    main(None, None)
    xray_recorder.end_segment()
 

この状態で実行すると以下の用にUSER画面に送信データが表示されます。 

f:id:swx-matsui:20220407134600p:plain

次に、Lambda側のプログラムでも同様にできるか試してみます。 

先程と同様にプログラムに追記してみます。

put-dynamodb.py

from aws_xray_sdk.core import patch_all 
from aws_xray_sdk.core import xray_recorder
 
import boto3 
 
dynamodb = boto3.resource('dynamodb') 
 
patch_all()  
 
 
def lambda_handler(event, context) -> None:
    document = xray_recorder.current_segment()
    document.set_user("U12345")
    items = []
    items.append(event)
    table = dynamodb.Table("accept_data")
    with table.batch_writer() as batch:
        for data in items:
            batch.put_item(Item=data)
 

するとエラーが発生します。

"errorMessage": "FacadeSegments cannot be mutated.", "errorType": "FacadeSegmentMutationException",.....

このエラーの原因は、LambdaでX-Rayを有効にしている場合は、セグメントに対してコードからは関与できないことに起因します。

AWS Lambda と AWS X-Ray - AWS X-Ray

Lambda 関数とウェブアプリケーションの計測のもう 1 つの違いは、Lambda が作成して X-Ray に送信するセグメントは、関数コードで変更できないことです。サブセグメントを作成し、そこに注釈とメタデータを記録できますが、親セグメントに注釈とメタデータを追加することはできません。

サブセグメントを作成したらどうなるでしょうか。

サブセグメントは、コード内の特定の関数の状態についてより詳細に見ることができるセグメントと親子関係にあるような概念です。

AWS X-Ray の概念 - AWS X-Ray 

コードを以下に変更して実行してみます。   

    document = xray_recorder.current_subsegment()
    document.set_user("U12345")

実行するとこちらもエラーとなります。

[ERROR] AttributeError: 'Subsegment' object has no attribute 'set_user'

set_userは、サブセグメントに対応していないようです。 

以下のドキュメントを見ますと、セグメントは、userフィールドをオプションで入れることができるのに対して、サブセグメントには、userフィールドがないのでサブセグメントには、userを入れ込めないことを確認できます。

AWS X-Ray セグメントドキュメント - AWS X-Ray

注釈機能では、どうでしょうか。 USER画面に表示させることはできないですが、注釈データでuserを自分で設定することでuserをフィルタリングすることができるはずです。

put-dynamodb.py

from aws_xray_sdk.core import patch_all 
from aws_xray_sdk.core import xray_recorder
 
import boto3 
 
dynamodb = boto3.resource('dynamodb') 
 
patch_all()  
 
@xray_recorder.capture('lambda_event')
def lambda_handler(event, context) -> None:
    document = xray_recorder.current_subsegment()
    document.put_annotation('user', 'U12345')
    items = []
    items.append(event)
    table = dynamodb.Table("accept_data")
    with table.batch_writer() as batch:
        for data in items:
            batch.put_item(Item=data)
 

こちらは、実行は成功しました。

生データをみてみるとサブセグメントの欄にuserが入っていることが確認できます。

"subsegments": [
    {
        "id": "xxxxxxx",
        "name": "lambda_event",
        "start_time": 1649300985.0695126,
        "end_time": 1649300985.3674273,
        "in_progress": false,
        "annotations": {
            "user": "U12345"
        },

検索をかけてみます。

annotation.user = "U12345"

該当するユーザーでフィルタリングすることができました。

f:id:swx-matsui:20220407143754p:plain

結論

セグメントにコードから関与できるローカル環境では、X-Ray Analyticsで実行ユーザーを表示させることができました。  

Lambdaでは、セグメントにコードから関与できないのでUSERのダッシュボードに実行ユーザーを表示させることはできませんが、サブセグメントと注釈を使うことで同等のフィルタリング機能を使うことができるので是非Lambdaで使う場合にはこちらを試してみてください。

松井 宏司

アプリケーションサービス部

AWS認定11冠

プロレスをこよなく愛する