英文:
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
与这个(无法编译的)代码不同:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论