😊

AWS LambdaのCloudWatchログへの記録にはリクエストIDをつけようと思う(Pythonでの実装)

2023/06/22に公開

はじめに


AWS Lambdaで、手間を掛けずに簡単に出力するのであれば難しいライブラリ等を使わなくてもprint()を使えばCloudWatchログへ記録されて確認できますが、単一アプリケーションとしてLambdaを実装し、ルーティングして処理を実行する場合(API Gatewayから入る複数のAPIを1つのLambda関数でメソッドやIDで振り分けて処理するなど)などに問題となるのが、『ログが入り乱れる』件ですよね。
そこで、ログ記録の際にリクエストIDをつけると障害発生時にトレースしやすくなるので実装しました。サンプルコードも載せてます。

リクエストIDってなに

Lambda で関数が実行されると、コンテキストオブジェクトがハンドラーに渡されます。
このプロパティで提供されているリクエストIDのことです。

このリクエストIDをログにつける

このリクエストIDを自身のアプリケーションが出力するログにもつけておいてあげることで、
障害発生時にトレースしやすくなります。

ログ出力処理の実装

ログ出力処理実装のサンプルです。
inspectでファイル名、関数名、行数を取得して同時に記録してます。

common.py
import os
import inspect

class SampleLog:
    '''ロケーションデータをまとめる'''
    pass
def get_location():
    '''ファイル名、関数名、行数を返す関数'''
    location = SampleLog()
    frame = inspect.currentframe().f_back
    location.filename = os.path.basename(frame.f_code.co_filename)
    location.name = frame.f_code.co_name
    location.lineno = frame.f_lineno
    return location
def save_log(requestid,location,*args):
    '''与えられたパラメタでprintする関数'''
    print("[{}][{} {}() L{}]{}".format(requestid,location.filename,location.name,location.lineno,args))

呼び出し元

sample.py
loginfo = "[Exception:DoesNotExist]userid:{}, todid:{}, e:{}".format(request.userid,request.todoid, e)
common.save_log(context.aws_request_id,common.get_location(),loginfo)

context.aws_request_idはselfとかに入れておいてgetする形で使った方が良いですね。

ログ出力例

リクエストIDでフィルタすると絞り込めます。

けっこう良くないですか?

最後に

AWS LambdaのCloudWatchログへの記録時にリクエストIDをつける方法を紹介しました。
書いている途中で思ったのですが、CloudWatchログのログイベントのフィルターでリクエストIDで絞り込めたらこんなことしなくていいですね。。。
見た限りできなさそうでですが。その辺り調べて分かり次第、追記します。

参考

Discussion