Logging is required in any application that we write. This is one of the most common components that developers across different industries are required to understand. Long running systems are more understandable and maintainable if logging is done correctly within these systems. Some of the important reasons I find logging useful:
During Development
- To allow debugging programs especially for distributed systems.
- To quickly identify the failure point within a system.
- To understand the code flow for a given system capability.
During Production - To register anomalies with in the system.
- To register temporary failures
- To register permanent failures
- To provide information regarding any of the above events so that developers / dev-ops can gather enough context to understand why they happened.
To allow to infer the above information, the logging systems generally provide the following capabilities:
Allow formatting the message such that, most commonly required fields like time / source of message are printed along with the message, without the developer being required to provide this every time he tries to log a message. This allows developers concentrate on the important bits of the message throughout the development of the system. It also allows them to create a representation of the message that would the application most. For Ex: some developers might print time at the beginning of every message, others might prefer the class / source of the message.
Custom destinations to write messages to. Most basic destinations provided by all logging systems are System Console and A File at some location. A few other common destinations are Databases , network service etc.
Ability to control the flow of information / messages to various destinations. This most commonly accomplished by assigning a priority to the message and then filtering messages to a given destination based on what the destination accepts.
Ability to configure different destinations for different messages, different priorities.
A stand alone library / component that can be easily integrated into any system without affecting other dependencies of the system.
I am going to discuss a few ways of using the log4j2 library using 2.7 version. The log4j2 documentation is a great place to get detailed information about how to use the log4j2 system. I am going to list down some of the common modes of configuring log4j2 for different scenarios, they will be listed from simple → complex. I am going to use maven for building the project.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
All configurations for log4j are done using log4j2.xml. To start off the initial log4j2.xml is as below:
<Configuration status="debug">
<Appenders>
<File name="file-log" fileName="/tmp/logging.out" append="false">
<PatternLayout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %C - %msg%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="com.anishek" level="info" additivity="false">
<appender-ref ref="file-log" level="info"/>
</Logger>
</Loggers>
</Configuration>