CloudWatch LogsのログをJavaScriptで取得する
AWS上でServerless系のアプリを開発していると、大体のログはCloudWatch Logsにたまっていきます。 で、このデータを取得してダッシュボードに表示するとか内部処理的なことできたら便利よねーって気がした […]
広告ここから
広告ここまで
目次
AWS上でServerless系のアプリを開発していると、大体のログはCloudWatch Logsにたまっていきます。
で、このデータを取得してダッシュボードに表示するとか内部処理的なことできたら便利よねーって気がしたので、とりあえず試してみました。
Log Streamのデータを取得するコードサンプル
'use strict'
const aws = require('aws-sdk')
const cloudwatchlogs = new aws.CloudWatchLogs();
const params = {
  logGroupName: '/aws/lambda/{YOUR_LAMBDA_NAME}',
  logStreamName: '{YOUR_LOG_STREAM_NAME}',
}
cloudwatchlogs.getLogEvents(params, function(err, data) {
  if (err) console.log(err, err.stack);       // an error occurred
  else     console.log(JSON.stringify(data)); // successful response
});
これを実行すると、以下のようなJSONが取得できます。
{
  "events": [
    {
      "timestamp": 1502329050066,
      "message": "START RequestId: 78a33025-7d6c-11e7-965d-21381e8db922 Version: $LATEST\n",
      "ingestionTime": 1502329050092
    },
    {
      "timestamp": 1502329050071,
      "message": "2017-08-10T01:37:30.071Z\t78a33025-7d6c-11e7-965d-21381e8db922\tWarning: Application ID is not set\n",
      "ingestionTime": 1502329065157
    },
    {
      "timestamp": 1502329050072,
      "message": "END RequestId: 78a33025-7d6c-11e7-965d-21381e8db922\n",
      "ingestionTime": 1502329065157
    }
  ],
  "nextForwardToken": "f/XXXXXXXXX",
  "nextBackwardToken": "b/XXXXXXXXXXX"
}
ログを検索する
filterLogEvents()を使うことで、複数のストリームを跨いだデータ取得や検索ができます。
ロググループ全体からデータを取得
'use strict'
const aws = require('aws-sdk')
var cloudwatchlogs = new aws.CloudWatchLogs();
var params = {
  logGroupName: '/aws/lambda/{YOUR_LAMBDA_NAME}',
}
cloudwatchlogs.filterLogEvents(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     {
    console.log(JSON.stringify(data))
  };           // successful response
});
件数指定
'use strict'
const aws = require('aws-sdk')
var cloudwatchlogs = new aws.CloudWatchLogs();
var params = {
  logGroupName: '/aws/lambda/{YOUR_LAMBDA_NAME}',
  limit: 10,
}
cloudwatchlogs.filterLogEvents(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     {
    console.log(JSON.stringify(data))
  };           // successful response
});
特定のストリームのみを検索する
'use strict'
const aws = require('aws-sdk')
var cloudwatchlogs = new aws.CloudWatchLogs();
var params = {
  logGroupName: '/aws/lambda/{YOUR_LAMBDA_NAME}',
  logStreamNames: [
    '{YOUR_LOG_STREAM_NAME}'
  ],
  limit: 10,
}
cloudwatchlogs.filterLogEvents(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     {
    console.log(JSON.stringify(data))
  };           // successful response
});
特定のワードで検索する
'use strict'
const aws = require('aws-sdk')
var cloudwatchlogs = new aws.CloudWatchLogs();
var params = {
  logGroupName: '/aws/lambda/{YOUR_LAMBDA_NAME}',
  logStreamNames: [
    '{YOUR_LOG_STREAM_NAME}'
  ],
  filterPattern: 'End',
  limit: 10,
}
cloudwatchlogs.filterLogEvents(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     {
    console.log(JSON.stringify(data))
  };           // successful response
});
利用可能なフィルタについてはドキュメントを確認しましょう。
レスポンスサンプル
{
  "events": [
    {
      "logStreamName": "2017/08/10/[$LATEST]fa0459eaca4c47fd8910814a87aa2d6d",
      "timestamp": 1502329050066,
      "message": "START RequestId: 78a33025-7d6c-11e7-965d-21381e8db922 Version: $LATEST\n",
      "ingestionTime": 1502329050092,
      "eventId": "33503057349872421645050596679170442839993300164917788672"
    },
    {
      "logStreamName": "2017/08/10/[$LATEST]fa0459eaca4c47fd8910814a87aa2d6d",
      "timestamp": 1502329050071,
      "message": "2017-08-10T01:37:30.071Z\t78a33025-7d6c-11e7-965d-21381e8db922\tWarning: Application ID is not set\n",
      "ingestionTime": 1502329065157,
      "eventId": "33503057349983925371043249813090712220593683440808296448"
    },
    {
      "logStreamName": "2017/08/10/[$LATEST]fa0459eaca4c47fd8910814a87aa2d6d",
      "timestamp": 1502329050072,
      "message": "END RequestId: 78a33025-7d6c-11e7-965d-21381e8db922\n",
      "ingestionTime": 1502329065157,
      "eventId": "33503057350006226116241780436232247938866331802314276865"
    },
  ],
  "searchedLogStreams": [
    {
      "logStreamName": "2017/08/10/[$LATEST]XXXXXXX",
      "searchedCompletely": false
    }
  ],
  "nextToken": "XXXXXXXXXXXXX"
}
覚書
もしCloudWatch Logsのメトリクスフィルターで満足できない検索をしたい場合は、フロント側でlodashなどを使って頑張るか、Amazon Elasticsearch Serviceにデータをストリーミングさせてそちらから検索するといいかなと思います。
良い方法や事例あればFacebookとかでコメントもらえると嬉しいです。