为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

潇潇雨雨 2021-10-17 10:39:45
所以我们有一个应用程序,我们将把它的所有日志发送到 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以便它可以被 elasticSearch 索引,因此可以在 Kibana 中作为一个字段进行搜索。我们为这 3 个字段尝试了各种语法组合/变体,例如%c{2},%M和%LLine - 它们都按字面意义打印出来,作为我们尝试放入的变量。在 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);这有效,我们唯一的问题是在 JSON 中为 Kafka 输入输出类、行和方法到目前为止,我们无法覆盖 Kibana 的@timestamp字段,因此它包含 log4j 生成的时间戳,以便我们可以可靠地按生成日志的时间/日期排序(否则,如果它们以随机顺序出现,它们会令人困惑) - 当我们添加了@标志,Kibana 添加了一个标签,如_timestampparsefailure,并显示提交@timestamp的_@timestamp,而不是使用它来覆盖它生成的时间戳。任何人都可以请教吗?我们已经搜索了很远很远,到目前为止还没有找到任何接近的东西。谢谢。
查看完整描述

2 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

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

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



查看完整回答
反对 回复 2021-10-17
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

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


@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方法内部完成的,但我不能发布,因为我没有被授权。


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


查看完整回答
反对 回复 2021-10-17
  • 2 回答
  • 0 关注
  • 802 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信