从多个线程进行 Java 日志记录的最佳实践?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/565893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best practices for Java logging from multiple threads?
提问by Jason S
I want to have a diagnostic log that is produced by several tasks managing data. These tasks may be in multiple threads. Each task needs to write an element (possibly with subelements) to the log; get in and get out quickly. If this were a single-task situation I'd use XMLStreamWriteras it seems like the best match for simplicity/functionality without having to hold a ballooning XML document in memory.
我想要一个由多个管理数据的任务生成的诊断日志。这些任务可能在多个线程中。每个任务都需要向日志写入一个元素(可能带有子元素);快速进出。如果这是一个单任务情况,我会使用XMLStreamWriter,因为它似乎是简单性/功能性的最佳匹配,而不必在内存中保存一个不断膨胀的 XML 文档。
But it's not a single-task situation, and I'm not sure how to best make sure this is "threadsafe", where "threadsafe" in this application means that each log element should be written to the log correctly and serially (one after the other and not interleaved in any way).
但这不是单任务情况,我不确定如何最好地确保这是“线程安全的”,其中此应用程序中的“线程安全”意味着每个日志元素都应该正确且连续地写入日志(一个在另一个并且没有以任何方式交错)。
Any suggestions? I have a vague intuition that the way to go is to use a queue of log elements (with each one able to be produced quickly: my application is busy doing real work that's performance-sensitive), and have a separate thread which handles the log elements and sends them to a file so the logging doesn't interrupt the producers.
有什么建议?我有一个模糊的直觉,要走的路是使用日志元素队列(每个元素都可以快速生成:我的应用程序正忙于执行对性能敏感的实际工作),并有一个单独的线程来处理日志元素并将它们发送到文件,以便日志记录不会中断生产者。
The logging doesn't necessarily have to be XML, but I do want it to be structured and machine-readable.
日志记录不一定必须是 XML,但我确实希望它是结构化的和机器可读的。
edit: I put "threadsafe" in quotes. Log4j seems to be the obvious choice (new to me but old to the community), why reinvent the wheel...
编辑:我将“线程安全”放在引号中。Log4j 似乎是显而易见的选择(对我来说是新的但对社区来说是旧的),为什么要重新发明轮子......
回答by jpfollenius
You could use synchronization mechanisms (like a monitor or a semaphor) to make sure, that one log request is processed before accepting the next. This could all be hidden from the code calling the logging routines.
您可以使用同步机制(如监视器或信号量)来确保在接受下一个日志请求之前处理一个日志请求。这些都可以从调用日志记录例程的代码中隐藏起来。
回答by Jens Schauder
Use a logging framework, such as Log4.
使用日志框架,例如 Log4。
and if you are not happy with the output you can write your own Appender, Filter, whatever to tweak it just write. So you could do even some caching to rearrange the entries, although I am not saying this is a good idea.
如果您对输出不满意,您可以编写自己的 Appender、过滤器,以及任何调整它的方法。所以你甚至可以做一些缓存来重新排列条目,虽然我并不是说这是一个好主意。
回答by Gareth Davis
log4j is and has been the standard for java logging for many years. But if you don't fancy an external dependency then the java.util.loggingpackage provides an acceptable solution.
log4j 多年来一直是 Java 日志记录的标准。但是如果你不喜欢外部依赖,那么java.util.logging包提供了一个可以接受的解决方案。
回答by eljenso
Use a logging framework that implements some form of the NDC pattern, like Log4J.
回答by Christian Berg
回答by Dan
I think you are on the wrong path. You say “threadsafe” but you actually mean “serialized”. Threadsafe means that one thread will not interfere with data from other thread. Most of the time, threading issues are resolved beforehand and you should not worry about it just for logging sake. For example, if your write:
我认为你走错了路。你说“线程安全”,但实际上你的意思是“序列化”。线程安全意味着一个线程不会干扰来自其他线程的数据。大多数情况下,线程问题是预先解决的,您不必仅仅为了日志记录而担心。例如,如果你写:
myVariableSum = 0 + myVariable;
//here comes other thread - Not very likely!
logger.info("Log some INFO; myVariable has value" + myVariable.toString());
You have to make sure that myVariable has not been changed by some other thread from the moment calculation (first line) was performed but before logging method was called. If this happens, you will log dirty value that was not used to perform the operation but value that was assigned by some other thread. This is generally taken care of; for example local (method level) variable can not be changed by other thread. Anyway, if you have to worry about this when logging, than 99% that your program has serious threading issues already.
All major logging frameworks are by themselves “threadsafe” meaning they can be deployed in multithreaded environments and will not display problems similar to one described above internally.
Getting traces to appear in log in order they happen is actually usually called “serialization” of calls. Serializing log writes will be a major performance bottleneck on any multithreaded app. If you use logging framework, like log4j, traces from all threads will appear in single place more or less in order they happen. However, one column is generally Thread name, so you can easily filter your log data by thread; each thread will log its data in chronological order. Check out this link:
http://logging.apache.org/log4j/1.2/faq.html#1.7
Finally, if serializing log writes is what you really need, then you could use some kind of structure, like java.util.concurrent.BlockingQueue to route your messages.
您必须确保 myVariable 从执行计算(第一行)的那一刻起但在调用日志记录方法之前没有被其他线程更改。如果发生这种情况,您将记录未用于执行操作但由其他线程分配的值的脏值。这通常会得到照顾;例如本地(方法级别)变量不能被其他线程更改。无论如何,如果您在记录时必须担心这一点,那么 99% 的情况下您的程序已经存在严重的线程问题。
所有主要的日志框架本身都是“线程安全的”,这意味着它们可以部署在多线程环境中,并且不会在内部显示与上述类似的问题。
使跟踪按发生的顺序出现在日志中实际上通常称为调用的“序列化”。序列化日志写入将成为任何多线程应用程序的主要性能瓶颈。如果您使用日志框架,如 log4j,则来自所有线程的跟踪或多或少会出现在一个地方,以便它们发生。但是,一栏一般是线程名,所以你可以很容易地按线程过滤你的日志数据;每个线程将按时间顺序记录其数据。查看此链接:http:
//logging.apache.org/log4j/1.2/faq.html#1.7
最后,如果序列化日志写入是您真正需要的,那么您可以使用某种结构,例如 java.util。 concurrent.BlockingQueue 路由您的消息。
回答by Evan
I tend to use SLF4Jon top of Log4J. The parameterized loggingfunctionality is especially attractive if you are going to have a lot of logging statements that may well get switched off in a production environment.
我倾向于在 Log4J 之上使用SLF4J。该参数记录功能是特别有吸引力,如果你将有大量的日志记录可能会得到在生产环境中关闭语句。
It can also run over the top of java.util.logging or use it's own simple output.
它也可以在 java.util.logging 的顶部运行或使用它自己的简单输出。
回答by Ceki
Use logback-classic. It is a newer and better implementation of log4j.
使用 logback-classic。它是 log4j 的更新更好的实现。
回答by JustJeff
If you had to, you could roll your own .. using single-writer/single-reader FIFO or queues.
如果必须,您可以推出自己的 .. 使用单写入器/单读取器 FIFO 或队列。