初めに
昨日AWS Lambdaにログ形式やログレベルのコントロールといった指定が可能なアップデートが行われました。
機能については既に別の方が記事を書かれているため大枠としてはこちらをご参照ください。
本日リリースされたAWS SAM CLIv1.103.0
が既にこちらの機能に対応していたのでせっかくなのでSAMでも試してみます。
SAMテンプレート作成
今回新たにAWS::Serverless::Functionに追加されたLoggingConfig
で設定可能です。
また今回のアップデートでsam init
に--structured-logging
オプションが追加されておりこちらを指定することでログフォーマットデフォルトでJSON形式としたテンプレートが生成されるようになっております。
sam init
実行時にこのオプションを付与したsam-app-structed
プロジェクトと、このオプションを未指定(--no-structured-logging
指定と同等)を比較すると以下の差分が確認できます。
(そのほかにも名前とダブルクォートの有無はありますが実質的な差はありません)
$ diff -ubBr sam-app-no-structed sam-app-structed
...
+ # You can add LoggingConfig parameters such as the Logformat, Log Group, and SystemLogLevel or ApplicationLogLevel. Learn more here https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-loggingconfig.
+ LoggingConfig:
+ LogFormat: JSON
...
ちなみにsam init --structured-logging
で生成した場合この設定はGlobalsセクションに書き込まれるようです。
template.yml
...
Globals:
Function:
Timeout: 3
# You can add LoggingConfig parameters such as the Logformat, Log Group, and SystemLogLevel or ApplicationLogLevel. Learn more here https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-loggingconfig.
LoggingConfig:
LogFormat: JSON
...
もう少し色々書き加えていい感じにログを調整できるようにしてみます。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
AppLogLevel:
Type: string
Default: WARN
AllowedValues:
- FATAL
- ERROR
- WARN
- INFO
- DEBUG
- TRACE
Globals:
Function:
Timeout: 10
LoggingConfig:
LogFormat: JSON
ApplicationLogLevel: !Ref AppLogLevel
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs20.x
Architectures:
- x86_64
LoggingConfig:
LogGroup: /aws/lambda/blog/structed-log-sample
3種類のログレベルでの出力を用意しておきます。
app.mjs
export const lambdaHandler = async (event, context) => {
console.debug("Im DEBUGGING log")
console.warn("Im WARNING log")
console.error("Im ERROR log")
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'hello world',
})
};
return response;
};
実行
SAMテンプレートとデプロイ側のみの対応かなと思っていたのですが既にlocal invoke
の方も対応しているようです。
(ただ追加された処理がほとんど引数の追加とテンプレートの変換くらいなのでコンテナ側で何かやってる気がします)
レベルを変えて出力を試してみます。
% sam local invoke
...
START RequestId: e48c8dcd-f6df-4ef2-9c1e-93224eed7900 Version: $LATEST
{"timestamp":"2023-11-17T11:17:12.419Z","level":"WARN","requestId":"e48c8dcd-f6df-4ef2-9c1e-93224eed7900","message":"Im WARNING log"}
{"timestamp":"2023-11-17T11:17:12.434Z","level":"ERROR","requestId":"e48c8dcd-f6df-4ef2-9c1e-93224eed7900","message":"Im ERROR log"}
% sam local invoke --parameter-overrides AppLogLevel=ERROR
...
START RequestId: 8b1ed350-cc79-4fe7-bee9-f56abe6b748d Version: $LATEST
{"timestamp":"2023-11-17T11:15:15.482Z","level":"ERROR","requestId":"8b1ed350-cc79-4fe7-bee9-f56abe6b748d","message":"Im ERROR log"}
END RequestId: 8b1ed350-cc79-4fe7-bee9-f56abe6b748d
sam local invoke --parameter-overrides AppLogLevel=DEBUG
...
START RequestId: d21dc300-2c59-43c1-b4a4-beaeb1a41fd3 Version: $LATEST
{"timestamp":"2023-11-17T11:15:48.530Z","level":"DEBUG","requestId":"d21dc300-2c59-43c1-b4a4-beaeb1a41fd3","message":"Im DEBUGGING log"}
{"timestamp":"2023-11-17T11:15:48.545Z","level":"WARN","requestId":"d21dc300-2c59-43c1-b4a4-beaeb1a41fd3","message":"Im WARNING log"}
{"timestamp":"2023-11-17T11:15:48.546Z","level":"ERROR","requestId":"d21dc300-2c59-43c1-b4a4-beaeb1a41fd3","message":"Im ERROR log"}
debugオプションをつけて流したりしてみましたがLogGroup
の設定を変えてもlocal invoke
では何か起きるみたいのはなさそうです。
終わりに
欲しいログレベルというのは環境によって違うものかと思いますので今回のようにログレベルが調整できるようになったのは非常に嬉しいアップデートです。
またJSON形式となったことでよりCloudWatch Logs Insightとの親和性もより良くなったのではないでしょうか。
特にSAMを利用している環境であればGlobalsセクションをうまく活用することでリソースごとに設定を記載せずともログレベルを一箇所の設定値でまとめて管理し、必要に応じて部分的に上書きということが可能ですのでうまく活用して冗長な書き方を減らしていきましょう。