Java 是否有一个Logback布局来创建以消息参数作为属性的JSON对象?
我想将日志事件作为带有参数化字符串消息的JSON对象发送给Loggly。我们的项目目前有很多代码如下所示:Java 是否有一个Logback布局来创建以消息参数作为属性的JSON对象?,java,json,slf4j,logback,loggly,Java,Json,Slf4j,Logback,Loggly,我想将日志事件作为带有参数化字符串消息的JSON对象发送给Loggly。我们的项目目前有很多代码如下所示: String someParameter = "1234"; logger.log("This is a log message with a parameter {}", someParameter); { "message": "This is a log message with a parameter 1234", "level": INFO, ....
String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
"message": "This is a log message with a parameter 1234",
"level": INFO,
....
}
{
"message": "This is a log message with a parameter {}",
"level": INFO,
"parameters": [
"1234"
]
}
{
"ts":"2017-02-16T07:41:36.680-08:00",
"msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
"logger":"com.xxx.services.metrics.ExecutionTimeLogger",
"level":"INFO",
"metric":{
"name":"Controller Hit",
"method":"setupSession",
"className":"class com.xxx.services.controllers.SessionController",
"duration":3225
}
}
我们目前使用Logback作为SLF4J后端,Logback将ILogEvent对象序列化为JSON。因此,当我们的日志事件发送到Loggly时,它们看起来是这样的:
String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
"message": "This is a log message with a parameter 1234",
"level": INFO,
....
}
{
"message": "This is a log message with a parameter {}",
"level": INFO,
"parameters": [
"1234"
]
}
{
"ts":"2017-02-16T07:41:36.680-08:00",
"msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
"logger":"com.xxx.services.metrics.ExecutionTimeLogger",
"level":"INFO",
"metric":{
"name":"Controller Hit",
"method":"setupSession",
"className":"class com.xxx.services.controllers.SessionController",
"duration":3225
}
}
虽然这确实有效,但它为someParameter
的每个值发送不同的消息
字符串,这使得Loggly的自动过滤器几乎无用
相反,我希望有一个创建JSON的布局,如下所示:
String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
"message": "This is a log message with a parameter 1234",
"level": INFO,
....
}
{
"message": "This is a log message with a parameter {}",
"level": INFO,
"parameters": [
"1234"
]
}
{
"ts":"2017-02-16T07:41:36.680-08:00",
"msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
"logger":"com.xxx.services.metrics.ExecutionTimeLogger",
"level":"INFO",
"metric":{
"name":"Controller Hit",
"method":"setupSession",
"className":"class com.xxx.services.controllers.SessionController",
"duration":3225
}
}
此格式允许Loggly将所有日志事件与消息一起分组这是一条带有参数的日志消息
,而不管someParameter
的值是多少
它看起来是这样做的-除了编写自己的布局来执行ILogEvent对象的自定义序列化之外,是否有任何方法可以使用Logback完成此任务?有一个用于Logback的JSON logstash编码器,您可以使用为每种类型的日志消息设置一个戳,然后在日志中过滤一次
根据源代码,戳记作为单独的值存储在JSON中 这里有一个最近创建的项目,它提供了一个特定于JSON的日志API,并与SLF4J配合使用:
因此,我试图记录执行时间,我创建了一个名为ExecutionTime的pojo,其中包含名称、方法、类和持续时间 然后我就可以创建它了:
ExecutionTime time = new ExecutionTime("Controller Hit", methodName, className, sw.getTotalTimeMillis());
对于日志记录,我使用了:
private final Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info(append("metric", time), time.toString());
确保您有:
import static net.logstash.logback.marker.Markers.append;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
这将记录如下内容:
String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
"message": "This is a log message with a parameter 1234",
"level": INFO,
....
}
{
"message": "This is a log message with a parameter {}",
"level": INFO,
"parameters": [
"1234"
]
}
{
"ts":"2017-02-16T07:41:36.680-08:00",
"msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
"logger":"com.xxx.services.metrics.ExecutionTimeLogger",
"level":"INFO",
"metric":{
"name":"Controller Hit",
"method":"setupSession",
"className":"class com.xxx.services.controllers.SessionController",
"duration":3225
}
}
可能是另一种设置,因为我使用logback-spring.xml将日志输出到json:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<property name="PROJECT_ID" value="my_service"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>app/logs/${PROJECT_ID}.json.log</File>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<fieldNames>
<timestamp>ts</timestamp>
<message>msg</message>
<thread>[ignore]</thread>
<levelValue>[ignore]</levelValue>
<logger>logger</logger>
<version>[ignore]</version>
</fieldNames>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<maxIndex>10</maxIndex>
<FileNamePattern>app/logs/${PROJECT_ID}.json.log.%i</FileNamePattern>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>20MB</MaxFileSize>
</triggeringPolicy>
</appender>
<logger name="com.xxx" additivity="false" level="DEBUG">
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
</logger>
<root level="WARN">
<appender-ref ref="FILE"/>
</root>
</configuration>
app/logs/${PROJECT_ID}.json.log
ts
味精
[忽略]
[忽略]
记录器
[忽略]
10
app/logs/${PROJECT_ID}.json.log。%i
20MB
就像前面回答的那样,您将得到一个带有MDC的一维JSON树和/或使用带有logstash logback编码器的标记
如果您还需要以下信息:
- 用于定义记录的数据类型键和类型的代码簿
- 日志聚合工具的配置(如elasticsearch)
- 生成的Java帮助程序代码用于高效和正确的日志记录
logger.info(host("localhost").port(8080), "Hello world");
生成标记时,会出现如下情况。我在您的示例中看到的问题是,您不知道参数将插入消息中的何处。@LeonardBrünings这不重要,因为参数被传递到
log.log(消息,param1,param2)代码>函数。只要在插入JSON对象的数组中保持顺序,一切都很好。但是JSON中的消息没有任何占位符。如果这是故意的且不是错误,您将不知道如何呈现正确的消息。@LeonardBrünings将占位符添加到示例输出JSONYup中,这就是我们最后用来向日志消息添加任意对象的内容。您能提供示例吗?开发人员必须从MDC中添加和删除值,这并不意味着它很优雅,这是一个很好的小图书馆。我怀疑我是否会将现有项目转换为it,因为这需要相当多的工作,但我肯定会在未来的项目中牢记这一点。谢谢@MusikPolicy-我们感谢您的反馈。我现在开始一个新项目,并将尝试此功能。但是,我不确定是否可以将默认字段配置为包含在日志中(我通过Logback实现了这一点,但我不喜欢依赖MDC来输出任何字段,所以我更喜欢带有API的slf4j json logger)。其想法是在配置文件中配置一个field+值,该值将自动添加到所有生成的JSON日志行/对象中。这在slf4j json logger中可能吗?现在没有这方面的功能。应该相对容易完成。请将此作为一个问题发布到github(此处),或提交一份PR!这种方法很好,我们也尝试过,但由于库的日志消息没有格式化为JSON,因此对我们没有任何用处。它作为消息的一部分出现,作为“度量”单独的节点-打印相同的信息?有什么建议吗?我可以解决重复的问题如下。logger.info(“TROS进程更新”,追加(“trosdata”,cleanerLogData),cleanerLogData);现在消息获得值“TROS Proces Update”