如何在python中使用boto3查询cloudwatch日志

Sim*_*aur 26 python amazon-web-services amazon-cloudwatch boto3 aws-lambda

我有一个将指标写入 Cloudwatch 的 lambda 函数。虽然它写入指标,但它会在日志组中生成一些日志。

INFO:: username: simran+test@abc.com ClinicID: 7667 nodename: MacBook-Pro-2.local

INFO:: username: simran+test2@abc.com ClinicID: 7667 nodename: MacBook-Pro-2.local

INFO:: username: simran+test@abc.com ClinicID: 7668 nodename: MacBook-Pro-2.local

INFO:: username: simran+test3@abc.com ClinicID: 7667 nodename: MacBook-Pro-2.local
Run Code Online (Sandbox Code Playgroud)

我想x根据任何参数查询过去几小时内的AWS 日志,其中 x 可以是 12 到 24 小时之间的任何时间。

例如:

  1. 查询过去 5 小时内的 Cloudwatch 日志,其中 ClinicID=7667

或者

  1. 查询过去 5 小时内的 Cloudwatch 日志,其中ClinicID=7667username='simran+test@abc.com'

或者

  1. 查询过去 5 小时内的 Cloudwatch 日志,其中 username='simran+test@abc.com'

boto3在 Python 中使用。我可以在这方面有指导吗?

Unk*_*nts 49

您可以使用 CloudWatch Logs Insights 获得您想要的信息。

您将使用start_queryget_query_resultsAPI:https : //boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html

要开始您将使用的查询(对于您问题中的用例 2,1 和 3 相似):

import boto3
from datetime import datetime, timedelta
import time

client = boto3.client('logs')

query = "fields @timestamp, @message | parse @message \"username: * ClinicID: * nodename: *\" as username, ClinicID, nodename | filter ClinicID = 7667 and username='simran+test@abc.com'"  

log_group = '/aws/lambda/NAME_OF_YOUR_LAMBDA_FUNCTION'

start_query_response = client.start_query(
    logGroupName=log_group,
    startTime=int((datetime.today() - timedelta(hours=5)).timestamp()),
    endTime=int(datetime.now().timestamp()),
    queryString=query,
)

query_id = start_query_response['queryId']

response = None

while response == None or response['status'] == 'Running':
    print('Waiting for query to complete ...')
    time.sleep(1)
    response = client.get_query_results(
        queryId=query_id
    )
Run Code Online (Sandbox Code Playgroud)

响应将以这种格式包含您的数据(加上一些元数据):

{
  'results': [
    [
      {
        'field': '@timestamp',
        'value': '2019-12-09 17:07:24.428'
      },
      {
        'field': '@message',
        'value': 'username: simran+test@abc.com ClinicID: 7667 nodename: MacBook-Pro-2.local\n'
      },
      {
        'field': 'username',
        'value': 'simran+test@abc.com'
      },
      {
        'field': 'ClinicID',
        'value': '7667'
      },
      {
        'field': 'nodename',
        'value': 'MacBook-Pro-2.local\n'
      }
    ]
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • 您应该注意 `start_query` 函数的 `limit` 参数([链接](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html#CloudWatchLogs.Client. start_query)),默认为1000。如果您使用高密度日志,则可以忽略某些事件而无需指定更高的限制。 (4认同)
  • 请注意,除了“Running”之外,“response['status']”也可以是“Scheduled”,因此请考虑在“while”条件中添加“or response['status'] == 'Scheduled'”。完整列表是链接文档中的“已计划”、“正在运行”、“已完成”、“失败”、“已取消”、“超时”和“未知”。 (3认同)

San*_*tel 8

您可以使用cloudWatchlogs 客户端和一些编码来实现这一点。您还可以自定义条件或使用 JSON 模块以获得精确的结果。

编辑

您可以使用describe_log_streams来获取流。如果您只想要最新的,只需设置限制 1,或者如果您想要多个,请使用 for 循环在过滤时迭代所有流,如下所述。

    import boto3

    client = boto3.client('logs')


    ## For the latest
    stream_response = client.describe_log_streams(
        logGroupName="/aws/lambda/lambdaFnName", # Can be dynamic
        orderBy='LastEventTime',                 # For the latest events
        limit=1                                  # the last latest event, if you just want one
        )

    latestlogStreamName = stream_response["logStreams"]["logStreamName"]


    response = client.get_log_events(
        logGroupName="/aws/lambda/lambdaFnName",
        logStreamName=latestlogStreamName,
        startTime=12345678,
        endTime=12345678,
    )

    for event in response["events"]:
        if event["message"]["ClinicID"] == "7667":
            print(event["message"])
        elif event["message"]["username"] == "simran+test@abc.com":
            print(event["message"])
        #.
        #.
        # more if or else conditions

    ## For more than one Streams, e.g. latest 5
    stream_response = client.describe_log_streams(
        logGroupName="/aws/lambda/lambdaFnName", # Can be dynamic
        orderBy='LastEventTime',                 # For the latest events
        limit=5                                  
        )

    for log_stream in stream_response["logStreams"]:
        latestlogStreamName = log_stream["logStreamName"]

        response = client.get_log_events(
             logGroupName="/aws/lambda/lambdaFnName",
             logStreamName=latestlogStreamName,
             startTime=12345678,
             endTime=12345678,
        )
        ## For example, you want to search "ClinicID=7667", can be dynamic

        for event in response["events"]:
           if event["message"]["ClinicID"] == "7667":
             print(event["message"])
           elif event["message"]["username"] == "simran+test@abc.com":
             print(event["message"])
           #.
           #.
           # more if or else conditions



Run Code Online (Sandbox Code Playgroud)

让我知道事情的后续。