Powertools for AWS Lambda (TypeScript) の Logger で service(サービス名)を指定したみた

2024.02.14

こんにちは、CX 事業本部製造ビジネステクノロジー部の若槻です。

Powertools for AWS Lambda (TypeScript) の Logger を使用すると、Lambda の呼び出しイベントやコンテキストなどのフィールドを追加した構造化ログの出力を実装することができます。

今回は、この Powertools for AWS Lambda (TypeScript) の Logger で service(サービス名) フィールドを指定してみました。

試してみた

パッケージインストール

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

npm i @aws-lambda-powertools/logger

CDK コード

必要なリソースを AWS CDK(TypeScript)で作成します。

lib/cdk-sample-stack.ts

import {
  aws_lambda,
  aws_logs,
  aws_lambda_nodejs,
  Stack,
  RemovalPolicy,
  CfnOutput,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';

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

    const logGroup = new aws_logs.LogGroup(this, 'SampleFuncGroup', {
      removalPolicy: RemovalPolicy.DESTROY,
    });

    new CfnOutput(this, 'LogGroupName', {
      value: logGroup.logGroupName,
    });

    const sampleFunc = new aws_lambda_nodejs.NodejsFunction(
      this,
      'SampleFunc',
      {
        architecture: aws_lambda.Architecture.ARM_64,
        runtime: aws_lambda.Runtime.NODEJS_20_X,
        logGroup,
      }
    );

    new CfnOutput(this, 'SampleFuncName', {
      value: sampleFunc.functionName,
    });
  }
}

サービス名を指定しない場合

まずは、serviceName を指定しない場合のログ出力を確認してみます。次のように Lambda ハンドラー内で Logger の初期化をデフォルトの設定で行います。

lib/cdk-sample-stack.sampleFunc.ts

import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

export const handler = (): void => {
  logger.info('Hello, world!');
};

Lambda 関数を含むリソースを CDK でデプロイして、関数を実行します。

npx cdk deploy --require-approval never --method=direct

aws lambda invoke --function-name ${sampleFuncName} outputfile.txt

CloudWatch Logs のロググループに構造化ログが出力されました。

ログの内容を見ると service というフィールドがありますが、serviceName を指定しない場合は service_undefined となってしまいます。

{
    "level": "INFO",
    "message": "Hello, world!",
    "service": "service_undefined",
    "timestamp": "2024-02-13T15:49:10.449Z",
    "xray_trace_id": "1-65cb8f76-0911c4d61b76ff6f6ed72378"
}

サービス名をハンドラー内で直接指定した場合

Lambda ハンドラーのコードを次のように修正します。Logger の初期化時に serviceName プロパティでサービス名を直接指定します。

lib/cdk-sample-stack.sampleFunc.ts

import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger({
  serviceName: 'SampleApp',
});

export const handler = (): void => {
  logger.info('Hello, world!');
};

リソースを CDK でデプロイして、関数を実行します。

npx cdk deploy --require-approval never --method=direct

aws lambda invoke --function-name ${sampleFuncName} outputfile.txt

CloudWatch Logs のロググループに構造化ログが出力されました。

ログの内容を見ると、今度は service フィールドに SampleApp が設定されています。

{
    "level": "INFO",
    "message": "Hello, world!",
    "service": "SampleApp",
    "timestamp": "2024-02-13T16:08:38.375Z",
    "xray_trace_id": "1-65cb9406-1ac973503ed30e6f058946a4"
}

サービス名をハンドラー内で直接指定して、出力ログ内の service フィールドを設定することができました。

サービス名を環境変数で指定した場合

もう一つのサービス名の指定方法として、Lambda 関数の環境変数で指定する方法があります。

Lambda 関数のコードを次のように修正します。CDK のコードで Lambda 関数の environment プロパティで POWERTOOLS_SERVICE_NAME を指定します。

lib/cdk-sample-stack.sampleFunc.ts

    const sampleFunc = new aws_lambda_nodejs.NodejsFunction(
      this,
      'SampleFunc',
      {
        architecture: aws_lambda.Architecture.ARM_64,
        runtime: aws_lambda.Runtime.NODEJS_20_X,
        logGroup,
        environment: {
          POWERTOOLS_SERVICE_NAME: 'SampleApp2', // サービス名を環境変数で指定
        },
      }
    );

Lambda 関数のコードははじめのものに戻します。

lib/cdk-sample-stack.sampleFunc.ts

import { Logger } from '@aws-lambda-powertools/logger';

const logger = new Logger();

export const handler = (): void => {
  logger.info('Hello, world!');
};

リソースを CDK でデプロイして、関数を実行します。

npx cdk deploy --require-approval never --method=direct

aws lambda invoke --function-name ${sampleFuncName} outputfile.txt

CloudWatch Logs のロググループに構造化ログが出力されました。

ログの内容を見ると、今度は service フィールドに SampleApp2 が設定されています。

{
    "level": "INFO",
    "message": "Hello, world!",
    "service": "SampleApp2",
    "timestamp": "2024-02-13T16:36:59.298Z",
    "xray_trace_id": "1-65cb9aaa-2b6be5ea390f5cd154b88078"
}

サービス名を環境変数で指定して、出力ログ内の service フィールドを設定することができました。

おわりに

Powertools for AWS Lambda (TypeScript) の Logger で service(サービス名)フィールドを指定してみました。

同じ AWS アカウント上に複数のサービスがある場合や、ログを外部に転送する場合は、サービス名を指定しておくとクエリをする際に役立ちます。

また設定方法は環境変数による方法の方が、パラメーターとして外部から注入できるので開発時の取り回しが便利になると思います。

参考

以上