😺

Lambda PowertoolsをChaliceから使用する方法

2023/03/07に公開

1.はじめに

みなさんLambda Powertoolsはご存知でしょうか?Lambda関数用のライブラリで、X-Rayによるトレース、ログ出力、CloudWatchのカスタムメトリクスの作成等々が簡単に実装できる優れモノです。
現在対応している言語はPython、Javaの2つですが、今回はPython向けのサーバレスフレームワークであるChaliceの中でLambda Powertoolsを使う方法を紹介していきたいと思います。
Chalice&Lambda Powertoolsって何やねんという方は、記事の末尾に参考のリンクを貼ってますので興味があればご覧ください。

2.ChaliceからLambda Powertoolsを使う方法

以下、ライブラリのインストールも含め手順を書いていきたいと思います。

2-1.ライブラリのインストール

まずは事前準備として開発環境にChalice、Lambda Powertoolsをインストールします。
シンプルにpipでインストールできます。

$ pip install chalice
$ pip install aws_lambda_powertools

2-2.プロジェクトの作成とコードの記述

まずはChalice用のプロジェクトを作りましょう。以下のコマンドを実行します。
ここでは「lambda_powertools_sample」というプロジェクト名にしましたが、任意の名前でOKです。

$ chalice new-project lambda_powertools_sample

そうすると以下の構成でディレクトリとファイルが生成されます。

lambda_powertools_sample/
├── app.py
├── .chalice
│   └── config.json
└── requirements.txt

requirements.txtを開いて必要なライブラリ定義を追記します。ここではLambda Powertoolsですね。バージョンはご利用環境に合わせて変更してください。

requirements.txt
aws-lambda-powertools==1.21.1

続いてapp.pyを編集します。デフォルトではこのような形です。

app.py
from chalice import Chalice

app = Chalice(app_name='lambda_powertools_sample')

@app.route('/')
def index():
    return {'hello': 'world'}

これをこのように書き換えます。

app.py
from chalice import Chalice
from chalice.app import ConvertToMiddleware    # 追加(1)
from aws_lambda_powertools import Logger       # 追加(1)
from aws_lambda_powertools import Tracer       # 追加(1)

app = Chalice(app_name='lambda_powertools_sample')

logger = Logger()    # 追加(2)
tracer = Tracer()    # 追加(2)
app.register_middleware(ConvertToMiddleware(logger.inject_lambda_context))    # 追加(3)
app.register_middleware(ConvertToMiddleware(tracer.capture_lambda_handler))   # 追加(3)


@app.route('/')
def index():
    logger.debug('Lambda Powertoolsのサンプルです')    # 追加(4)
    return {'hello': 'world'}

ここでやっていることは以下の通りです。
 (1)必要なライブラリのインポート
 (2)ログ出力用のloggerと、X-Rayでトレースするためのtracerを定義
 (3)app.register_middlewareによりミドルウェアの登録を実施
 (4)アプリ側からテスト用のログを出力

さらに、.chalice/config.jsonを更新してX-Rayを有効にします。4行目の「"xray": true」と8行目の「environment_variables」の定義を追加しています。

.chalice/config.json
{
  "version": "2.0",
  "app_name": "lambda_powertools_sample",
  "xray": true,                                                      ※追加
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "environment_variables": {                                     ※追加
        "POWERTOOLS_SERVICE_NAME": "lambda_powertools_sample",       ※追加
        "LOG_LEVEL": "DEBUG"                                         ※追加
      }
    }
  }
}

2-3.動作確認

ではさっそく試してみましょう。以下のコマンドでデプロイを行います。これ一発で必要なLambda関数とAPI Gateway定義が全て作成されます。

$ chalice deploy
Creating deployment package.
Creating IAM role: lambda_powertools_sample-dev
Creating lambda function: lambda_powertools_sample-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:ap-northeast-1:xxxxxxxxx:function:lambda_powertools_sample-dev
  - Rest API URL: https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/

curlコマンドでデプロイ済みのAPIエンドポイントにアクセスします。

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/
{"hello":"world"}

ではちゃんとログが出力されているか確認してみます。

ちゃんと出力されていますね。X-RAyの方はどうでしょうか。

出ていますね。見ての通り、API GatewayやLambdaの実行時間が確認できます。他にもエラー時にその発生元を可視化したり色々できるので、X-RAyを使えばサーバレス開発でのトラブルシューティングが簡単になります。

