【问题标题】:Log4J2 JSONLAYOUT How to add custom ParametersLog4J2 JSONLAYOUT 如何添加自定义参数
【发布时间】:2017-11-10 23:37:37
【问题描述】:

如何在Log4j2的JSONLAYOUT中添加自定义参数?

还有没有办法给 JSONLAYOUT 的消息元素添加模式?

我已经尝试过这里列出的选项 ->
logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout

请帮忙!

【问题讨论】:

  • @D.B.谢谢你。我已经正确检查了该链接,但没有找到如何添加自定义参数。问题是关于添加自定义参数,该链接中没有提到。
  • 您能否澄清一下添加自定义参数的含义?
  • @D.B.环境详细信息、日期格式等参数......
  • 您应该分享您所做的任何尝试。查看文档,我看不到自定义 json 输出格式的方法。我现在不在电脑前,所以我会在有空的时候尝试一些事情。

标签: log4j2


【解决方案1】:

解决方法是显式添加 log4j2 的 2.10.0 版本。此版本支持 JSONLayout 中的自定义参数!

<Appenders>

    <Console name="Console" target="SYSTEM_OUT">
        <JSONLayout compact="true" eventEol="true">
            <KeyValuePair key="application" value="${sys:com.example.appname}"/>
        </JSONLayout>
    </Console>
    <Async name="AsyncAppender" bufferSize="80">
        <AppenderRef ref="Console"/>
    </Async>

</Appenders>

【讨论】:

【解决方案2】:

据我了解,您正在寻找一种方法来自定义 JSONLayout 的 JSON 输出格式,其方式类似于通过指定“转换模式”来自定义 PatternLayout

我相信答案是您不能以同样的方式自定义JSONLayout。您可以选择要包含在消息中的各种信息。例如,documentation 显示类似 properties 的参数:

如果为 true,则附加程序在生成的 JSON 中包含线程上下文映射。默认为 false。

因此您可以设置各种参数以包含某些类型的信息,但您无法直接控制包含的特定项目。

可以做的是使用ObjectMessage 和 JSON 库来生成 JSON 消息。但是,这会在 JSON 中生成 JSON(假设您仍希望通过这种方法使用 JSONLayout)。下面是一些示例代码来说明:

具有生成日志消息的main方法的类:

package example;

import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;

public class JsonMessageExample {

    private static final Logger log = LogManager.getLogger();
    
    public static void main(String[] args) {
        Map<String,String> msgMap = new HashMap<>();
        msgMap.put("myKey", "myValue");
        JSONObject message = new JSONObject(msgMap);
        log.info(message);
    }
}

log4j2.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JSONLayout/>
        </Console>

    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

上面的输出:

{
  "timeMillis" : 1510429852038,
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "example.JsonMessageExample",
  "message" : "{\"myKey\":\"myValue\"}",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "threadId" : 1,
  "threadPriority" : 5
}

如您所见,消息名称值对的值是 JSON 字符串。为了解析它,您必须将外部对象解析为 JSON,提取消息字段,然后将其值也解析为 JSON。

但是,如果您使用不同的布局,例如非常基本的PatternLayout,如下所示:&lt;PatternLayout pattern="%m%n"/&gt;

您将只能生成一级 JSON 输出,因此只需解析一次。但是,您必须编写逻辑来获取消息中所需的所有数据并将其填充到地图(和 JSON 对象)中,因为现在您只是转储地图的内容。

使用相同 java 代码的示例输出,布局更改为PatternLayout,如上所述:

{"myKey":"myValue"}

编辑:

如果你想使用PatternLayout的“转换模式”,输出JSON格式的日志,甚至不需要编写逻辑来获取一些细节,你甚至可以这样做:

<PatternLayout>
    <pattern>{"timeMillis":"%d{UNIX_MILLIS}","thread":"%t","level":"%p","loggerName":"%c","message":%m}%n</pattern>
</PatternLayout>

样本输出:

{"timeMillis":"1510455694601","thread":"main","level":"INFO","loggerName":"example.JsonMessageExample","message":{"myKey":"myValue"}}

【讨论】:

  • 感谢您的建议。有没有其他方法可以将自定义参数添加到“JSONLayout”中?
  • 你可以自己写布局
  • @D.B.如何编写自定义布局?
  • @GuerinoRodella 请参阅log4j2 manual
  • 这是一个很好的例子,因为PatternLayout 非常广泛,但使用它的主要问题是无法转义值内的引号。例如,您的 {"myKey":"myValue"} 没有转义,因此 "message" 将无法正确读取,并且会破坏读取这些 JSON 值的任何类型的解析器。
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多