X-Ray トレーシングの実装

AWS のモニタリングとトラブルシューティング

John Q. Martin

Principal Consultant

X-Ray SDK の概要

 

主な特徴:

  • 対応言語:Python、Node.js、Java、.NET、Go、Ruby
  • 2つのアプローチ:自動計装と手動計装
  • SDK は UDP ポート 2000 経由でデーモンと通信
  • X-Ray API とは直接通信しない

 

自動計装と手動計装:

X-Ray SDK の自動計装と手動計装の比較

AWS のモニタリングとトラブルシューティング

Python SDK:Flask のセットアップ

 

from flask import Flask
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware

app = Flask(__name__)

xray_recorder.configure(
    service='MyFlaskApp',
    sampling=True,
    context_missing='LOG_ERROR',
    daemon_address='127.0.0.1:2000'
)

XRayMiddleware(app, xray_recorder)

 

レコーダーの4つの設定:

  • service - サービスマップに表示される名前
  • sampling - サンプリングの有効・無効
  • context_missing - LOG_ERROR でクラッシュを防止
  • daemon_address - セグメントの送信先

ミドルウェアをアタッチすると、すべての受信リクエストが自動的にトレースされます。

AWS のモニタリングとトラブルシューティング

自動計装:Python

 

# Instrument all supported libraries
from aws_xray_sdk.core import patch_all
patch_all()
# Or selectively
from aws_xray_sdk.core import patch
patch(['boto3', 'requests', 'psycopg2'])

 

対応ライブラリ:

boto3、requests、データベースクライアントなど、X-Ray の自動計装が対応するライブラリ

AWS のモニタリングとトラブルシューティング

手動計装:Python

 

デコレーターを使う方法:

@xray_recorder.capture('process_order')
def process_order(order_id):
    order = get_order(order_id)
    return process_payment(order)

 

コンテキストマネージャーを使う方法:

def process_order(order_id):
    with xray_recorder.capture('fetch_order'):
        order = db.query(Order).filter_by(
            id=order_id).first()
    with xray_recorder.capture('process_payment'):
        return payment_service.charge(order.total)
AWS のモニタリングとトラブルシューティング

コードでのアノテーションとメタデータ

 

アノテーションの追加:

xray_recorder.put_annotation(
    'order_id', order_id)
xray_recorder.put_annotation(
    'user_id', user_id)

 

メタデータの追加(詳細な情報):

xray_recorder.put_metadata(
    'order_details',
    {'items': order.items,
     'total': order.total})
  • アノテーションはインデックス化されるが、メタデータはされない
  • アノテーションは型付き、メタデータは任意の JSON
  • フィルタリングにはアノテーション、デバッグ情報にはメタデータを使用
AWS のモニタリングとトラブルシューティング

トレースでのエラーハンドリング

 

def process_order(order_id):
    try:
        order = get_order(order_id)
        payment = process_payment(order)
        return payment
    except PaymentError as e:
        xray_recorder.put_annotation(
            'error_type', 'payment_failed')
        xray_recorder.put_metadata(
            'error_details',
            {'message': str(e), 'order_id': order_id})
        raise

 

  • トレース対象の関数内で発生した例外は自動的にキャプチャされる
  • コンソールでフィルタリングできるよう、エラー種別をアノテーションとして追加する
  • 完全なエラー詳細はメタデータとして追加する
  • アプリのエラーハンドリングを継続するため、必ず例外を再送出する
AWS のモニタリングとトラブルシューティング

Node.js SDK:Express のセットアップ

 

const AWSXRay = require('aws-xray-sdk-core');
const xrayExpress = require('aws-xray-sdk-express');
const app = require('express')();

AWSXRay.config([AWSXRay.plugins.EC2Plugin]);

// Open segment for all incoming requests
app.use(xrayExpress.openSegment('MyExpressApp'));

app.get('/api/orders/:id', async (req, res) => {
    const order = await fetchOrder(req.params.id);
    res.json({ order });
});

// Close segment after response
app.use(xrayExpress.closeSegment());

// Automatic instrumentation
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const https = AWSXRay.captureHTTPs(require('https'));
AWS のモニタリングとトラブルシューティング

Lambda の実装

 

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

patch_all()  # instrument AWS SDK calls

def lambda_handler(event, context):
    xray_recorder.put_annotation(
        'user_id', event['user_id'])

    result = process_user(event['user_id'])

    return {
        'statusCode': 200,
        'body': json.dumps(result)
    }

 

