在 log4j Appender 中记录时的循环依赖

发布于 2024-11-14 20:09:02 字数 270 浏览 8 评论 0原文

我正在编写一个 log4j 附加程序,它通过 http 将日志发送到服务器。我想使用 apache-commons 中的 HttpClient 来保持我的代码美观且简单。

现在的问题是 HttpClient 和 Co. 使用 log4j 本身。通常是一件好事,但是当从 log4j 附加程序实现中调用它们时,会引入循环引用或无限循环,最终导致 OutOfMemoryException。

当然,我可以在没有任何第三方库的情况下编写我想要的内容,但我只是想知道是否有已知的解决方案来解决此类问题?

I am writing a log4j appender that sends the logs to a server via http. I wanted to use HttpClient from apache-commons to keep my code nice and simple.

The problem now is that HttpClient and Co. uses log4j itself. Usually a good thing but when calling them from within a log4j appender implementation, circular references or endless loops are introduced, ultimately leading to an OutOfMemoryException.

Of course I can write what I want without any thrid-party libraries but I just wondered if there is known solution to this kind of problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

奢欲 2024-11-21 20:09:02

这是一个很好的问题!遗憾的是 log4j 没有尝试在这里帮助您。但我们可以狡猾地使用 log4j 来修复 log4j!重要的概念是诊断上下文

private static final String IN_APPEND_KEY = MyAppender.class.getName() + ".inAppend";
public void append(LoggingEvent e) {
    if (e.getMDC(IN_APPEND_KEY) != null) return;
    MDC.put(IN_APPEND_KEY, this);
    try {
        <your code here>
    } finally {
        MDC.remove(IN_APPEND_KEY);
    }
}

:基本上想要设置一个标志,它将随着附加程序的执行流程“旅行”。至少在理论上,这正是诊断环境的作用。它是线程本地的并且跨线程继承。精心编写的代码甚至可以跨其他边界(例如消息队列)保留上下文。那该有多酷:您的附加程序将日志消息放在 HTTP 请求队列中,队列保存诊断上下文并在请求运行时恢复它,HTTP 库记录错误,并且您的附加程序仍然检测到循环!这几乎是你能要求的最好的事情了。

This is a great question! It's a shame that log4j doesn't try to help you here. But we can be devious and use log4j to fix log4j! The important concept is a Diagnostic Context:

private static final String IN_APPEND_KEY = MyAppender.class.getName() + ".inAppend";
public void append(LoggingEvent e) {
    if (e.getMDC(IN_APPEND_KEY) != null) return;
    MDC.put(IN_APPEND_KEY, this);
    try {
        <your code here>
    } finally {
        MDC.remove(IN_APPEND_KEY);
    }
}

You basically want to set a flag that will "travel" with the execution flow of your appender. This is exactly what a diagnostic context does, in theory at least. It is thread-local and inherited across threads. Carefully-written code will even preserve the context across other boundaries, such as a message queue. How cool would that be: your appender puts the log message on an HTTP request queue, the queue saves the diagnostic context and restores it when request gets run, the HTTP library logs an error, and your appender still detects the loop! It's pretty much the best thing you could ask for.

短暂陪伴 2024-11-21 20:09:02

为什么 Apache HttpClient 的记录器使用您的 Appender ?给它另一个Appender,控制台什么的。

Why does the logger from Apache HttpClient uses your Appender ? Give it another Appender, Console or something.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文