我有一个用NodeJS编写的AWS Lambda函数,它由CloudWatch Subscription过滤器触发。有人告诉我,Lambda函数中exports.handler的“event”参数是我用来获取Log数据的。
当我打印时,我看到以下内容与我在实际CloudWatch控制台中看到的人类可读数据完全不同。这是什么意思?!?这是我得到的:
"models"
根据以下链接,此数据没有错: http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-cloudwatch-logs
根据StackOverflow中的这个答案,这也是数据没错: KeyError: 'awslogs' ... outEvent = str(event['awslogs']['data']) - Python
非常感谢您提供任何帮助!
答案 0 :(得分:1)
您准确找到了Amazon CloudWatch Logs Sample Event。因此,基于此,您的event
对象的结构类似于:
{
"awslogs": {
"data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=="
}
}
这是什么?
让我们解压一下,以便更好地了解这里发生了什么。在这种情况下,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_MESSAGE
或CONTROL_MESSAGE
,如果我的理解是正确的,CONTROL_MESSAGE
用于检查lambda的可达性owner
:原始日志的AWS账户ID logGroup
:原始日志的日志组logStream
:原始日志的日志流subscriptionFilter
:匹配的订阅过滤器名称logEvents
:与您在控制台中看到的内容相关的实际日志如何使用它?
您可以使用CloudWatches Subscription Filters with AWS Lambda中的以下示例轻松地在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();
}
});
};
希望有所帮助。
答案 1 :(得分:0)
这是什么意思?!?
当您看到仅由字符[A-Z][a-z][0-9][+/=]
组成的字符串时,这通常表示Base64编码。 Base64允许不支持任意二进制数据的传输...携带任意二进制数据,通过使用每个字节仅传送6(而不是8)位的格式对其进行重新编码,使用64(2 ^ 6)个符号,所有其中包括标准的ASCII字符,因此与文本传输兼容。
为什么数据是二进制的?
因为它被gzipped。 Gzip是一种压缩算法非常好并且在压缩文本方面非常快......但是Gzipping文本生成任意二进制数据,所以它不能用JSON序列化,JSON只支持文本(和数字以及true / false /空)。
因此,gzip压缩数据在base64中编码,以便在JSON中传输。
您需要将base64表示转换为二进制,然后g-un-zip。
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。