LocalStackを使って AWS CloudWatch Logsを味わってみます。
「LocalStackを使う (AWSエミュレーター)」で AWSのエミュレーター環境を構築し、
「LocalStackで AWSの Lambda」で Lamdaで JavaScriptの関数を実行してみました。
ここではやはり LocalStackでやりますが、Lambdaのところで作った JavaScriptの関数からコンソールに出した「Hello World」を、CloudWatch Logsに格納してみます。
環境はこの通り。
- Ubuntu Server 22.04.2
- Docker Engine - Community 23.0.1
- LocalStack 1.4.0
既に LocalStackは起動している状態からスタートです。
Lambdaで実行したプログラムのログについて、以下のドキュメントにこんな記載があります。
AWS Lambda の Amazon CloudWatch Logs へのアクセス
Lambda 関数のログは、Lambda コンソール、CloudWatch コンソール、AWS Command Line Interface(AWS CLI)、または CloudWatch API を使って表示することができます。
ということで、Lambdaで実行したプログラムがコンソール出力したメッセージは、CloudWatch Logsに記録されてそうなんですよね。
であれば、運用サイドではログを CloudWatch側で見たいものです。
どうにかならないでしょうか。
LocalStackの CloudWatch Logsのドキュメントはこちら。
CloudWatch Logs
具体的なとり方の方法は書いてないですが、やれそうな感じがします。
AWS CLI(awsコマンドのこと)には[logs]ってオプションがありまして、これが ColudWatch Logsのログを見るために使えそうです。
LocakStackでは[awslocal logs]ってことになります。
[aws logs]コマンドのリファレンスはこちら。
logs
ちょっとやってみましょう。
CloudWatch Logsには、ロググループって呼ばれるログの容れ物の観念があります。
Lambdaの説明によると、Lambdaからのログは自動的にロググループができるようになっており、それは[/aws/lambda/
という訳で、まずどんなロググループがあるのか見てみました。
[aws logs describe-log-groups]コマンドを使います。
localstack@UbuntuServer2204-1:~/work/lambda$ awslocal logs describe-log-groups
{
"logGroups": [
{
"logGroupName": "/aws/lambda/my-function",
"creationTime": 1677990183226,
"metricFilterCount": 0,
"arn": "arn:aws:logs:us-east-1:000000000000:log-group:/aws/lambda/my-function",
"storedBytes": 1021
}
]
}
ドキュメントの通りに作られていました。(ピンク色の箇所)
ログを見るコマンドでは、ロググループ以外にログストリーム名というのも必要なようです。
特定のロググループのログストリーム名を取得するのは
[aws logs describe-log-streams]コマンドになります。
localstack@UbuntuServer2204-1:~/work/lambda$ awslocal logs describe-log-streams --log-group-name /aws/lambda/my-function
{
"logStreams": [
{
"logStreamName": "2023/03/05/[$LATEST]eeac4c7021fab1ac718109c1283ef540",
"creationTime": 1677990183236,
"firstEventTimestamp": 1677990183099,
"lastEventTimestamp": 1677990531199,
"lastIngestionTime": 1677990531216,
"uploadSequenceToken": "3",
"arn": "arn:aws:logs:us-east-1:000000000000:log-group:/aws/lambda/my-function:log-stream:2023/03/05/[$LATEST]eeac4c7021fab1ac718109c1283ef540",
"storedBytes": 1021
}
]
}
これでログループ名とログストリーム名が分かりましたので、ログ自体を取ってみましょう。
コマンドは[aws logs get-log-events]です。
localstack@UbuntuServer2204-1:~/work/lambda$ awslocal logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name 2023/03/05/[$LATEST]eeac4c7021fab1ac718109c1283ef540
An error occurred (ResourceNotFoundException) when calling the GetLogEvents operation: The specified log group does not exist
ロググループが無いって言ってますね。
上のコマンドで取ってきたものなのに。
ちょっとハマりましたが、Stack Overflow に同じ悩みをもった人が!
aws logs: The specified log group does not exist
これによりますと、ロググループ名じゃなくてログストリーム名が間違っていて、それに引っ張られて「ロググループが無い」って言ってるらしいのです。
問題の箇所は「$LATEST」の「$」で、これをエスケープしたら解決したってありました。
やってみます。
localstack@UbuntuServer2204-1:~/work/lambda$ awslocal logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name 2023/03/05/[\$LATEST]eeac4c7021fab1ac718109c1283ef540
{
"events": [
{
"timestamp": 1677990183099,
"message": "START RequestId: b6ade401-9ab2-4cfb-8d5a-85094bf13d7c Version: $LATEST",
"ingestionTime": 1677990183246
},
{
"timestamp": 1677990183127,
"message": "2023-03-05T04:23:03.080Z\tb6ade401-9ab2-4cfb-8d5a-85094bf13d7c\tINFO\tHello World!\r",
"ingestionTime": 1677990183246
},
{
"timestamp": 1677990183155,
"message": "END RequestId: b6ade401-9ab2-4cfb-8d5a-85094bf13d7c",
"ingestionTime": 1677990183246
},
{
"timestamp": 1677990183183,
"message": "REPORT RequestId: b6ade401-9ab2-4cfb-8d5a-85094bf13d7c\tDuration: 9.41 ms\tBilled Duration: 10 ms\tMemory Size: 128 MB\tMax Memory Used: 128 MB\t",
"ingestionTime": 1677990183246
},
{
"timestamp": 1677990497287,
"message": "START RequestId: ff8253fe-0200-4e4a-b979-fc769e1622a4 Version: $LATEST",
"ingestionTime": 1677990497323
},
{
"timestamp": 1677990497292,
"message": "2023-03-05T04:28:17.276Z\tff8253fe-0200-4e4a-b979-fc769e1622a4\tINFO\tHello World!\r",
"ingestionTime": 1677990497323
},
{
"timestamp": 1677990497298,
"message": "END RequestId: ff8253fe-0200-4e4a-b979-fc769e1622a4",
"ingestionTime": 1677990497323
},
{
"timestamp": 1677990497304,
"message": "REPORT RequestId: ff8253fe-0200-4e4a-b979-fc769e1622a4\tDuration: 2.52 ms\tBilled Duration: 3 ms\tMemory Size: 128 MB\tMax Memory Used: 128 MB\t",
"ingestionTime": 1677990497323
},
{
"timestamp": 1677990531185,
"message": "START RequestId: b367463c-7843-4276-905b-329c44ed3697 Version: $LATEST",
"ingestionTime": 1677990531216
},
{
"timestamp": 1677990531189,
"message": "2023-03-05T04:28:51.172Z\tb367463c-7843-4276-905b-329c44ed3697\tINFO\tHello World!\r",
"ingestionTime": 1677990531216
},
{
"timestamp": 1677990531194,
"message": "END RequestId: b367463c-7843-4276-905b-329c44ed3697",
"ingestionTime": 1677990531216
},
{
"timestamp": 1677990531199,
"message": "REPORT RequestId: b367463c-7843-4276-905b-329c44ed3697\tDuration: 4.06 ms\tBilled Duration: 5 ms\tMemory Size: 128 MB\tMax Memory Used: 128 MB\t",
"ingestionTime": 1677990531216
}
],
"nextForwardToken": "f/00000000000000000000000000000000000000000000000000000011",
"nextBackwardToken": "b/00000000000000000000000000000000000000000000000000000000"
}
あぁ、出ました出ました。(長くなってしまいましたが…)
「LocalStackで AWSの Lambda」で取得したログと同じものが 1行ずつ分けて取得できています。
[aws logs get-log-events]コマンドには、開始時間/終了時間の指定、文言による指定をする方法(オプション)が用意されていますので、それらを使ってフィルタリングをすると使いやすくなると思います。
以上になります。
AWSの Lambdaではログが CloudWatch Logsに格納されているということを知り、それを CLIで取得できることをお勉強しました。
何となくですがこの感じだと Grafanaあたりで取得できそうな気がします。
そうしたらカッコイイ画面でログ確認をできるかも知れません。