Log4J2 JsonLayout 打印出 class、方法和行以及@timestamp 覆盖

Log4J2 JsonLayout printing out class, method and line and @timestamp override

所以我们有一个应用程序,我们将把它的所有日志发送到 Kibana 服务器(通过 Kafka 服务器)。

以下是我们设法开始工作的基础知识,可以毫无问题地发布到 Kibana:

        <Kafka name="KafkaAppender" topic="topic1">
        <JsonLayout compact="true">
            <KeyValuePair key="service" value="some_app_tag"/>
            <KeyValuePair key="@timestamp" value="${date:yyyy-MM-dd HH:mm:ss.SSS}"/>
            <KeyValuePair key="host_name" value="${hostName}"/>
            <KeyValuePair key="unique_id" value="$${map:name:-NA}"/>
    </JsonLayout>
        <Property name="bootstrap.servers">kafka1.com:9092,kafka2.com:9092,kafka3.com:9092</Property>
    </Kafka>

然而,我们发现很难在 JsonLayout 中打印出 class、方法和行号,以便它可以被 elasticSearch 索引,因此可以在 Kibana 中作为一个字段进行搜索。

我们为这 3 个字段尝试了各种语法 combinations/variations,例如 Line 的 %c{2}%M%L - 它们都按字面意义打印为我们的变量尝试放入。

在 Console Appender 中,他们使用: <pattern>%23.23d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] [$${map:name:-NA}] %c{1}.%M(%F:%L): %highlight{%m%n%throwable}</pattern>

"$${map:name:-NA}" 是我们添加的内容,用于添加唯一的错误 ID,可以根据用户收到的错误消息进行搜索,它是由类似以下内容设置的:

    StringMapMessage mapMsg = new StringMapMessage();
    mapMsg.put("name", "arun");
    LOGGER.fatal(mapMsg);

这行得通,我们唯一的问题是

  1. 输出class,JSON中Kafka输入的行和方法

  2. 到目前为止,我们无法覆盖 Kibana 的 @timestamp 字段,因此它包含 log4j 生成的时间戳,这样我们就可以可靠地按 time/date 日志排序是生成的(否则如果它们以随机顺序出现会造成混淆) - 当我们添加 @ 符号时,Kibana 添加了一个标签,如 _timestampparsefailure,并显示提交的 @timestamp_@timestamp,而不是用它来覆盖它生成的时间戳。

请问有人能指点一下吗?我们四处搜寻,到目前为止还没有找到任何接近的东西。

谢谢。

我们还没有找到使 JsonLayout 输出 class 的方法,行和方法,我们采用的解决方法是实现我们自己的布局,基本上就是创建一个新的自定义布局插件基本上是 JsonLayout class 的副本,增加了对模式的支持:

@Plugin(name = "CustomJsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class CustomJsonLayout extends AbstractJacksonLayout {

在其构造函数中添加了参数:

final boolean stacktraceAsString,
final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields,
final boolean objectMessageAsJsonObject

然后当然也将它们添加到 super 调用中。

最大的变化是覆盖了 toSerializable(final LogEvent event, final Writer writer) 方法并添加了私有方法 customFunctionToApplyPatternConversion,它看起来类似于:

Object wrappedEvent = wrapLogEvent(convertMutableToLog4jEvent(event));
if (wrappedEvent instanceof LogEventWithAdditionalFields) {
    LogEventWithAdditionalFields eventWithAdditionalFields = (LogEventWithAdditionalFields) wrappedEvent;
    eventWithAdditionalFields = customFunctionToApplyPatternConversion(event, eventWithAdditionalFields);

    wrappedEvent = eventWithAdditionalFields;
}
objectWriter.writeValue(writer, wrappedEvent);

大部分内容都是在 customFunctionToApplyPatternConversion 方法中完成的,但我不能 post 因为我没有被授权。

这是关于如何添加对检测模式的支持并用值替换它们的一般思路。 如果您查看 JsonLayout classes 和 PatternLayout classes 的完整代码,您可以更好地理解这一点 - 这实际上是将它们合并在一起,然后在 log4j2.xml 中指定 CustomJsonLayout而不是默认的。

将 "locationInfo="true" " 添加到 Log4j2 配置文件中的 JSON 属性: 例如:

<JsonLayout complete="false" locationInfo="true" properties="true" propertiesAsList="true" eventEol="true">