2-4.サブモジュールからの呼び出し方法

実プロジェクトではapp.pyのみに処理を記述していくだけではなく、サブモジュールに切り出すことも多いかと思います。
この場合の対応方法についても書いてみます。例えば以下のようにサブモジュールを切ったとします。chalicelibディレクトリ配下にserviceLogic.pyを追加した感じですね。

lambda_powertools_sample/
├── app.py
├── .chalice
│   └── config.json
├── .chalicelib            ※追加
│   └── serviceLogic.py    ※追加
└── requirements.txt

サブモジュール(serviceLogic.py)内の処理は、仮にこんな感じだとします。

chalicelib/serviceLogic.py
class ServiceLogic:
    def hogehoge(self):
        # ~~~
        # 何がしかの処理
        # ~~~
        return 'Finish!!'

この場合、サブモジュール側でLambda Powertoolsを使うにはこのように追記すればOKです。

chalicelib/serviceLogic.py
from aws_lambda_powertools import Logger    # 追加
from aws_lambda_powertools import Tracer    # 追加
logger = Logger(child=True)                 # 追加
tracer = Tracer()                           # 追加

class ServiceLogic:
    def hogehoge(self):
        # ~~~
        # 何がしかの処理
        # ~~~
        logger.debug('サブモジュールからの呼び出しサンプル')    # 追加
        return 'Finish!!'

app.py側に処理を追加して、サブモジュールを呼び出すようにしましょう。

app.py
from chalice import Chalice
from chalice.app import ConvertToMiddleware
from aws_lambda_powertools import Logger
from aws_lambda_powertools import Tracer
from chalicelib import serviceLogic                  # 追加

app = Chalice(app_name='lambda_powertools_sample')

logger = Logger()
tracer = Tracer()
app.register_middleware(ConvertToMiddleware(logger.inject_lambda_context))
app.register_middleware(ConvertToMiddleware(tracer.capture_lambda_handler))


@app.route('/')
def index():
    logger.debug('Lambda Powertoolsのサンプルです')
    service = serviceLogic.ServiceLogic()            # 追加
    service.hogehoge()                               # 追加
    return {'hello': 'world'}

ではデプロイして実行結果を見てみましょう。デプロイとcurlでのAPIアクセスは先程と同じです。

$ chalice deploy
$ curl https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/
{"hello":"world"}

ログを見てみましょう。

出てますね。いい感じです。X-RAyの方はどうでしょうか。

こちらはあまり変化はないですね。サブモジュール側の関数(hogehoge)の実行時間が分かりません。
こういった場合はデコレータの「@tracer.capture_method」を使います。このような感じ。

from aws_lambda_powertools import Logger
from aws_lambda_powertools import Tracer
logger = Logger(child=True)
tracer = Tracer()

class ServiceLogic:
    
    @tracer.capture_method    # 追加
    def hogehoge(self):
        # ~~~
        # 何がしかの処理
        # ~~~
        logger.debug('サブモジュールからの呼び出しサンプル') 
        return 'Finish!!'

こうすると関数レベルで実行時間を把握できます。
再度curlでAPIを叩いてX-Rayの画面を見ると、以下の通りhogehoge関数の実行時間が出ています。ステキ。

3.今回使ったライブラリについて

以上でLambda Powertoolsの説明は終わりですが、ご参考まで今回使用したライブラリの紹介記事を共有させて頂きます。

3-1.Chalice

ChaliceはAWSが開発したサーバレスアプリケーション向けのフレームワークで、Python向けのライブラリとして提供されています。API Gateway+LambdaによるオーソドックスなREST APIを始め、色々なサーバレスアプリを爆速で作ることができます。開発効率は他のフレームワーク(SAM、Amplify等々)と比較しても圧倒的です。(個人的感想ですが)
詳しい解説については以下の記事を参照ください。
https://aws.amazon.com/jp/builders-flash/202003/chalice-api/?awsf.filter-name=*all

3-2.Lambda Powertools

Lambda Powertoolsについては、こちらのクラメソさんの記事に詳しく書かれてました。ご参考まで引用させて頂きます。
https://dev.classmethod.jp/articles/aws-lambda-powertools-python/

4.さいごに

今回はChaliceとLambda Powertoolsの連携方法を紹介させて頂きました。
この記事が誰かのお役に立てると幸いです。

Discussion