将任意对象传递给Log4j中的ThreadContext.put()。

huangapple go评论77阅读模式
英文:

Passing arbitrary object to ThreadContext.put() in Log4j

问题

我想将任意对象传递给 ThreadContext.put() 方法,就像这样:

MyObject originalMessage = new MyObject(...);
ThreadContext.put("originalMessage", originalMessage);

但是该方法只允许将 String 作为其第二个参数:文档在此

在 log4j 中是否有一种方法可以在 Log4j 的 MDC 中放入任意对象?或者有其他替代方法吗?我想要的是,允许进一步执行 log.error() 来自动记录 originalMessage,而无需在每个地方都将其作为参数传递。

另外,我不能自己调用 toString(),因为这样会急切地评估该方法(该对象的计算成本相当大),所以我希望在需要时延迟其调用,就像当您将任意对象传递给 log.debug("{}",someObject) 时一样。

英文:

I want to pass an arbitrary object to the ThreadContext.put() method like this:

MyObject originalMessage = new MyObject(...);
ThreadContext.put("originalMessage", originalMessage);

But that method only allows String as its second argument: docs here.

Is there a way to put an arbitrary object in log4j in Log4j's MDC? Or an alternative to this? What I want is to allow further executions of log.error() to automatically log the originalMessage without need of passing it as a parameter everywhere.

Also, I can't invoke toString() myself as I would be eagerly evaluating that method (which is quite heavy in this object), so I want its invocation to be delayed until it's needed, just like when you pass an arbitrary object to log.debug("{}", someObject).

答案1

得分: 3

我终于在这里这里找到了一个(hack的)解决方案。

与这个(无法编译的)代码不同:

ThreadContext.put("originalMessage", originalMessage);

我可以这样做:

final var threadContextMap = (ObjectThreadContextMap) ThreadContext.getThreadContextMap();
threadContextMap.putValue("originalMessage", originalMessage);

只要你添加这个JVM选项:

-Dlog4j2.threadContextMap=org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap

现在,这看起来有些hacky,因为getThreadContextMap()方法应该返回内部映射的只读视图:

> 返回用于存储线程上下文键值对的内部数据结构的只读视图...

因此,这个解决方案将该只读映射进行了强制转换,并且在了解实现不是只读的情况下进行了修改...虽然不是最透明的解决方案,但它能够工作。

英文:

I finally found a (hack) solution here and here.

Instead of this (which doesn't compile):

ThreadContext.put("originalMessage", originalMessage);

I can do:

final var threadContextMap = (ObjectThreadContextMap) ThreadContext.getThreadContextMap();
threadContextMap.putValue("originalMessage", originalMessage);

This works as long as you add this JVM option:

-Dlog4j2.threadContextMap=org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap

Now, this looks hacky because getThreadContextMap() the method is supposed to return a read-only view of the internal map:

> Returns a read-only view of the internal data structure used to store thread context key-value pairs ...

So this solution is casting that read-only map and, knowing the implementation is not read-only, modifying it ... not the most transparent solution but it works.

huangapple
  • 本文由 发表于 2020年10月2日 02:35:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/64161350.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定