使用 Json 模板布局 log4j2 在 json 日志中写入序列号时处理异常堆栈跟踪
Handling exception stack trace while writing serial no in json logs using Json template layout log4j2
我正在使用 json template layout 通过 kinesis firehose 和 firelens 将我的 ecs 服务的 json 日志写入到 s3。
以下是我使用的json模板布局的配置-
{
"context_map": {
"$resolver": "mdc"
},
"serial_no": {
"$resolver": "pattern",
"pattern": "%sn"
},
"timestamp": {
"$resolver": "timestamp",
"pattern": {
"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"timeZone": "UTC"
}
},
"level": {
"$resolver": "level",
"field": "name"
},
"logger_name": {
"$resolver": "logger",
"field": "name"
},
"message": {
"$resolver": "message",
"stringified": true
},
"thread": {
"$resolver": "thread",
"field": "name"
},
"exception": {
"exception_class": {
"$resolver": "exception",
"field": "className"
},
"exception_message": {
"$resolver": "exception",
"field": "message",
"stringified": true
},
"stacktrace": {
"$resolver": "exception",
"field": "stackTrace",
"stringified": true
}
},
"class": {
"$resolver": "source",
"field": "className"
}
}
以下是日志配置的快照-
Console:
- Name: Console
Target: SYSTEM_OUT
JsonTemplateLayout:
eventTemplateUri: "file:/opt/amazon/log-configuration/JsonLayoutTemplate.json"
prettyPrintEnabled: true
stackTraceEnabled: true
以下是异常情况下生成的样例日志-
{
"container_id": "1f1319d278264d3dwewdeddewdewdewdew-849099158",
"container_name": "test-container",
"context_map": {
"RequestId": "28289758-ab3b-4f8c-b3f1-freferfc"
},
"exception": {
"exception_class ": "com.xyz.exception”,
"exception_message": "Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.",
"stacktrace": "com.xyz.exception: Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.\n\ .... stackTrace”
},
"level": "ERROR”,
"logger_name": "com.xyz.handler",
"message": "Seems to be impossible to process message: helllo world",
"serial_no": "52 com.xyz.handler: Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.\n\ .... stackTrace",
"source": "stdout",
"thread": "test-thread",
"timestamp": "2021-04-06 T14:30:02.122 Z"
}
根据文档 Pattern Resolver delegates to PatternLayout
和模式布局提供 %sn
用于获取序列号。
我们确实需要序列号,因为我们可以同时获取很多日志,所以为了区分日志,我们将在查询日志时依赖那些 json 日志中的序列号、requestId 参数在 AWS Athena 中。
此外,我看到很少有序列号为空的日志实例(不是异常日志)
如何防止 serial_no 在其中包含异常堆栈跟踪?
并确保我总是在日志中得到 serial_no 字段 ?
当您通过 pattern
解析器从 JsonTemplateLayout
委托给 PatternLayout
时,LogEvent
将按原样传递。一旦 PatternLayout
发现 LogEvent
附加了异常,它会将堆栈跟踪附加到发出的输出,因为创建的 PatternLayout
实例继承了 stackTraceEnabled=true
标志您设置为 JsonTemplateLayout
。因此,您需要禁用 PatternLayout
的堆栈跟踪,如下所示:
{
"$resolver": "pattern",
"pattern": "%sn",
"stackTraceEnabled": false
}
请注意,这仍将生成 string
类型的序列号。如果要生成 number
类型的序列号,可以按以下方式使用 timestamp
解析器:
{
"$resolver": "timestamp",
"epoch": {
"unit": "nanos",
"rounded": true
}
}
与此同时,我创建了 LOG4J2-3067 以将序列号解析器添加到 JsonTemplateLayout
。
我正在使用 json template layout 通过 kinesis firehose 和 firelens 将我的 ecs 服务的 json 日志写入到 s3。
以下是我使用的json模板布局的配置-
{
"context_map": {
"$resolver": "mdc"
},
"serial_no": {
"$resolver": "pattern",
"pattern": "%sn"
},
"timestamp": {
"$resolver": "timestamp",
"pattern": {
"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"timeZone": "UTC"
}
},
"level": {
"$resolver": "level",
"field": "name"
},
"logger_name": {
"$resolver": "logger",
"field": "name"
},
"message": {
"$resolver": "message",
"stringified": true
},
"thread": {
"$resolver": "thread",
"field": "name"
},
"exception": {
"exception_class": {
"$resolver": "exception",
"field": "className"
},
"exception_message": {
"$resolver": "exception",
"field": "message",
"stringified": true
},
"stacktrace": {
"$resolver": "exception",
"field": "stackTrace",
"stringified": true
}
},
"class": {
"$resolver": "source",
"field": "className"
}
}
以下是日志配置的快照-
Console:
- Name: Console
Target: SYSTEM_OUT
JsonTemplateLayout:
eventTemplateUri: "file:/opt/amazon/log-configuration/JsonLayoutTemplate.json"
prettyPrintEnabled: true
stackTraceEnabled: true
以下是异常情况下生成的样例日志-
{
"container_id": "1f1319d278264d3dwewdeddewdewdewdew-849099158",
"container_name": "test-container",
"context_map": {
"RequestId": "28289758-ab3b-4f8c-b3f1-freferfc"
},
"exception": {
"exception_class ": "com.xyz.exception”,
"exception_message": "Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.",
"stacktrace": "com.xyz.exception: Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.\n\ .... stackTrace”
},
"level": "ERROR”,
"logger_name": "com.xyz.handler",
"message": "Seems to be impossible to process message: helllo world",
"serial_no": "52 com.xyz.handler: Problem processing the SQS message with body helllo world, exception: Error while deserializing the message from test - message - queue.\n\ .... stackTrace",
"source": "stdout",
"thread": "test-thread",
"timestamp": "2021-04-06 T14:30:02.122 Z"
}
根据文档 Pattern Resolver delegates to PatternLayout
和模式布局提供 %sn
用于获取序列号。
我们确实需要序列号,因为我们可以同时获取很多日志,所以为了区分日志,我们将在查询日志时依赖那些 json 日志中的序列号、requestId 参数在 AWS Athena 中。
此外,我看到很少有序列号为空的日志实例(不是异常日志)
如何防止 serial_no 在其中包含异常堆栈跟踪? 并确保我总是在日志中得到 serial_no 字段 ?
当您通过 pattern
解析器从 JsonTemplateLayout
委托给 PatternLayout
时,LogEvent
将按原样传递。一旦 PatternLayout
发现 LogEvent
附加了异常,它会将堆栈跟踪附加到发出的输出,因为创建的 PatternLayout
实例继承了 stackTraceEnabled=true
标志您设置为 JsonTemplateLayout
。因此,您需要禁用 PatternLayout
的堆栈跟踪,如下所示:
{
"$resolver": "pattern",
"pattern": "%sn",
"stackTraceEnabled": false
}
请注意,这仍将生成 string
类型的序列号。如果要生成 number
类型的序列号,可以按以下方式使用 timestamp
解析器:
{
"$resolver": "timestamp",
"epoch": {
"unit": "nanos",
"rounded": true
}
}
与此同时,我创建了 LOG4J2-3067 以将序列号解析器添加到 JsonTemplateLayout
。