API以Json格式记录

时间:2017-08-14 20:46:53

标签: json logging 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" : "...."
  ]
}

我的问题是:

使用Logback,如何将嵌套字段(例如上面示例中的标题,标签,requestPaylod)记录为json子文档。我尝试过MDC,但它仅限于 仅限'String,String'的映射,并将第一级之后的所有字段视为String。

我讨厌为此编写我的自定义记录器,并希望使用成熟的日志记录框架(logback / log4j)来控制日志记录级别,时间戳记日志事件等。

2 个答案:

答案 0 :(得分:1)

您可以在任何Logback appender中使用logback-contrib's 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>

给出这样的日志语句......

MDC.put("header1", "headerValue1");
logger.info("hello!");
logger.info("good bye!");

... 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"}

我认为这会将您的日志事件写为JSON文档,同时仍保留Logback的行为,例如“控制日志记录级别,时间戳日志事件等”。有一些内置支持可以更改JSON格式(例如,您可以包含/排除上下文,记录器名称等),但JsonLayout类提供了一个扩展点,允许您更改属性名称通过扩展JsonLayout并覆盖toJsonMap()来生成JSON。

编辑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!");

会产生这个输出(其中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"}

答案 1 :(得分:0)

对于请求/响应日志记录,请尝试Logbooklogstash-logback-encoder。您将能够使用标记来添加结构化内容。

为了在JSON结构中添加“您自己的”字段,我编写了一个您可能感兴趣的代码生成器,它添加了构建器支持:json-log-domain