If you have ever had to analyze problems in production, I believe you know how important it is to have a good log record. Good logging requires three things:
- Log messages need to provide the information needed to understand what the application is doing internally.
- Writing log messages must be as efficient as possible so as not to affect the performance of the application.
- You need to be able to adapt log details to different deployment environments and situations.
Although you still need to decide which log messages should be written for each use case, you don't have to worry about requirements 2 and 3. Various logging frameworks have addressed these technical requirements. You only need to select one of them and use it to write log messages.
To make it better, SLF4J provides a standardized API that is implemented by most frameworks in one way or another. This allows you to change the logging framework without changing the code. You only need to change the dependency to a different framework that implements the SLF4J interface.
Write log messages using SLF4J
Writing log messages using SLF4J is very simple. First, you need to call LoggerFactory on the getLogger method to instantiate a new Logger object. You can then call one of the debug, info, warning, error, or fatal methods on the Logger to write log messages with the corresponding log level. Here you can see a typical example:
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088">public </span><span style="color:#000088">class </span><span style="color:#660066">MyClass </span><span style="color:#666600">{ </span><span style="color:#660066">Logger </span><span style="color:#000000">log </span><span style="color:#666600">= </span><span style="color:#660066">LoggerFactory </span><span style="color:#666600">. </span><span style="color:#000000">getLogger </span><span style="color:#666600">(</span><span style="color:#000088">this</span><span style="color:#666600">. </span><span style="color:#000000">of getClass </span><span style="color:#666600">(). </span><span style="color:#000000">of getName </span><span style="color:#666600">());</span> <span style="color:#000088">public</span><span style="color:#000088">invalid</span><span style="color:#000000">myMethod of</span><span style="color:#666600">()</span><span style="color:#666600">{</span><span style="color:#000000"> record</span><span style="color:#666600">. </span><span style="color:#000000">info </span><span style="color:#666600">( </span><span style="color:#008800">"This is an informational message" </span><span style="color:#666600">); </span><span style="color:#880000">// ... </span><span style="color:#666600">} </span><span style="color:#666600">}</span> </span></span></span>
So, if these frameworks can be easily interchanged, which one should you choose?
The answer to this question is not as easy as you think. Several frameworks are widely used in the Java world. In this article, I want to introduce you to Log4j and its two successors, Logback and Log4j2.
Apache Log4j
Apache Log4j Is a very old logging framework, which has been the most popular framework for many years. It introduces the basic concepts still in use in modern logging frameworks, such as hierarchical logging levels and recorders.
The development team announced the end of Log4j's life cycle in 2015. Although many legacy projects still use it, if you start a new project, you should prefer one of the other frameworks discussed in this article.
Matt is here In previous articles Log4j has been explained in great detail , You can use the slf4 japi I showed you earlier to write log messages using log4j. Therefore, before talking about Logback and Log4j2, let's quickly browse the required dependencies and configurations.
Required dependencies
If you want to use Log4j in your application, you need to add the log4j.jar file to your classpath. You can see the required Maven dependencies in the following code snippet.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">log4j </span><span style="color:#000088"></groupId> </span><span style="color:#000088"><artifactId> </span><span style="color:#000000">log4j </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><version> </span><span style="color:#000000">1.2.17 </span><span style="color:#000088"></version> </span><span style="color:#000088"></dependency></span> </span></span></span>
Log4j itself does not support SLF4J. You also need to add the following dependencies to use log4j through the standardized interface.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">org.slf4j </span><span style="color:#000088"></groupId> </span><span style="color:#000088"><artifactId> </span><span style="color:#000000">slf4j-log4j12 </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><scope> </span><span style="color:#000000">test </span><span style="color:#000088"></scope> </span><span style="color:#000088"></dependency></span> </span></span></span>
Configure Log4j
In addition to the log4j.jar file, you also need to define additional programs and loggers and their log levels in the log4j.properties file. appender writes log messages to a destination, such as a file or database. The logger and level define the granularity of log messages written to the log file.
The following code snippet shows the implementation of an application development system using Hibernate as an object relational mapper Typical Log4j configuration . It writes all log messages to the file app.log and sets the general log level to INFO. The configuration also sets the log level of recorder org.hibernate.SQL to DEBUG and the category org.hibernate.type.descriptor.sql to TRACE. These are the two recorders of Hibernate, which write the executed SQL statements and their binding parameter values to the configuration file appender.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000000">Log 4 j </span><span style="color:#666600">. </span><span style="color:#000000">Additional program</span><span style="color:#666600">. </span><span style="color:#000000">file</span><span style="color:#666600">=</span><span style="color:#000000">organization</span><span style="color:#666600">. </span><span style="color:#000000">Apache</span><span style="color:#666600">. </span><span style="color:#000000">Log 4 j </span><span style="color:#666600">. </span><span style="color:#660066">FileAppender </span><span style="color:#000000"> log4j </span><span style="color:#666600">. </span><span style="color:#000000">Additional program</span><span style="color:#666600">. </span><span style="color:#000000">file</span><span style="color:#666600">. </span><span style="color:#660066">file</span><span style="color:#666600">=</span><span style="color:#000000">application program</span><span style="color:#666600">. </span><span style="color:#000000 "> log Log 4 j </span><span style="color:#666600">. </span><span style="color:#000000">Additional program</span><span style="color:#666600">. </span><span style="color:#000000">file</span><span style="color:#666600">. </span><span style="color:#000000">layout</span><span style="color:#666600">=</span><span style="color:#000000">organization</span><span style="color:#666600">. </span><span style="color:#000000">Apache</span><span style="color:#666600">. </span><span style="color:#000000">Log 4 j </span><span style="color:#666600">. </span><span style="color:#660066">Pattern layout</span><span style="color:#000000"> log4j </span><span style="color:#666600">. </span><span style="color:#000000">Additional program</span><span style="color:#666600">. </span><span style="color:#000000">file</span><span style="color:#666600">. </span><span style="color:#000000">layout</span><span style="color:#666600">. </span><span style="color:#660066">ConversionPattern </span><span style="color:#666600">=% </span><span style="color:#000000">d </span><span style="color:#666600">{ </span><span style="color:#000000">HH </span><span style="color:#666600">: </span><span style="color:#000000">mm </span><span style="color:#666600">: </span><span style="color:#000000">ss </span><span style="color:#666600">, </span><span style="color:#000000">SSS </span><span style="color:#666600">} </span><span style="color:#666600">%- </span><span style="color:#006666">5p </span><span style="color:#666600">[% </span><span style="color:#000000">c </span><span style="color:#666600">] </span><span style="color:#666600">- </span><span style="color:#666600">% </span><span style="color:#000000">m </span><span style="color:#666600">% </span><span style="color:#000000">n</span> <span style="color:#000000"> Log 4 j </span><span style="color:#666600">. </span><span style="color:#000000">rootLogger </span><span style="color:#666600">= </span><span style="color:#000000">info </span><span style="color:#666600">, </span><span style="color:#000000">file </span><span style="color:#880000"># Basic log level for all messages</span><span style="color:#000000"> log4j </span><span style="color:#666600">. </span><span style="color:#000000">Recorder</span><span style="color:#666600">. </span><span style="color:#000000">organization</span><span style="color:#666600">. </span><span style="color:#000000">dormancy</span><span style="color:#666600">=</span><span style="color:#000000 "> information </span><span style="color:#880000"># SQL Statements and parameters</span><span style="color:#000000"> log4j </span><span style="color:#666600">. </span><span style="color:#000000">Recorder</span><span style="color:#666600">. </span><span style="color:#000000">organization</span><span style="color:#666600">. </span><span style="color:#000000">dormancy</span><span style="color:#666600">. </span><span style="color:#000000">SQL </span><span style="color:#666600">=</span><span style="color:#000000 "> debugging Log 4 j </span><span style="color:#666600">. </span><span style="color:#000000">Recorder</span><span style="color:#666600">. </span><span style="color:#000000">organization</span><span style="color:#666600">. </span><span style="color:#000000">dormancy</span><span style="color:#666600">. </span><span style="color:#000000">input</span><span style="color:#666600">. </span><span style="color:#000000">descriptor </span><span style="color:#666600">. </span><span style="color:#000000">sql </span><span style="color:#666600">=</span><span style="color:#000000 "> tracking</span></span></span></span>
Based on this configuration, you can write log messages using the SLF4J API. Now is all about Log4j. If you want more information, please check Matt Watson's Ultimate Log4j tutorial.
Sign in
Logback was written by the same developer who implemented Log4j with the goal of becoming its successor. It follows the same concept as Log4j, but has been rewritten to improve performance, support SLF4J natively, and implement Other improvements, Such as automatic reload of advanced filtering options and log configuration.
The framework consists of three parts:
- logback core
- logback classic
- Login access
Logback core provides the core functions of the log framework. Logback classic adds more features to core functions, such as native support for SLF4J. And logback access integrates it with the servlet container so that you can use it to write HTTP access logs.
Required dependencies
You only need to define the dependency on logback classic. It includes dependencies on logback core and slf4j APIs.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">ch.qos.logback </span><span style="color:#000088"></groupId> </span><span style="color:#000088"><artifactId> </span><span style="color:#000000">logback-classic </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><version> </span><span style="color:#000000">1.2.3 </span><span style="color:#000088"></version> </span><span style="color:#000088"></dependency></span> </span></span></span>
Configure rollback
Logback does not require any configuration. By default, it writes all log messages at debug level or higher to standard output. You can make changes using a custom configuration file in XML or Groovy format.
Logback uses the same concept as Log4j. Therefore, it is not surprising that even if they use different file formats, their configurations are very similar. The following code snippet shows the same configuration that I used in Log4j.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><configuration> </span><span style="color:#000088"><appender </span><span style="color:#660066">name </span><span style="color:#666600">= </span><span style="color:#008800">"FILE" </span><span style="color:#660066">class </span><span style="color:#666600">= </span><span style="color:#008800">"ch.qos.logback.core.FileAppender" </span><span style="color:#000088">> </span><span style="color:#000088"><file> </span><span style="color:#000000">app.log </span><span style="color:#000088"></file> </span><span style="color:#000088"><encoder> </span><span style="color:#000088"><pattern> </span><span style="color:#000000">%d{HH:mm:ss,SSS } %-5p [%c] - %m%n </span><span style="color:#000088"></pattern> </span><span style="color:#000088"></encoder> </span><span style="color:#000088"></appender> </span><span style="color:#000088"><logger </span><span style="color:#660066">name </span><span style="color:#666600">= </span><span style="color:#008800">"org.hibernate.SQL" </span><span style="color:#660066">level </span><span style="color:#666600">= </span><span style="color:#008800">"DEBUG" </span><span style="color:#000088">/> </span><span style="color:#000088"><logger </span><span style="color:#660066">name </span><span style="color:#666600">= </span><span style="color:#008800">"org. hibernate.type.descriptor.sql" </span><span style="color:#660066">level </span><span style="color:#666600">= </span><span style="color:#008800">"TRACE" </span><span style="color:#000088">/> </span><span style="color:#000088"><root</span><span style="color:#660066">level</span><span style="color:#666600">= </span><span style="color:#008800">"information" </span><span style="color:#000088">> </span><span style="color:#000088"><appender-ref </span><span style="color:#660066">ref</span> <span style="color:#666600">= </span><span style="color:#008800">"file" </span><span style="color:#000088">/> </span><span style="color:#000088"></root> </span><span style="color:#000088"></configuration></span> </span></span></span>
After adding the required dependencies and configuring Logback, you can use it to write log messages through the SLF4J API. Therefore, if you want to benefit from the improvements provided by Logback, you can replace Log4j with Logback without changing any code.
Now let's take a look at Log4j2. If you want to know more about Logback, please check Eugen In depth articles on this.
Apache Log4j2
Apache Log4j2 It is the youngest of the three frameworks. Its goal is to improve the two frameworks by providing its own improvements to Log4j, including some improvements contained in Logback and avoiding the problems of Log4j and Logback.
Therefore, like Logback, Log4j2 provides support for SLF4J, automatically reloads your logging configuration, and supports advanced filtering options. In addition to these features, it also allows latency evaluation of log statements based on lambda expressions, providing support for low latency systems Asynchronous recorder And provide no Garbage mode To avoid any delays caused by garbage collector operations.
All these features make Log4j2 In these three log frames State of the art and Fastest.
Required dependencies
Log4j2 packages its API and implementation in two separate jar files. You can use log4j-api.jar to implement and build your application, and you need to provide additional log4j-core.jar at runtime. If you want to use the slf4 API, you also need the log4j-slf4j-impl.jar file, which contains the bridge between the two APIs.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">org.apache.logging.log4j </span><span style="color:#000088"></groupId> </span><span style="color:#000088"><artifactId> </span><span style="color:#000000">log4j-api </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><version> </span><span style="color:#000000">2.11.1 </span><span style="color:#000088"></version> </span><span style="color:#000088"></dependency> </span><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">org.apache .logging.log4j </span><span style="color:#000088"></groupId> </span><span style="color:#000088"><artifactId> </span><span style="color:#000000">log4j-core </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><version> </span><span style="color:#000000">2.11.1 </span><span style="color:#000088"></version> </span><span style="color:#000088"></dependency> </span><span style="color:#000088"><dependency> </span><span style="color:#000088"><groupId> </span><span style="color:#000000">org.apache.logging.log4j </span><span style="color:#000088"></groupId> </span><span style="color:#000088">< artifactId> </span><span style="color:#000000">log4j-slf4j-impl </span><span style="color:#000088"></artifactId> </span><span style="color:#000088"><version> </span><span style="color:#000000">2.11. 1 </span><span style="color:#000088"></version> </span><span style="color:#000088 "> < / dependency ></span> </span></span></span>
Configure Log4j2
The configuration of Log4j2 follows the same principles as the previous two log frameworks, so it looks very similar.
<span style="color:#000000"><span style="color:#555555"><span style="background-color:#f7f7f9"><span style="color:#000088"><structure</span><span style="color:#660066">state</span><span style="color:#666600">= </span><span style="color:#008800">""Information" </span><span style="color:#000088">> </span><span style="color:#000088"><Additional destinations> </span><span style="color:#000088"><file</span><span style="color:#660066">name</span><span style="color:#666600">= </span><span style="color:#008800">"FILE"</span><span style="color:#660066">file name</span><span style="color:#666600">= </span><span style="color:#008800">"app.log" </span><span style="color:#000088">> </span><span style="color:#000088"><of PatternLayout</span><span style="color:#660066">pattern</span><span style="color:#666600">= </span><span style="color:#008800">"%d {HH: MM: SS.SSS} [%T]%-5level% logger{36} - %msg%n" </span><span style="color:#000088">/> </span><span style="color:#000088"></File> </span><span style="color:#000088"></Appenders> </span><span style="color:#000088"><Loggers> </span><span style="color:#000088"><Logger </span><span style="color:#660066">name </span><span style="color:#666600">= </span><span style="color:#008800">"org.hibernate.SQL" </span><span style="color:#660066">level </span><span style="color:#666600">= </span><span style="color:#008800">"DEBUG" </span><span style="color:#000088">> </span><span style="color:#000088"><AppenderRef </span><span style="color:#660066">ref </span><span style="color:#666600">= </span><span style="color:#008800">"FILE" </span><span style="color:#000088">/> </span><span style="color:#000088">< /Recorder> </span><span style="color:#000088"><Recorder</span><span style="color:#660066">name</span><span style="color:#666600">= </span><span style="color:#008800">"org.hibernate.type.descriptor.sql"</span><span style="color:#660066">level</span><span style="color:#666600">=</span> <span style="color:#008800">"TRACE" </span><span style="color:#000088">> </span><span style="color:#000088"><AppenderRef </span><span style="color:#660066">ref </span><span style="color:#666600">= </span><span style="color:#008800">"FILE" </span><span style="color:#000088">/> </span><span style="color:#000088"></Logger> </span><span style="color:#000088"><Root </span><span style="color:#660066">level </span><span style="color:#666600">= </span><span style="color:#008800">"info" </span><span style="color:#000088">> </span><span style="color:#000088"><AppenderRef </span><span style="color:#660066">ref </span><span style="color:#666600">= </span><span style="color:#008800">"FILE" </span><span style="color:#000088">/> </span><span style="color:#000088"></Root> </span><span style="color:#000088"></Loggers> </span><span style="color:#000088"></Configuration></span> </span></span></span>
conclusion
Log4j, Logback and Log4j2 are excellent logging frameworks that are widely used. So which one should you use?
I recommend Log4j2 because it is the fastest and most advanced of the three frameworks. If performance is not your highest priority, Logback is still a good choice.