boto3でCloudWatch Logs Insightsのクエリを実行する

boto3でCloudWatch Logs Insightsのクエリを実行してみました。
2024.05.30

CloudWatch Logs Insightsで取得した結果をそのまま簡単なプログラムで処理したいことがありました。 そのため、boto3でCloudWatch Logs Insightsのクエリを実行を試してみました。

おすすめの方

  • boto3でCloudWatch Logs Insightsのクエリを実行したい方

Pythonのスクリプト

クエリの実行と結果の取得は、同時にできません。異なるAPIを利用します。

また、結果の取得は少し待つ必要があるので、1秒ごとにループして確認しています。 実行結果は、「output.json」に保存します。

app.py

import json
import boto3
import time
from datetime import datetime, timezone


LOG_GROUP_NAMES = [
    "/aws/lambda/ApiGateway-Need-API-Key-Sample--HelloWorldFunction-51IvePw4uOY8"
]

QUERY_STRING = "fields @timestamp, @message, @logStream, @log | sort @timestamp asc"

# JSTでOK
START_DATE_TIME = datetime(2024, 2, 1)
END_DATE_TIME = datetime(2024, 2, 10)

LIMIT = 3

OUTOUT_FILE = "output.json"

client = boto3.client("logs")


class QueryStatusException(Exception):
    pass


def main():
    query_id = start_query()

    results = get_query_results(query_id)

    with open(OUTOUT_FILE, "w") as f:
        f.write(json.dumps(results, indent=2))


def start_query() -> str:
    resp = client.start_query(
        logGroupNames=LOG_GROUP_NAMES,
        startTime=int(START_DATE_TIME.replace(tzinfo=timezone.utc).timestamp()),
        endTime=int(END_DATE_TIME.replace(tzinfo=timezone.utc).timestamp()),
        queryString=QUERY_STRING,
        limit=LIMIT,
    )
    return resp["queryId"]


def get_query_results(query_id: str) -> list[dict]:
    while True:
        time.sleep(1)
        resp = client.get_query_results(queryId=query_id)
        print(resp["status"])

        if ["Scheduled", "Failed", "Cancelled", "Timeout", "Unknown"] in resp[
            "results"
        ]:
            raise QueryStatusException(resp["status"])

        if resp["status"] == "Running":
            continue

        if resp["status"] == "Complete":
            print(resp["statistics"])
            return resp["results"]


if __name__ == "__main__":
    main()

スクリプトを実行する

$ python app.py

Running
Running
Complete
{'recordsMatched': 28.0, 'recordsScanned': 28.0, 'bytesScanned': 4055.0}

スクリプトの実行結果(JSONファイル)

結果を見やすいようにインデント付きのJSONにしています。

[
  [
    {
      "field": "@timestamp",
      "value": "2024-02-07 09:35:11.331"
    },
    {
      "field": "@message",
      "value": "INIT_START Runtime Version: python:3.9.v44\tRuntime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:3fee14476de2c6c6b67487c8862ea51f1b5376c221844a0e7711d96cc87b3666\n"
    },
    {
      "field": "@logStream",
      "value": "2024/02/07/[$LATEST]d946c98b6dd4449daeb162b8a709f145"
    },
    {
      "field": "@log",
      "value": "057885367821:/aws/lambda/ApiGateway-Need-API-Key-Sample--HelloWorldFunction-51IvePw4uOY8"
    },
    {
      "field": "@ptr",
      "value": "xxx"
    }
  ],
  [
    {
      "field": "@timestamp",
      "value": "2024-02-07 09:35:11.460"
    },
    {
      "field": "@message",
      "value": "START RequestId: c96b279f-27b2-44a3-9d9f-4f971791392c Version: $LATEST\n"
    },
    {
      "field": "@logStream",
      "value": "2024/02/07/[$LATEST]d946c98b6dd4449daeb162b8a709f145"
    },
    {
      "field": "@log",
      "value": "057885367821:/aws/lambda/ApiGateway-Need-API-Key-Sample--HelloWorldFunction-51IvePw4uOY8"
    },
    {
      "field": "@ptr",
      "value": "yyy"
    }
  ],
  [
    {
      "field": "@timestamp",
      "value": "2024-02-07 09:35:11.462"
    },
    {
      "field": "@message",
      "value": "END RequestId: c96b279f-27b2-44a3-9d9f-4f971791392c\n"
    },
    {
      "field": "@logStream",
      "value": "2024/02/07/[$LATEST]d946c98b6dd4449daeb162b8a709f145"
    },
    {
      "field": "@log",
      "value": "057885367821:/aws/lambda/ApiGateway-Need-API-Key-Sample--HelloWorldFunction-51IvePw4uOY8"
    },
    {
      "field": "@ptr",
      "value": "zzz"
    }
  ]
]

さいごに

boto3でCloudWatch Logs Insightsのクエリを実行してみました。得られた情報をさらに分析したい場合などに便利だと思います。

参考