Node.js
AWS
CloudWatch
lambda

AWS Lambdaで CloudWatch Logsから送られるログデータをデコードする

More than 1 year has passed since last update.

CloudWatch Logsのログデータは下記のようなJSON形式でLambdaに転送されます。

具体的なログデータはevent['awslogs']['data']で取得できますが、このエンコードされたデータのデコードに少々戸惑ったので記事にしておきます。


event.json

{

"awslogs": {
"data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=="
}
}


動作環境

AWS Lambda (Node.js 4.3)


実装

結論から言うとbase64によるエンコードのみならずgzipでさらに圧縮がなされているので、Node.js側ではevent['awslogs']['data']に対してbase64でのデコードとgunzipをしてあげれば解決します。

公式ドキュメントにもさらっと書いてあったりもしますが。

http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/Subscriptions.html

コードは下記の通りです。


Node.js


const zlib = require('zlib');

//略

function processEvent(event, callback) {
const base64Logs = new Buffer(event['awslogs']['data'], 'base64');
zlib.gunzip(base64Logs, function (err, binary) {
var uncompressedLogs = binary.toString('ascii');
const slackMessage = {
channel: slackChannel,
text: ${uncompressedLogs}
};
//略
});
}


ほぼLambdaで既に用意されているCloudWatch Logs用のテンプレートの使い回しになってます。

なので[//略]の部分にはslackにログを通知するための別の記述をしています、今回はデコードのためのコードを説明したいのでここについては省略させてください。

base64によるデコード、gunzipによる解凍もdataを16進数表現で取り扱っているので、gunzipしたデータはtoString('ascii')で文字列に変換する必要があります、もしログに英数字以外が入りうる場合は適宜utf8等に変更してください。

以上になります、参考になれば幸いです。