首页 文章

由cloudwatch日志触发的nodejs lambda函数的exports.handler中的“event”参数

提问于
浏览
0

我有一个用NodeJS编写的AWS Lambda函数,它由CloudWatch Subscription过滤器触发 . 有人告诉我,Lambda函数中exports.handler的“event”参数是我用来获取Log数据的 .

当我打印时,我看到以下内容与我在实际CloudWatch控制台中看到的人类可读数据完全不同 . 这是什么意思?!?这是我得到的:

{ awslogs: { data: 'H4sIAAAAAAAAAKWS207jMBRFf8XyMwFfYztvURpQpFIqEmYeUIV8S4nUJlXizggh/p3D7Qt4Xfvs47O3/IqPcVnsPnYvp4gLvCq78um2btvypsYXePo/xhmwNlQSKZk0QgE+TPubeTqfQCn/ts2U1tN++eJtmqM9guBD0JzF2CuleiWJ9rLvuZfWyyAAM0u4NULaGIxw1hjgOvggeueYYBHWLWe3+Hk4pWEar4dDivOCi0e8tkcX7NdDTzaEahrH6D+Gumnl7BLx7vOU+l8c04fjFQ8BLuJcaqm1ZkTo3EAUKSUEy3NNieQiJ1wzRSEpBQa61oRSQjRckgaoKdkjJIYiciI4p4Lk/OKnPljPCFUZMRljiNCC0UKKSxhB3X1Z1c2qyF2vvPU00yr6zFCjMglhM+cFM8oCpRRt75tN1WzLNRh+2yB6bDbXdzuE6j/1piu2Z3cYlufPVlB3t22qTXlbF80YhnhFOKnkSvCrdkgRfX+AH0szojbZdF4K1D5UFYj4bff2DvK/Lnc7AgAA' } }

根据以下链接,这个数据没错:http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-cloudwatch-logs

根据StackOverflow中的这个答案,这也是数据没错:KeyError: 'awslogs' ... outEvent = str(event['awslogs']['data']) - Python

非常感谢您的任何帮助!

2 回答

  • 1

    你准确找到了Amazon CloudWatch Logs Sample Event . 因此,基于此,您的 event 对象的结构类似于:

    {
      "awslogs": {
        "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=="
      }
    }
    

    What is it?

    让我们打开包装,以更好地了解这里发生了什么 . 在这种情况下 event.awslogs.data 将具有以下值:

    "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=="
    

    该值实际上是GZIPPED有效负载的 Base64 编码字符串 . 这样做是为了压缩有效载荷,并保持小,同时允许它以JSON传输 .

    如果我们对Base64进行解码,然后将其解压缩,我们最终得到以下值:

    {
      "messageType": "DATA_MESSAGE",
      "owner": "123456789123",
      "logGroup": "testLogGroup",
      "logStream": "testLogStream",
      "subscriptionFilters": [
        "testFilter"
      ],
      "logEvents": [
        {
          "id": "eventId1",
          "timestamp": 1440442987000,
          "message": "[ERROR] First test message"
        },
        {
          "id": "eventId2",
          "timestamp": 1440442987001,
          "message": "[ERROR] Second test message"
        }
      ]
    }
    

    这个元素如下:

    • messageType :可以是 DATA_MESSAGECONTROL_MESSAGE ,如果我的理解是正确的, CONTROL_MESSAGE 用于检查lambda的可达性

    • owner :原始日志的AWS账户ID

    • logGroup :原始日志的日志组

    • logStream :原始日志的日志流

    • subscriptionFilter :匹配的订阅筛选器名称

    • logEvents :与您在控制台中看到的内容相关的实际日志

    How do I use it?

    您可以使用CloudWatches _1677317中的以下示例轻松地在Node.js Lambda中实现类似的功能:

    var zlib = require('zlib');
    exports.handler = function(input, context) {
        var payload = new Buffer(input.awslogs.data, 'base64');
        zlib.gunzip(payload, function(e, result) {
            if (e) { 
                context.fail(e);
            } else {
                result = JSON.parse(result.toString('ascii'));
                console.log("Event Data:", JSON.stringify(result, null, 2));
                context.succeed();
            }
        });
    };
    

    希望有所帮助 .

  • 0

    这是什么意思?!?

    当您看到仅由字符 [A-Z][a-z][0-9][+/=] 组成的字符串时,这通常表示Base64编码 . Base64允许不支持任意二进制数据的传输...承载任意二进制数据,通过使用每个字节仅传送6(而不是8)位的格式对其进行重新编码,使用64(2 ^ 6)个符号,所有其中包括标准ASCII字符,因此与文本传输兼容 .

    为什么数据是二进制的?

    因为它是gzipped . Gzip是一种压缩算法非常好并且在压缩文本方面非常快......但Gzipping文本生成任意二进制数据,因此无法在JSON中序列化,JSON只支持文本(和数字以及true / false / null) .

    因此,gzip压缩数据在base64中进行编码,以便在JSON中进行传输 .

    您需要将base64表示转换为二进制,并对其进行g-un-zip .

    http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#LambdaFunctionExample中的示例:

    var zlib = require('zlib');
    exports.handler = function(input, context) {
        var payload = new Buffer(input.awslogs.data, 'base64'); // decode base64 to binary
        zlib.gunzip(payload, function(e, result) { // gunzip the binary data
            if (e) { 
                context.fail(e);
            } else {
                result = JSON.parse(result.toString('ascii'));
                console.log("Event Data:", JSON.stringify(result, null, 2));
                context.succeed();
            }
        });
    };
    

    请注意,这使用旧的 context.fail()context.succeed() 约定,这显然仍然支持向后兼容性,但不应在新代码中使用 . 见http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html#nodejs-prog-model-oldruntime-context-methods .

相关问题