CloudWatchLogsには、ログの内容をLambdaに飛ばして処理を行う、サブスクリプションフィルタという機能が存在します。
今回は、その方法について解説していきます。
CloudWatchLogsからLambdaに連携されるデータの3つの特徴
CloudWatchLogsからLambdaに飛ばされるログは以下の三つの特徴があります。
・ある程度のログのまとまりが連携される。
・base64エンコードされている。
・gzip圧縮されている。
LambdaでCloudWatchLogsからのデータを扱うには、この三つの特徴を理解した上で処理を行う必要があります。
以下、それぞれの特徴について解説していきます。
ある程度のログのまとまりが連携される
サブスクリプションフィルタで飛ばされるCloudWatchLogsは、ある程度の塊になっています。
ログの1行1行が飛ばされるわけではないということです。
1行ずつ飛ばしていると、通信コストがかさんでしまうので、ある程度まとまった量が出力されたら連携するという方式をとっているのです。
ですから、Lambdaで処理する際は、ループで1行ずつ処理していくのが定石になります。
base64エンコードされている
これはそのままです。
連携されるデータはbase64エンコードされているので、Lambda上で編集などを行う場合は、デコードしてやる必要があります。
gzip圧縮されている
こちらもそのままですね。
送られてくるデータはgzip圧縮されているので、処理する際はまず解凍してやる必要があります。
CloudWatchLogsを処理するサンプル
以下にCloudWatchLogsを処理するLambdaのサンプルを紹介します。
使用言語はPythonになります。
import json import base64 import gzip def lambda_handler(event, context): print('event =' + str(event)) # CloudWatchLogsから受け取ったデータはbase64エンコードされているため、デコード処理を行う decoded_data = base64.b64decode(event['awslogs']['data']) # ログ本体のデータ(awslogs.data)はバイナリに圧縮されているため、gzip解凍する json_data = json.loads(gzip.decompress(decoded_data)) # ログデータを1件ずつループしてログ出力 for log in json_data['logEvents']: print(str(log['message'])) return
具体的なデータの変化
サンプルソースだけだと、実際のデータがどのように変化していっているのかがわかりにくいかと思います。
参考までにデータがどのように変化していっているかも載せておきます。
CloudWatchLogsからの生データ
CloudWatchLogsから送られた直後の生データです。
awslogsの下にdataのみがついている状態です。
{'awslogs': { 'data': 'pIowREIIzlS6fmCy4eLsQ0WhLeDQBkERRwTZ/N4325ZKsGFvyNaD75n9QvhYKL4CKtVD6Aqhz81Fh+N3xPtHktYNLToscfIfO4SHww25JqaiLBUKS06wlCxuqDhXUA6pIowREIIzlS6fmCy4eLsQ0WhLeDQBkERRwTZ/N4325ZKsGFvyNcC2MZJSZtKBOcU3PiQhirooU/G3+c3RTcOHy4LtjZo+0eFQvyaV573U+drb1byrEbaD75n9QvhYKL4CKtVD6AqhcC2UvgKq1UP6AHu6/6LZDuUQDAAA=' } }
base64デコード後
dataを取り出してデコードしたものです。
gzip圧縮されているのは、dataのみなので、以降は取り出して処理をしています。
b"x08\x05\x1e7\x12s\x02T2\xe0D\t\xc2\x84`@\x00G\xb3\xe0\xe2\xedBD\xa3m\xcab\t\x80\xa4\x8cJ\xb2\xf9\xbbi\xac/\x17\xb3bl\xd3\xaf\x01\xdd7\xff\x83\xa6k\xa1\xf0\x02(\xac\x85\x92\x17@\xc9Z(}\x01\x94\xae\x85\xb2\x07\xf4p\xffe5eu\x90pj\x88\xc1:\xc5FP\x92\x1a\xd5\x10\xca\x19#\xe6\xc487V\xc6\n\x7f6\xfe8\xbb)\xb8q\xf8p]\xb0\xb3G\xdb=*\x16\xe4\xb3\xbc\xf6\xba\x9f:[{\xb7|\xc7n<7\x17\x1d\x8e\xdf\x11\xef\x1f&\xad\x1bZtXt\xf2\x1f;\x84G\xc3\r\xb9&Z\x11\xaa\xb8\xc4B(\nL\xa5\x84\x08\xca\xb0P\x8aI\xa9\x08\x05\x1e7\x12s\x02T2\xe0D\t\xc2\x84`@\x00G\xb3\xe0\xe2\xedBD\xa3m\xcab\t\x80\xa4\x8cJ\xb2\xf9\xbbi\xac/\x17\xb3bl\xd3\xaf\x01\xdd7\xff\x83\xa6k\xa1\xf0\x02(\xac\x85\x92\x17@\xc9Z(}\x01\x94\xae\x85\xb2\x07\xf4p\xff\x05\x8a\xb8\xd0\x8fD\x03\x00\x00"
gzip解凍後
解凍することによって、だいぶデータの意味が分かるようになってきました。
後は、好きな項目を取得して編集していくだけです。
{ 'messageType': 'DATA_MESSAGE', 'owner': '111111111111111', 'logGroup': '/aws/lambda/sample_lambda', 'logStream': '2019/09/09/[$LATEST]82fd3b0a10b7431b9d346553bf566be8', 'subscriptionFilters': ['LambdaStream_sample_simple_cloudwatchlogs_logging'], 'logEvents': [ { 'id': '34968077942591337450799588934260778063248526397357752320', 'timestamp': 1568022845483, 'message': 'SampleLog1\n' }, { 'id': '34968077942591337450799588934260778063248526397357752321', 'timestamp': 1568022845483, 'message': 'SampleLog2\n' }, { 'id': '34968077942591337450799588934260778063248526397357752322', 'timestamp': 1568022845483, 'message': 'SampleLog3\n' }, { 'id': '34968077942591337450799588934260778063248526397357752323', 'timestamp': 1568022845483, 'message': 'SampleLog4\n' } ] }
アラートメールを送る
LambdaでCloudWatchLogsのログを扱う方法は以上です。
後は、SESやSNSを使用することでそのログをアラートメールとして飛ばすことも可能です。
LambdaからSESに飛ばすサンプルは以下で紹介していますので、ご参照ください。