问题描述
Log4j2的JsonLayout将LogEvent内容转换为JSON,如下所示:
Java:
logger.info("This is an info message");
输出:
{
"timeMillis" : 1598613343782,"thread" : "main","level" : "INFO","loggerName" : "com.example.Test","message" : "This is an info message","endOfBatch" : false,"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger","contextMap" : { },"threadId" : 1,"threadPriority" : 5
}
但是当将对象(bean)传递给Logger
时,它将消息作为字符串吐出。
假设我的豆子是这样的:
public class MyLogBean {
private String message;
private String userId;
private String ip;
public MyLogBean(String message,String userId,String ip) {
this.message = message;
this.userId = userId;
this.ip = ip;
}
public MyLogBean() {}
public String getMessage() {return message;}
public void setMessage(String message) {this.message = message;}
public String getUserId() {return userId;}
public void setUserId(String userId) {this.userId = userId;}
public String getIp() {return ip;}
public void setIp(String ip) {this.ip = ip;}
}
然后,如果尝试使用以下内容编写MyLogBean: Java:
logger.info(new MyLogBean("UserLogged","[email protected]","192.168.1.56"));
输出:
{
"timeMillis" : 1598613343782,"message" : "com.example.MyLogBean@328cf0e1","threadPriority" : 5
}
它将"com.example.MyLogBean@328cf0e1"
打印为消息。
如何使其像这样在JSON中编写消息:
{
"timeMillis" : 1598613343782,"message" : {
"message":"UserLogged","userId":"[email protected]","ip":"192.168.1.56"
},"threadPriority" : 5
}
我需要MyLogBean
类由JsonLayout自动转换为JSON。不幸的是,默认情况下,JsonLayout使用toString
方法并将所有对象内容都放置为字符串。
我尝试通过使用Log4J Message接口实现MyLogBean
类来将其转换为JSON,但是它仍然使用字符串方法(getFormattedMessage
)。即使我使用字符串到JSON的转换器,消息再次变成字符串,输出也会变成这样:
{
"message" : "{\"message\":\"UserLogin\",\"userId\":\"john\",\"ip\":\"10.2.3.4\"}"
}
解决方法
文档说您应该这样做:
<JsonLayout objectMessageAsJsonObject="true"/>
如果在所有日志事件上都需要userId和ip,则可以将它们添加到ThreadContextMap中。然后它们将自动出现在contextMap部分中,您只需记录您的消息即可。
另一个选项是在MyLogBean()中包含toString()方法,该方法将相关字段作为JSON字符串返回。
如果您无法修改Bean类,则可以创建自己的IntrospectingMessage,该IntrospectingMessage接受Bean作为参数,并在调用getFormattedMessage时返回所有属性的JSON字符串。
,事实证明,LogstashLayout是可以解决问题的自定义布局。
- 在
"message": "${json:message:json}"
文件中写入LogstashJsonEventLayoutV1.json
。 - Java对象必须实现
MultiformatMessage
并以getFromattedMessage
方法返回JSON字符串。 -
getMessageFormats()
方法还必须返回JSON
。