主な特徴:

  • アクティブトレーシングを有効にすると、Lambda は SDK 不要で基本的なトレースを自動送信する
  • サブセグメントの追加、アノテーション、ダウンストリーム呼び出しの計装には X-Ray SDK が必要
  • コンソールで有効化:「設定」→「モニタリングツール」
  • またはテンプレートで:Tracing: Active
AWS のモニタリングとトラブルシューティング

ECS と Fargate:サイドカーパターン

 

タスク構成:

ECS Task
|_ Application Container
|   sends to xray-daemon:2000
|_ X-Ray Daemon Container
    forwards to X-Ray service

アプリコンテナの設定:

xray_recorder.configure(
    service='MyECSApp',
    daemon_address='xray-daemon:2000'
)

 

タスク定義に含まれる内容:

  • デーモンコンテナamazon/aws-xray-daemon イメージ、UDP ポート 2000
  • アプリコンテナ:環境変数 AWS_XRAY_DAEMON_ADDRESS=xray-daemon:2000

サイドカーパターンを使う理由:

  • デーモンがタスクに合わせてスケールする
  • 障害がタスク単位で分離される
AWS のモニタリングとトラブルシューティング

X-Ray デーモンのインストール

プラットフォーム別インストール:

  • Amazon Linux 2
    • sudo yum install -y aws-xray-daemon-3.x.rpm
  • Ubuntu
    • sudo dpkg -i aws-xray-daemon-3.x.deb
  • Windows
    • xray.exe -f cfg.yaml install
  • Docker
    • docker run -p 2000:2000/udp amazon/aws-xray-daemon

インストール後:

sudo systemctl start xray
sudo systemctl enable xray

デーモンの役割:

  • UDP ポート 2000 でリッスン
  • セグメントをバッファリングしてバッチ処理
  • HTTPS 経由で X-Ray API に転送
  • リトライを処理するため、アプリ側での対応は不要
AWS のモニタリングとトラブルシューティング

デーモンの設定

 

TotalBufferSizeMB: 24
Concurrency: 8
Region: "us-east-1"
Socket:
  UDPAddress: "127.0.0.1:2000"
  TCPAddress: "127.0.0.1:2000"
Logging:
  LogLevel: "info"
  LogPath: "/var/log/xray/xray-daemon.log"
LocalMode: false

 

  • バッファサイズは高トラフィック時に増加させる
  • Concurrency は X-Ray への並列接続数を設定する
  • コンテナ環境では UDP アドレスを 0.0.0.0 に設定する
  • ローカル開発で認証情報が不要な場合は LocalMode を true にする
AWS のモニタリングとトラブルシューティング

IAM アクセス許可

 

{
  "Effect": "Allow",
  "Action": [
    "xray:PutTraceSegments",
    "xray:PutTelemetryRecords",
    "xray:GetSamplingRules",
    "xray:GetSamplingTargets",
    "xray:GetSamplingStatisticSummaries"
  ],
  "Resource": "*"
}

 

最も簡単な方法

マネージドポリシー AWSXRayDaemonWriteAccess を使用する

アタッチ先:

  • EC2 インスタンスロール
  • ECS タスクロール
  • Lambda 実行ロール

権限が正しく設定されていない場合、デーモンは動作してもセグメントが送信されずに失敗します。

AWS のモニタリングとトラブルシューティング

デーモンのデプロイパターン

 

インスタンスごと、サイドカー、共有サービスの3つの X-Ray デーモンデプロイパターン

AWS のモニタリングとトラブルシューティング

レッスンのまとめ

 

  • SDKpatch_all() による自動計装、デコレーターとコンテキストマネージャーによる手動計装
  • アノテーション(インデックス化・検索可能)とメタデータ(詳細情報・非インデックス)
  • Lambda:基本トレースは自動送信。サブセグメントとダウンストリーム呼び出しには SDK が必要
  • ECS/Fargate:サイドカーデーモンコンテナパターン
  • デーモン:cfg.yaml で設定、AWSXRayDaemonWriteAccess IAM ポリシーが必要
  • デプロイ:EC2 はインスタンスごと、コンテナはサイドカー
AWS のモニタリングとトラブルシューティング

X-Ray トレーシングの実装

AWS のモニタリングとトラブルシューティング

Preparing Video For Download...