ちょっと話題の記事

[X-Ray] X-Rayを使用して実行時間が長いLambda関数の資料を作成する

2019.05.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

AIソリューション部の平内(SIN)です。

Amazon Connectや、Amazon Alexaでは、Lambda関数を利用できますが、どちらもタイムアウトに制限(8秒)があり、時間内に処理できない場合、サービス側でエラーとなってしまいます。

このタイムアウトは絶対に避けることができないため、もし、処理時間が長くなる(若しくは、その危険性がある)場合、それを考慮した設計が必要になります。

下記は、実行時間が長い処理をSQSで処理するようにした例です。
Amazon ConnectとTwilioの連携

今回は、このような場合に、「何の処理に、どれ位時間がかかるので、このように設計しました」と明確に言うための資料としてX-Rayを簡単に使ってみたのでその記録です。

注:すいません。本記事は、X-Rayの特別な使い方を紹介するようなものではありません。利用手順をまとめただけの個人的な覚書です。

2 手順

今回作業した手順は、以下のとおりです。

  1. トレースの有効化
  2. aws-xray-sdk-coreの利用
  3. サブセグメントの生成(X-Ray対応外のファンクションを使用するため)

(1) トレースの有効化

Lambda関数からX-Rayを使用するには、デバッグとエラー処理のところで、アクティブトレースを有効にしますにチェックします。

(2) aws-xray-sdk-coreの利用

AWSのサービスをトレースするだけなら、aws-xray-sdk-coreaws-sdkをラップするだけです。

const AWSXRay = require('aws-xray-sdk-core');
var AWS = AWSXRay.captureAWS(require('aws-sdk'));

(3) サブセグメントの生成

AWSのサービス以外をトレースしたい場合は、サブセグメントを生成して囲みます。

const seg = AWSXRay.getSegment();
const subsegment = AWSXRay.getSegment().addNewSubsegment('Twillo');
// ここに計測したいファンクションを記述する
subsegment.close();

3 対象コード

サンプルで準備したコードは、以下のようなものです。

Connectから呼び出されるLambda関数をイメージしています。

  1. 電話番号をDynamoDBに記録する
  2. メッセージ文の雛形をS3から取得する
  3. SMSを送信する(Twilio)
const AWSXRay = require('aws-xray-sdk-core');
var AWS = AWSXRay.captureAWS(require('aws-sdk'));

exports.handler = async (event) => {

    const phoneNumber = event.phoneNumber;

    // DynamoDBに電話番号を記録する
    const tableName = 'x-ray-sample';
    const promaryKey = phoneNumber;
    const value = (new Date()).toString();
    await dynamoDbPut(tableName, promaryKey, value);

    // S3からSMSの本文取得する
    const bucket = 'x-ray-sample';
    const key = 'sms-message.txt';
    const data = await s3GetObject(bucket, key);
    const body = data.Body.toString("utf-8");

    // TwilioでSMS送信する
    const seg = AWSXRay.getSegment();
    const subsegment = AWSXRay.getSegment().addNewSubsegment('Twillo');
    const result = await createSMS(phoneNumber, body);
    console.log(result);
    subsegment.close();
};

async function s3GetObject(bucket, key) {
    var s3 = new AWS.S3();
    var params = {
        Bucket: bucket,
        Key: key
    };
    return await s3.getObject(params).promise();
}

async function dynamoDbPut(tableName, promaryKey, value) {
    const client = new AWS.DynamoDB.DocumentClient();

    let item = {
        "id": promaryKey,
        "value": value
    }
    var param = {
        TableName : tableName,
        Item: item
    };
    return await client.put(param).promise();
}

async function createSMS(to_number, body) {

    const account_sid = process.env.Sid;
    const auth_token = process.env.Token;
    const from_number = process.env.FromNumber;

    const client = require('twilio')(
        account_sid,
        auth_token
    );

    return new Promise( (resolve, reject) => {
        client.messages.create({
            from: from_number,
            to: to_number,
            body: body
        })
        .then(response => {
            console.log(response);
            resolve(response.id);
        })
        .catch( error => {
            reject(error);
        })
    })
}

4 トレースの確認

X-RayのコンソールからTraceを選択し、適当な時間(過去、何分前までのものを検索対象とするか)を指定して更新すると、Traceリストに1回の実行が1行となって表示されます。

トレースを選択すると、その内容が確認できます。

TwilioのSMS送信処理で、12.3sかかっていることが分かります。この結果から、Twilioのレスポンスによって「送信しました/送信に失敗しました」のようなアナウンスを返す実装は不可能であることが分かります。

5 AWS_XRAY_CONTEXT_MISSING

実際の計測は、Lambdaの実行環境で行なうため、問題とならないのですが、デバッグ等のため、コードをローカルで実行しようとすると、下記のエラーが出ます。

Error: Failed to get the current sub/segment from the context.

このエラーは、AWS_XRAY_CONTEXT_MISSINGという環境変数が設定されていない事が原因のようです。

実環境で動作させると、LOG_ERRORという環境変数がセットされていることが確認できます。

console.log('AWS_XRAY_CONTEXT_MISSING=' + process.env.AWS_XRAY_CONTEXT_MISSING);
AWS_XRAY_CONTEXT_MISSING=LOG_ERROR

実際にローカルの実行環境で環境変数を設定するか、若しくは、下記のコードでこの問題を回避できます。

AWSXRay.setContextMissingStrategy('LOG_ERROR');

7 最後に

今回は、時間制限のある要件で、時間を要する処理があった場合に、その状況を把握して表現する方法としてX-Rayを使用してみました。

軽易に、使えるようにして、資料作成等に利用できるようしたいと思います。

8 参考リンク


ローカルで X-Ray デーモンを実行する
AWS X-Rayによるアプリケーションの分析とデバッグ
AWS Black Belt Online Seminar 「 AWS X-Ray」 資料及びQ&A公開
AWS X-Ray を使用する
AWS Lambda および AWS X-Ray