I have been trying log4j2 recently. Now, I would like to test it with slf4j and wondering if all the functionality in log4j2 (e.g. async logging via disruptor) will be available if I try slf4j with log4j2. I have tried adding the slf4j jar files and log4j2 & disruptor jar files to a test project (I added the log4j-slf4j jar but not completely sure if its only meant for log4j or for log4j2 as well). When I use log4j2, I can log out statements to the log file. When I try slf4j, it does not work (and I'm not sure if its my config or the fact that slf4j is not setup to work with log4js disruptor logging? Any suggestions would be welcome. I will update the post with more info and sample code as well.
1 Answer
Yes, async loggers via the disruptor should work whether your app uses the log4j2 api, the slf4j api or the log4j-1.2 api. See the log4j2 FAQ page for which jars to include. You'll need a jar for the slf4j api, and in addition you'll need the log4j-api-2.x, log4j-core-2.x and log4j-slf4j-impl-2.x jars. The same log4j2.xml config file should work.
Update: not all Log4j2 functionality is available via the SLF4J API.
5 Comments
Remko Popma
If all loggers are made async (with system property AsyncLoggerContextSelector) then a ringbuffer with RingBufferLogEvents is preallocated, and entries are mutated as new log events come along. This is not completely garbage-free, however, as log events contain Message objects; if you call
logger.info("Some parameterized msg, param={}", someObject);, a ParameterizedMessage object is created that creates a string snapshot of the parameters. This is necessary to prevent mutable parameter objects from changing between the call to logger.info and the background thread writing to the file.Remko Popma
When using mixed Async/Sync loggers, a different ring buffer is used. In this case the ring buffer is pre-allocated with
LogEventWrapper objects that can hold standard LogEvent objects. Here a standard LogEvent object is created for each call to logger.log(...) and put into the ring buffer by setting the LogEventWrapper field. So there is a trade-off here: more flexibility but potentially a small performance loss due to more object creation. In both cases the ring buffer slots are cleared as soon as the background thread has written the log event (so objects can be GC-ed).