记录可选键值

Rob*_*son 5 java logging logback slf4j

我有这个Web应用程序,日志记录非常繁重。我们已经实现了MDC对每个请求线程的调用,以便能够在日志中跟踪用户。

日志消息可能如下所示:

INFO  [2017-10-09 10:10:55,841] user_uuid=123-123-123 com.myapp.SomeClass: Some log message...
Run Code Online (Sandbox Code Playgroud)

现在的问题是,在大多数情况下,没有当前用户,并且user_uuid在上面的日志示例中,我们没有使用该字段。因此,它看起来像这样:

INFO  [2017-10-09 10:10:55,841] user_uuid= com.myapp.SomeClass: Some log message...
Run Code Online (Sandbox Code Playgroud)

如果没有MDC值,是否有任何方法不将MDC密钥和值写入日志?我还没有找到某些日志格式?

如果找不到MDC值,我希望它看起来像这样:

INFO  [2017-10-09 10:10:55,841] com.myapp.SomeClass: Some log message...
Run Code Online (Sandbox Code Playgroud)

上面的(MDC)示例配置如下:

%-5p [%d{ISO8601,UTC}] user_uuid=%mdc{user_uuid:-} %c: %m%n%rEx
Run Code Online (Sandbox Code Playgroud)

gly*_*ing 9

你的模式中的这个条目......

user_uuid=%mdc{user_uuid:-}
Run Code Online (Sandbox Code Playgroud)

... 由两部分组成:

  1. 静态“根”(即分配的左侧)始终存在于输出中。当 Logback 初始化自己时,决定包含它。

  2. 一个值(即赋值的右侧),只有在user_uuid填充了 MDC 属性时才会出现在输出中。在运行时为每个日志事件做出是否包含它的决定。

可能不会告诉您任何新内容,但关键是左侧的包含无法通过评估应用程序发出的每个日志事件时启动的任何条件逻辑来撤消。LogbackPatternLayoutBase遍历其给定的模式,每次遇到条件或可推导的东西时,它都会对其进行评估并将评估值附加到它正在遍历的模式中。所以,对于你的模式;在开始评估 MDC 条件之前,Logback 已经将“user_uuid=”分配给当前的 StringBuilder。

但是,您可以通过使用以下内容填充user_uuidMDC 属性实现所需的最终目标:user_uuid=<the user id>然后更改日志记录模式以仅记录 MDC 值而不进行分配。例如:

%-5p [%d{ISO8601,UTC}] %mdc{user_uuid:-}%c: %m%n%rEx
Run Code Online (Sandbox Code Playgroud)

使用该模式,以下日志调用......

logger.info("Does this include the user_uuid?");
MDC.put("user_uuid", "user_uuid=me ");
logger.info("Or does this include the user_uuid?");
Run Code Online (Sandbox Code Playgroud)

...将发出:

INFO  [2017-10-09 11:15:22,420] com.stackoverflow.SomeClassTest: Does this include the user_uuid?
INFO  [2017-10-09 11:15:22,435] user_uuid=me com.stackoverflow.SomeClassTest: Or does this include the user_uuid?
Run Code Online (Sandbox Code Playgroud)

尽管这有点尴尬,因为您必须记住在 MDC 值的末尾包含一个空格,并且此user_uuidMDC 值仅用于在此特定模式中进行日志记录(而仅包含user_uuid- 没有左侧和等于运算符 -会更普遍有用)。

如果这些缺点使这种方法对您无法使用,那么我认为您将不得不陷入 LogbackPatternLayoutBaseFormattingConverter实现某种形式的前瞻或某种方式来修改正在进行的 StringBuilder 如果赋值的右侧返回一个空字符串。


Ali*_*ean 6

如果值丢失,您可以使用空字符串%replace替换user_uuid=(注意$正则表达式中的尾随,意思是“输入结束”):

%-5p [%d{ISO8601,UTC}]%replace( user_uuid=%mdc{user_uuid}){' user_uuid=$', ''} %c: %m%n%rEx
Run Code Online (Sandbox Code Playgroud)

作为奖励,如果该值缺失,上述内容还将删除前导空格,因此如果该值缺失,您不会在日志消息中获得两个连续的空格。