如何下载完整的 AWS CloudWatch 日志

How to download complete AWS CloudWatch log

问题总结

如何使用 CLI 工具从 CloudWatch 下载完整日志?

我下载的日志不完整。我知道这一点,因为如果我使用 --start-from-head 颠倒顺序,我会得到新的内容。不只是倒序。


研究

我正在尝试跟踪 (Flask/Zappa, AWS lambda) 微服务​​中的一个棘手的间歇性故障。

我需要下载日志。

我可以检查 CloudWatch 中的日志:

这是一个包含我想要的文本的:

但是,如果我下载此日志,下载的文件包含以下文本:

> aws logs get-log-events --log-group-name '/aws/lambda/api-dev' --log-stream-name '2018/12/01/[$LATEST]59bc7e539d7948688e0666f8ed14822a' > wtf.txt

> cat wtf.txt | grep "timer"

即没有

现在如果我加上--start-from-head,现在我看到了:

> aws logs get-log-events --log-group-name '/aws/lambda/api-dev' --log-stream-name '2018/12/01/[$LATEST]59bc7e539d7948688e0666f8ed14822a' --start-from-head  > wtf.txt

> cat wtf.txt | grep "timer"
        "message": "> > >  starting game timer  < < <\n",

来自https://docs.aws.amazon.com/cli/latest/reference/logs/get-log-events.html 我观察到:

--limit (integer)

The maximum number of log events returned. If you don't specify a value, the maximum is as many log events as can fit in a response size of 1 MB, up to 10,000 log events.

...和:

> ls -l wtf.txt
-rw-r--r--  1 pi  staff  1247053  3 Dec 10:55:14 2018 wtf.txt

所以它超过了 1MB。所以看起来日志太长了。我要找的文字是日志中最早的一段

那么问题就变成了:如何下载完整的日志?

我尝试设置更高的 --limit,但得到:

An error occurred (InvalidParameterException) when calling the GetLogEvents operation: 1 validation error detected: Value '999999' at 'limit' failed to satisfy constraint: Member must have value less than or equal to 10000

默认值为 10000!无论如何设置一个任意的限制是丑陋的。无论我设置什么,日志都有变长的风险。

如何使用记录的 "nextForwardToken" 密钥?

def get_complete_log(stream_name):
    nextForwardToken = None

    while True:
        param_group =  " --log-group-name '/aws/lambda/api-dev'"
        param_stream = " --log-stream-name '" + stream_name + "'"
        param_token = (" --next-token '" + nextForwardToken + "'") if nextForwardToken else ""

        params = param_group + param_stream + param_token

        cmd = "aws logs get-log-events" + params + " > logs/tmp.txt"
        print(cmd)
        system(cmd)      

        with open('logs/tmp.txt','r') as f:
            tmp = f.read()

            print('CONTENTS:', tmp[:120], '\n')

            J = json.loads( tmp )

        nextForwardToken = J.get("nextForwardToken")

        if not nextForwardToken:
            break


get_complete_log( "2018/12/01/[$LATEST]59bc7e539d7948688e0666f8ed14822a" )

如果我检查输出:

aws logs get-log-events --log-group-name '/aws/lambda/api-dev' --log-stream-name '2018/12/01/[$LATEST]030c7bd5c6ff4d9eb3bb56b8607746b8' > logs/tmp.txt
CONTENTS: {
    "events": [
        {
            "timestamp": 1543707627572,
            "message": "START RequestId: 7b34fa3b-f5 

aws logs get-log-events --log-group-name '/aws/lambda/api-dev' --log-stream-name '2018/12/01/[$LATEST]030c7bd5c6ff4d9eb3bb56b8607746b8' --next-token 'f/34426362085021867195594556764906427633106607331166978053' > logs/tmp.txt
CONTENTS: {
    "events": [],
    "nextForwardToken": "f/34426362085021867195594556764906427633106607331166978053",
    "nextBackw 

所以除了第一个调用 returns "events": []"nextForwardToken": 之外的所有内容都是传入的相同标记!

我建议尝试这个 CLI tool。在我看来,它比 AWS 控制台和 AWS CLI 工具可靠得多。我用它来搜索 CloudWatch 中的大量日志流。您可以轻松指定一个时间范围来搜索甚至 grep CloudWatch 日志流。您还可以实时查看日志流。下面的示例在指定时间范围内搜索组中的所有日志流(另请参阅我正在搜索模式 ERROR 并使用 tee 输出到文件和控制台):

awslogs get my_log_group ALL --start='23/1/2015 12:00' --end='23/1/2016 13:00' | grep ERROR | tee errlogs.txt