AWS Lambda Functionのログを取得するgulpタスクを作ってみた
最近、Lambda Functionの開発をしてたりするのですがマネジメントコンソール上でCloudWatch Logsに保存されるLambda Functionログを確認するのがかなり辛いということがありました。そこでlambchop-tailも試してみたんですが元々node-aws-lambdaを利用してデプロイ1を行っていることもあり、直近のLambda FunctionのログをCloudWatch Logsから取得するgulpタスクを作りました。
ソースコード
node-aws-lambdaのGulp exampleに以下のソースコードを追加すると動作します。なお、取得するLogStreamの数をgulpコマンドのオプションとして指定できるようにしたかったのでminimist2を利用しています。
var AWS = require("aws-sdk"); var minimist = require('minimist'); var knownOptions = { string: 'logslimit', 'default' : { 'logslimit' : 1 } }; var options = minimist(process.argv.slice(2), knownOptions); gulp.task('logs', function(callback) { var config = require("./lambda-config.js"); var cloudwatchlogs = new AWS.CloudWatchLogs({ region : config.region }); var logGroupName = '/aws/lambda/' + config.functionName; cloudwatchlogs.describeLogStreams({ logGroupName : logGroupName, descending : true, // 直近のログを取得する limit : options.logslimit, // --logslimit オプションで指定可能 orderBy : 'LastEventTime' }, function(err, data) { if (err) { console.log(err, err.stack); return; } data.logStreams.forEach(function(logStream) { // ログの取得。paginationは未実装 cloudwatchlogs.getLogEvents({ logGroupName : logGroupName, logStreamName : logStream.logStreamName }, function(err, data) { if (err) { console.log(err, err.stack); return; } // ログ出力 data.events.forEach(function(event) { var lines = event.message.split('\n'); lines.pop(); // 最後に付与されている改行文字を除去 // 先頭行を出力 console.log(lines.shift()); // 1ログに2行以上ログがあれば出力。その際にインデントする for ( var i in lines) { console.log('\t' + lines[i]); } }); }); }); }); });
コメントにもあるようにgetLogEventsメソッドのpaginationは未実装です。今の所、アプリの規模が小さくそこまでログがなかったので。paginationが必要な場合は追加実装してください。
実行
hello-world blueprintのログを取得してみます。まずはhello-world blueprintのソースを貼っておきます。
console.log('Loading function'); exports.handler = function(event, context) { console.log('Received event:', JSON.stringify(event, null, 2)); console.log('value1 =', event.key1); console.log('value2 =', event.key2); console.log('value3 =', event.key3); context.succeed(event.key1); // Echo back the first key value // context.fail('Something went wrong'); };
このFunctionに対してlogsタスクを実行すると以下の様な感じでログを取得できます。引数の--logslimitオプションはデフォルト値が1なので、1でよい場合は指定不要です。以下ではオプションがあることを示すため指定しています。
$ gulp logs --logslimit 1 [13:18:15] Using gulpfile ~/gulpfile.js [13:18:15] Starting 'logs'... 2015-07-01T08:34:04.329Z 8lkpgcs36e4jsizq Loading function START RequestId: edb60818-1fcb-11e5-abb3-c31e55314433 2015-07-01T08:34:04.332Z edb60818-1fcb-11e5-abb3-c31e55314433 Received event: { "key1": "value1", "key2": "value2", "key3": "value3" } 2015-07-01T08:34:04.332Z edb60818-1fcb-11e5-abb3-c31e55314433 value1 = value1 2015-07-01T08:34:04.332Z edb60818-1fcb-11e5-abb3-c31e55314433 value2 = value2 2015-07-01T08:34:04.332Z edb60818-1fcb-11e5-abb3-c31e55314433 value3 = value3 END RequestId: edb60818-1fcb-11e5-abb3-c31e55314433 REPORT RequestId: edb60818-1fcb-11e5-abb3-c31e55314433 Duration: 2.03 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 27 MB $
ソースを読むと分かりますが、1ログの中で改行が存在する場合は2行目以降はインデントしています。
まとめ
これを作ったおかげでマネジメントコンソール上でログを確認するというストレスから開放されました。ただ、Lambda FunctionからCloudWatch Logsへのログの出力にはタイムラグがあるので、そこは待ちが発生するのが残念です(´・ω・`)
よければご利用下さい。
- node-aws-lambdaの利用方法はAWS LambdaファンクションをGulpでデプロイを参照して下さい。 ↩
- Pass arguments from the command lineというレシピがあったのでgulpで引数を利用する際はminimistを利用するのがよいようです。 ↩