About
Log4j is a debugging logger.
version:
- 1.2 (2015 switch to 2.x)
Dependency
dependencies {
compile 'org.apache.logging.log4j:log4j-api:2.13.0'
compile 'org.apache.logging.log4j:log4j-core:2.13.0'
}
Usage
Get a logger
- The name of this Logger will be the full qualified class name or where it reside. If the class is located at “com.example.app.MyClass”, the name will be the same
protected static final Logger parentLogger = LogManager.getLogger();
Concept
Markers
markers (log4j.Marker class) are objects that are used to add easily filterable information to log messages. Markers can be hierarchical - each Marker may have a parent. This allows for broad categories being subdivided into more specific categories. An example might be a Marker named “Error” with children named “SystemError” and “ApplicationError”.
Markers must be unique.
// A parent
Marker SQL_MARKER = MarkerManager.getMarker("SQL");
// A query marker
Marker QUERY_MARKER = MarkerManager.getMarker("SQL_QUERY").setParents(SQL_MARKER);
// A debug message with a marker
logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
Configuration
Set
By default, Log4j looks for a configuration file named log4j2.xml (not log4j.xml) in the classpath.
The order on how log4j search the configuration can be found in the AutomaticConfiguration section
- First via a java property:
-Dlog4j.configuration=file:/etc/schema-registry/log4j.properties
File
Format supported:
- properties
- xml
- yaml
xml
The default configuration xml would look like that.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Code
public class Main
{
private final static Logger logger = Logger.getLogger(Main.class);
public static void main(final String[] args) throws Exception
{
// Minimal Configuration
System.setProperty("log4j.debug","true");
org.apache.log4j.BasicConfigurator.configure();
if (args.length != 1)
{
logger.error("Please provide an argument");
return;
}
...
Example
How to dynamically create different log file
see Log4j - How to route message to log file created dynamically
Multiple Thread Programmatic
A constructor code where the logger is declared as class variable private Logger threadLogger
// Logger Name is normally hierarchic "com.foo.bar"
// We add the thread name
String loggerName = QueryExecutor.class.getCanonicalName()+"."+threadName;
LOGGER = Logger.getLogger(loggerName);
// Log4j properties
Properties log4jProp = new Properties();
// Once a message is accepted by the logger,
// it's sent to one or several appenders (to a file, to the console, to a mail server, etc.).
final String appenderName = "FileAppender";
// Set logger level to DEBUG and its only appender.
log4jProp.setProperty("log4j.logger."+loggerName, "DEBUG, " + appenderName);
// File Appender
log4jProp.setProperty("log4j.appender." + appenderName,"org.apache.log4j.FileAppender");
// Properties are the set method (File equivalent to setFile)
String timeStamp = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date());
String logFileName = loggerName+"_"+timeStamp+".log";
log4jProp.setProperty("log4j.appender." + appenderName + ".File", logFileName);
// Above Warning
// The levels of logging are TRACE, DEBUG, INFO, WARN, ERROR and FATAL.
// See org.apache.log4j.Level
log4jProp.setProperty("log4j.appender." + appenderName + ".Threshold","WARN");
// Layout is org.apache.log4j.PatternLayout
log4jProp.setProperty("log4j.appender." + appenderName + ".layout","org.apache.log4j.PatternLayout");
// See org.apache.log4j.PatternLayout#setConversionPattern date in ISO 8601 format, thread name, level, logger, message
log4jProp.setProperty("log4j.appender." + appenderName + ".layout.ConversionPattern","%d [%t] %-5p %c - %m%n");
PropertyConfigurator.configure(log4jProp);
Dynamic with Builder
Note that a rolling file appender added this way cannot use lookup value
RollingFileAppender rollingFileAppender = RollingFileAppender.newBuilder()
.withCreateOnDemand(true)
.setName("analytics-" + contextEventFileNameExpression)
.withFileName("logs/analytics.jsonl")
.withFilePattern("logs/analytics/$${date:yyyy-MM}/analytics-%d{yyyy-dd-MM}-%i.jsonl")
.setIgnoreExceptions(false)
.setFilter(
ThresholdFilter.createFilter(
Level.INFO,
Filter.Result.ACCEPT,
Filter.Result.DENY)
)
.setLayout(
PatternLayout
.newBuilder()
.withPattern("%m%n")
.build()
)
.withPolicy(
/**
* It causes a rollover once the date/time pattern no longer applies to the active file.
* https://logging.apache.org/log4j/2.x/manual/appenders.html#timebased-triggering-policy
*/
TimeBasedTriggeringPolicy
.newBuilder()
.build()
)
.setConfiguration(config)
.build();
config.addAppender(rollingFileAppender);