bunyanでAWS Lambdaを使ったAPIのログをCloudWatch Logsでフィルターしやすくする
AWS Lambdaのログ、どのように取得されていますか? Node.jsを使っている場合、一番てっとり早いのはconsole.logで記録することです。 console.logに頼るとつらい点 console.logで […]
目次
AWS Lambdaのログ、どのように取得されていますか?
Node.jsを使っている場合、一番てっとり早いのはconsole.log
で記録することです。
console.logに頼るとつらい点
console.log
でログを取るようにすると、CloudWatch Logsから調べるのが少し厄介です。
この関数はただ純粋にログを出すだけなので、「何がどれのログか」が拾いにくいという点があります。
また、JSONがはいるのかstringで入るのかなども特に決まっていないので、実装者によってログのフォーマットが変わるなどの問題もあります。そうなるともうCloudWatch Logsで頑張って目グレップするか、Elasticsearchあたりに投げ込んで思いっきり検索回すかしかないかなと思います。
bunyanを試している理由
bunyanはJSON形式でログを取ることができるライブラリです。
// import
const bunyan = require('bunyan');
// setup logger
const log = bunyan.createLogger({name: 'myapp'});
// log
log.info('hi');
このように使うと、JSON形式でログがでます。
{"name":"myapp","hostname":"banana.local","pid":40161,"level":30,"msg":"hi","time":"2013-01-04T18:46:23.851Z","v":0}
bunyanとCloudWatch Logsは相性が良い。たぶん
bunyanはJSON形式でログを残します。そしてCloudWatch LogsにはJSONメトリクスフィルターがあります。
と、いうことはbunyanでログを残すようにすればCloudWatch Logsでフィルターがしやすくなる(はず)です。
APIバックエンドでのロギング
複数回同時にAPIへアクセスきた場合、それぞれのログが1つのストリームにまとめて記録されることがあります。
そうなると、1行ずつどのリクエストのものか確認しないといけなくなり、なかなか大変です。
そこでbunyanを使う場合は、request idを記録するようにしてやります。
import { APIGatewayProxyHandler } from 'aws-lambda'
import * as bunyan from 'bunyan'
import * as bunyanFormat from 'bunyan-format'
/**
* Default configuration
**/
const defaultOptions: Partial<bunyan.LoggerOptions> = {
level: 'debug',
stream: new bunyanFormat({
outputMode: 'bunyan',
levelInString: true
}),
}
/**
* Create logger
**/
const createBunyanLogger = (opts?: bunyan.LoggerOptions): bunyan => {
const logger = bunyan.createLogger({
...defaultOptions,
...opts
})
return logger
}
export const handler: APIGatewayProxyHandler = async (event) => {
const logger = createBunyanLogger({
name: 'MyTestAPI',
requestId: event.requestContext.requestId
})
logger.info(event)
return {
statusCode: 200,
body: JSON.stringify({message: 'Hello'})
}
}
上のサンプルでは、requestId
というパラメタをカスタムで追加しています。これはCloudWatch Logsでのメトリクスフィルタを使う際に利用します。
記録したログを見る
上記のサンプルのような形でログを取ることで、APIリクエスト毎にメトリクスを見ることができます。
CloudWatch LogsやRollbarなどでしらべたいリクエストのIDをまず調べます。
その後、メトリクスフィルタで{$.requestId = "89eb2f4a-a645-4842-a288-65e7de3e28bf"}
のようにフィルタすることで、そのリクエストのログだけをまとめて見れるようになります。
おわりに
LoggerのセットアップをPJ / API毎にしないといけない手間はありますが、運用のことを考えると充分リターンは大きいかなと思います。
Nest.jsなどのFWを使っていれば標準のAPIであるかもしれないので、技術選定の際にはこの辺りも考慮してみてもよいかもしれません。