我有这个非常重要的web应用程序。我们已经为每个请求线程实现了对MDC
的调用,以便能够在我们的日志中跟踪用户。
logmessage可能如下所示:
INFO [2017-10-09 10:10:55,841] user_uuid=123-123-123 com.myapp.SomeClass: Some log message...
现在的问题是,大多数情况下,当前没有用户,并且我们没有使用上面日志示例中的user_uuid
字段。相反,它看起来像这样:
INFO [2017-10-09 10:10:55,841] user_uuid= com.myapp.SomeClass: Some log message...
有没有办法不写MDC密钥&如果没有MDC值,则在日志中的值?我还没找到一些日志格式?
如果没有找到MDC值,我希望它看起来像这样:
INFO [2017-10-09 10:10:55,841] com.myapp.SomeClass: Some log message...
以上(MDC)示例配置如下:
%-5p [%d{ISO8601,UTC}] user_uuid=%mdc{user_uuid:-} %c: %m%n%rEx
答案 0 :(得分:2)
您的模式中的此条目......
user_uuid=%mdc{user_uuid:-}
...由两部分组成:
静态根源' (即分配的左侧)这总是出现在输出中。当Logback初始化时,决定包含它。
一个值(即赋值的右侧),如果填充了MDC属性user_uuid
,则它仅出现在输出中。包含此内容的决定是在运行时为每个日志事件做出的。
可能没有告诉你任何新内容,但关键点在于,在评估应用程序发出的每个日志事件时,任何条件逻辑都无法撤消包含左侧的内容。 Logback的PatternLayoutBase
遍历其给定的模式,每当它涉及条件或可派生的某些内容时,它会对其进行评估并将评估值附加到它正在遍历的模式中。所以,对于你的模式; Logback已经分配了" user_uuid ="到目前的StringBuilder开始评估MDC条件之前。
但是,可以 通过使用user_uuid
填充user_uuid=<the user id>
MDC属性来实现所需的最终目标,然后将您的日志记录模式更改为只记录MDC值而不使用分配。例如:
%-5p [%d{ISO8601,UTC}] %mdc{user_uuid:-}%c: %m%n%rEx
使用该模式进行以下日志调用...
logger.info("Does this include the user_uuid?");
MDC.put("user_uuid", "user_uuid=me ");
logger.info("Or does this include the user_uuid?");
...将发出:
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?
虽然这有点尴尬,因为你必须记住在MDC值的末尾包含一个空格,这个user_uuid
MDC值只对在这个特定模式中记录有用(而只是包括user_uuid
- 没有左侧和等于运算符 - 通常会更有用。)
如果这些缺点导致这种方法对您无法使用,那么我认为您必须陷入Logback的PatternLayoutBase
或FormattingConverter
以实现某种形式的预测或如果赋值的右侧返回一个空字符串,则修改正在进行的StringBuilder的某种方法。
答案 1 :(得分:0)
如果缺少值,则可以使用%replace
用空字符串替换user_uuid=
(请注意正则表达式中的尾随$
,表示“输入结束”):>
%-5p [%d{ISO8601,UTC}]%replace( user_uuid=%mdc{user_uuid}){' user_uuid=$', ''} %c: %m%n%rEx
此外,如果缺少该值,上述内容还将删除前导空格,因此,如果缺少该值,则不会在日志消息中连续出现两个空格。