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

时间:2018-09-27 13:25:44

标签: java kibana log4j2

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

以下是我们设法工作的基础,没有任何问题地发布到了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个字段尝试了各种语法组合/变体,例如Line的%c{2}%M%L-它们都按字面意义打印出来,作为我们尝试放入的变量

在控制台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,该错误ID的设置方式如下:

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

这可行,我们唯一的问题是

  1. 在JSON中为Kafka输入输出类,行和方法

  2. 到目前为止,我们无法覆盖Kibana的@timestamp字段,因此它包含由log4j生成的时间戳,因此我们可以按生成日志的时间/日期可靠地进行排序(否则,它们会如果它们按随机顺序出现,将会造成混乱)-当我们添加@符号时,Kibana会添加诸如_timestampparsefailure之类的标签,并以@timestamp显示提交的_@timestamp,而不是使用它来覆盖它生成的时间戳。

有人可以建议吗?我们已经进行了广泛的搜索,到目前为止还没有找到任何东西。

谢谢。

2 个答案:

答案 0 :(得分:0)

我们还没有找到一种制作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而不是默认的。

答案 1 :(得分:0)

Add "locationInfo="true" " to the JSON properties in the Log4j2 config file: For Example:

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