AWS Lambda Powertools for TypeScriptがGAされたので試してみた

2022.07.23

こんにちは、CX事業本部 IoT事業部の若槻です。

このたび、AWS Lambda Powertools for TypeScriptがついにGAされました。

AWS Lambda Powertoolsは、Lambda Functionに対してサーバーレスのベストプラクティスを適用できるユーティリティで、AWS LabsからOSSとして提供されています。

今まではPythonとJavaでのみ提供されており、TypeScriptはbeta release(以下ブログ参照)でしたが、このたびproduct releaseとなりました。

今回は、GAされたこのAWS Lambda Powertools for TypeScriptを早速試してみました。

試してみた

まずはじめに、Lambda FunctionのTypeScriptコードにAWS Lambda Powertoolsを適用する方法は次の3つがあります。

  • Middy middlewareMiddy middleware engineを使う方法。Lambda Functionsに簡単にAWS Lambda Powertoolsを組み込める。
  • Manually:middlewareの追加などを行わない方法。AWS Lambda Powertoolsのきめ細かな制御が可能。
  • Method decoratorTypeScript method decoratorsを使用する方法。クラスを使う場合に有用。

今回はMiddyを使用した実装を試してみます。開発環境にmiddyをインストールしておきます。

npm i @middy/core

Lambda FunctionはAWS CDK(TypeScript)で構築します。

lib/aws-app-stack.ts

import { Construct } from 'constructs';
import { aws_lambda_nodejs, Stack, StackProps } from 'aws-cdk-lib';
import { Tracing } from 'aws-cdk-lib/aws-lambda';

export class AwsAppStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    new aws_lambda_nodejs.NodejsFunction(this, 'logger');
    new aws_lambda_nodejs.NodejsFunction(this, 'tracer', {
      tracing: Tracing.ACTIVE,
    }); //Tracerを使うFunctionはX-Rayの追跡を有効にする
    new aws_lambda_nodejs.NodejsFunction(this, 'metrics');
  }
}

AWS Lambda Powertools for TypeScriptには、次の3つの機能があります。

  • Logger
  • Tracer
  • Metrics

それぞれの機能を試してみます。

Logger

Loggerを使用すると、Lambdaの実行イベントの構造化ログをCloudWatch Logsに出力することができます。

@aws-lambda-powertools/loggerをインストールします。

npm install @aws-lambda-powertools/logger

Lambdaのコードは次のようになります。Loggerを初期化してHandlerで使用します。オプションでaddPersistentLogAttributesを使用すると任意のAttributeを出力ログに含めることができるので、Event Dataはこれを使用してLogに含めるようにすると良さそうです。

lib/aws-app-stack.logger.ts

import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger';
import middy from '@middy/core';

const logger = new Logger({
  logLevel: 'INFO',
  serviceName: 'shopping-cart-api',
});

const lambdaHandler = async (event: unknown): Promise<void> => {
  logger.addPersistentLogAttributes({ event: event });
  logger.info('This is an INFO log with some context');
};

export const handler = middy(lambdaHandler).use(injectLambdaContext(logger));

DeployしたLambda Functionを実行すると、次のEvent Logが出力されました。

log

{
    "cold_start": true,
    "function_arn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:AwsAppStack-loggerE71C1604-7O0zP2rA8iBZ",
    "function_memory_size": 128,
    "function_name": "AwsAppStack-loggerE71C1604-7O0zP2rA8iBZ",
    "function_request_id": "5c4e6be5-870f-487a-a0e8-bc05d44f1d9c",
    "level": "INFO",
    "message": "This is an INFO log with some context",
    "service": "shopping-cart-api",
    "timestamp": "2022-07-23T09:33:23.238Z",
    "xray_trace_id": "1-62dbc062-2b65813062b227f4358eb9c1",
    "event": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}

Tracer

TracerはAWS X-Ray SDK for Node.jsの軽量ラッパーで、Handler実行時のSegment毎のTraceデータをAWS X-Rayに記録できます。

@aws-lambda-powertools/tracerをインストールします。

npm install @aws-lambda-powertools/tracer

Lambdaのコードは次のようになります。

import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer';
import middy from '@middy/core';

const tracer = new Tracer({
  serviceName: 'shopping-cart-api',
});

const lambdaHandler = async (): Promise<void> => {
  /* ... Something happens ... */
};

export const handler = middy(lambdaHandler).use(captureLambdaHandler(tracer));

Lambdaを実行してX-RayのTraceを見ると、index.handlerのSegmentが記録されていますね。

またTracerでは、Handlerの中にサブセグメントを持たせて詳細なTraceを記録することも可能です。詳細は下記をご参考ください。

Metrics

Metricsを使用すると、Lambda実行をカスタムメトリクスとして発行できます。Amazon CloudWatch Embedded Metric Format (EMF)の形式でCloudWatch Logsに出力されたログが非同期でCloudWatch Metricsに発行されます。

@aws-lambda-powertools/metricsをインストールします。

npm install @aws-lambda-powertools/metrics

Lambdaのコードは次のようになります。

lib/aws-app-stack.metrics.ts

import {
  Metrics,
  MetricUnits,
  logMetrics,
} from '@aws-lambda-powertools/metrics';
import middy from '@middy/core';

const metrics = new Metrics({
  namespace: 'serverlessAirline',
  serviceName: 'orders',
});

const lambdaHandler = async (): Promise<void> => {
  metrics.addMetric('successfulBooking', MetricUnits.Count, 1);
};

export const handler = middy(lambdaHandler).use(logMetrics(metrics));

Lambdaを実行すると、CloudWatch LogsにMetricsの情報が記録されています。

log

{
    "_aws": {
        "Timestamp": 1658570601859,
        "CloudWatchMetrics": [
            {
                "Namespace": "serverlessAirline",
                "Dimensions": [
                    [
                        "service"
                    ]
                ],
                "Metrics": [
                    {
                        "Name": "successfulBooking",
                        "Unit": "Count"
                    }
                ]
            }
        ]
    },
    "service": "orders",
    "successfulBooking": 1
}

MetricsのNamespaceを見ると、メトリクスが発行されていることが確認できます。

おわりに

AWS Lambda Powertools for TypeScriptがGAされたので試してみました。

AWS Lambdaのロギングの実装は開発者やプロジェクトによってバラツキがあると思いますが、今後はAWS Lambda Powertoolsに統一されていく流れになるかも知れませんね。

参考

以上