使用 log4j2 进行结构化日志记录

编辑

通过利用 log4j2 的 MapMessage,甚至通过实现您自己的支持 JSON 的 MultiformatMessage,您可以将其他字段添加到生成的 JSON 中。

示例

logger.info(new StringMapMessage()
    .with("message", "Hello World!")
    .with("foo", "bar"));

如果 Jackson 在类路径上,您还可以使用 ObjectMessage 将自定义对象添加到生成的 JSON 中。

logger.info(new ObjectMessage(myObject));

myObject 变量引用一个可以由 Jackson ObjectMapper 序列化的自定义对象。

如果它是 JSON 对象,则使用任何一种方法都会将该对象合并到日志事件的顶层(而不是嵌套在 message 下)。如果它是字符串、数字、布尔值或数组,它将被转换为字符串并作为 message 属性添加。此转换避免了映射冲突,因为 message 在 Elasticsearch 映射中被键入为字符串。

提示

编辑

我们建议使用现有的 ECS 字段

如果没有合适的 ECS 字段,请考虑为您的字段添加 labels. 前缀,例如 labels.foo,用于简单的键/值对。对于嵌套结构,请考虑使用 custom. 前缀。这种方法可以防止在 ECS 稍后添加相同字段但使用不同映射时发生冲突。

注意事项

编辑

一个常见的陷阱是 Elasticsearch 如何处理字段名称中的点以及它们如何影响映射。在最近的 Elasticsearch 版本中,以下 JSON 结构将导致相同的索引映射

{
  "foo.bar": "baz"
}
{
  "foo": {
    "bar": "baz"
  }
}

属性 foo 将被映射到 对象数据类型

这意味着您无法索引 foo 是不同数据类型的文档,如下例所示

{
  "foo": "bar"
}

在该示例中,foo 是一个字符串。尝试索引该文档会导致错误,因为 foo 的数据类型不能同时是对象和字符串。