kir*_*ran 8 logging json logback mdc
我想将API请求/响应记录为json格式.
预期的LogEntry是这样的
{
"timestamp" : "...",
"level" : "DEBUG",
"headers" : [
"header1" : "value1",
"header2" : "value2",
"header3" : "value3"
],
"requestPayload" : "<Request Json>" // prefereablly as sub-document, worst case string is fine.
"labels" : [ //key fields which can be used for searching the logentry
"searchField1" : "....",
"searchField2" : "....",
"searchField3" : "...."
]
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
使用Logback,如何记录嵌套字段(例如上面示例中的标题,标签,requestPaylod),作为json子文档.我尝试过MDC,但它仅限于'String,String'的Map,并将第一级之后的所有字段视为String.
我讨厌为此编写我的自定义记录器,并希望使用成熟的日志记录框架(logback/log4j)的优点来控制日志记录级别,时间戳记日志事件等.
您可以在任何 Logback Appender 中使用logback-contrib JsonLayout。例如:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>false</prettyPrint>
</jsonFormatter>
<timestampFormat>yyyy-MM-dd' 'HH:mm:ss.SSS</timestampFormat>
<appendLineSeparator>true</appendLineSeparator>
</layout>
</appender>
Run Code Online (Sandbox Code Playgroud)
给定这样的日志语句......
MDC.put("header1", "headerValue1");
logger.info("hello!");
logger.info("good bye!");
Run Code Online (Sandbox Code Playgroud)
...使用JsonLayout将导致 Logback 写入以下内容:
{"timestamp":"2017-08-15 09:06:41.813","level":"INFO","thread":"main","mdc":{"header1":"headerValue1"},"logger":"com.stackoverflow.logback.LogbackTest","message":"hello!","context":"default"}
{"timestamp":"2017-08-15 09:06:41.887","level":"INFO","thread":"main","mdc":{"header1":"headerValue1"},"logger":"com.stackoverflow.logback.LogbackTest","message":"good bye!","context":"default"}
Run Code Online (Sandbox Code Playgroud)
我认为这符合将日志事件编写为 JSON 文档的要求,同时仍然保留 Logback 的行为,例如“控制日志记录级别、为日志事件添加时间戳等”。有一些内置支持更改 JSON 格式(例如,您可以包含/排除上下文、记录器名称等),但 JsonLayout 类提供了一个扩展点,允许您通过扩展和覆盖来更改结果 JSON 中的属性名称。 JsonLayouttoJsonMap()
编辑1:解决您的回复(“我的问题更多的是如何实现提到的json子文档/嵌套。MDC仅限于映射”)...您可以将复杂的MDC值序列化为JSON并添加序列化的JSON表示到MDC。例如:
Map<String, Object> complexMdcValue = new HashMap<>();
Map<String, Object> childMdcValue = new HashMap<>();
childMdcValue.put("name", "Joe");
childMdcValue.put("type", "Martian");
complexMdcValue.put("child", childMdcValue);
complexMdcValue.put("category", "etc");
MDC.put("complexNestedValue", objectMapper.writeValueAsString(complexMdcValue));
logger.info("hello!");
Run Code Online (Sandbox Code Playgroud)
将产生以下输出(其中 MVC 记录的键“complexNestedValue”是包含子文档的 JSON):
{"timestamp":"2017-08-27 18:03:46.706","level":"INFO","thread":"main","mdc":{"complexNestedValue":"{\"category\":\"etc\",\"child\":{\"name\":\"Joe\",\"type\":\"Martian\"}}"},"logger":"com.stackoverflow.logback.LogbackTest","message":"hello!","context":"default"}
Run Code Online (Sandbox Code Playgroud)