[Log] Log framework JUL and Log4j in Java

Existing log framework:

  1. Log facade: JCL (Jakarta Common Logging), SLF
  2. Log implementation: JUL (Java Util Logging), log4j, logback, log4j2

1. JUL learning

1.1 JUL introduction

JUL: the full name is Jakarta Common Logging. It is a Java Native logging framework. It does not need to introduce a third-party class library. Compared with other logging frameworks, it is easy to use and learn, and can be used flexibly in small applications.

framework:

  • Loggers: loggers. The application obtains the Logger object and calls its API to publish log information. The Logger object is usually the entry program for the application to access the logging system;
  • Appenders: also known as handlers. Each Logger is associated with a set of handlers. The Logger will hand over the log to the associated handlers, who are responsible for recording the log. Handlers are abstract here. Its specific implementation determines that the location of logging can be console, file, etc;
  • Layouts: also known as Formatters. It is responsible for converting and formatting the data in log events. Layouts determines the final form of data in a log record;
  • Level: each log message has an associated log level. This level provides a rough guide to the importance and urgency of log messages. Level can be associated with Loggers and Appenders to facilitate us to filter messages;
  • Filters: filters. Customize which messages will be recorded and which messages will be let go as needed.

[summary]: the user uses the Logger to record logs. The Logger holds multiple Handlers, and the log output operation is completed by the Handler. Before the Handler outputs logs, it will be filtered by Filters to determine which log levels are released and which log levels are intercepted. The Handler will output the log contents to the specified location (console / file). When outputting logs, the Handler will use Layout to typeset the output content.

1.2 quick start

Create a new SpringBoot project and introduce a junit dependency. POM file:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
</dependency>

Introductory case:

public class JulTest {

	public static final String CALSS_NAME = "com.zzc.sbexp.log.jul.JulTest";

    @Test
    public void testQuick() {
        Logger logger = Logger.getLogger(CALSS_NAME);
        // Output log level: info
        logger.info("hello jul");

        // Output by method
        logger.log(Level.INFO, "hello jul");

        // Output variable values through placeholders
        String name = "zzc";
        Integer age = 24;
        logger.log(Level.INFO, "User information:{0}, {1}", new Object[]{name, age});
    }

}

1.3 log level

Log level from high to low: off, server, warning, info, config, fine, finer, finest, all

If yes: off, the log level output is turned off;
If it is: all, then log level output is enabled.

The default level of Jul is info. As long as the log level is higher than info, it will be output.

Custom log level:

Steps:

  1. Turn off system default configuration
  2. Create a Handler. Here I output to the console and disk, so it is ConsoleHandler and FileHandler;
  3. Create a Formatter;
  4. Associate the Handler with the Formatter;
  5. Add the Handler to the Logger.
@Test
public void testLogConfig() throws IOException {
    Logger logger = Logger.getLogger(CALSS_NAME);
    // Turn off system default configuration
    logger.setUseParentHandlers(false);
    // Create console output Handler
    ConsoleHandler consoleHandler = new ConsoleHandler();
    SimpleFormatter simpleFormatter = new SimpleFormatter();
    // relation
    consoleHandler.setFormatter(simpleFormatter);
    // Create file output Handler
    FileHandler fileHandler = new FileHandler("logs.log");
    fileHandler.setFormatter(simpleFormatter);

    logger.addHandler(consoleHandler);
    logger.addHandler(fileHandler);
    // Configure log level
    logger.setLevel(Level.ALL);
    consoleHandler.setLevel(Level.ALL);
    fileHandler.setLevel(Level.WARNING);

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
}

[note]: the parent path of logs.log must exist, otherwise an error will be reported.

To modify the default configuration of RootLogger from a custom configuration file:

Add a configuration file logging.properties under the resource path, which contains:

#RootLogger is the default processor. You can configure multiple processors. All child logs that do not manually release the parent log will use these processors
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

#The log level of RootLogger (default INFO). All handlers are limited to this log level. The log level of Handler can be higher than that of RootLogger
.level = INFO

java.util.logging.FileHandler.pattern = E:/logs/java%u.log
#The size of a single log file, in bits, 1024bit is 1kb
java.util.logging.FileHandler.limit = 1024 * 1024 * 10
#Number of log files
java.util.logging.FileHandler.count = 1
#Whether to add log content by appending
java.util.logging.FileHandler.append = true
java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.encoding = UTF-8
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

code:

@Test
public void testLogProperties() throws IOException {
    // Loading configuration files through classes
    InputStream in = JulTest.class.getClassLoader().getResourceAsStream("logging.properties");
    // Create LogManger load profile
    LogManager logManager = LogManager.getLogManager();
    logManager.readConfiguration(in);
    Logger logger = Logger.getLogger(CALSS_NAME);

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
    logger.finest("finest");
}

To add a custom Logger to a custom profile:

Add a configuration file logging.properties under the resource path, which contains:

...

my.logger.handlers = java.util.logging.ConsoleHandler
my.logger.level = INFO
my.logger.useParentHandlers = false

code:

@Test
public void testMyLogProperties() throws IOException {
    // Loading configuration files through classes
    InputStream in = JulTest.class.getClassLoader().getResourceAsStream("logging.properties");
    // Create LogManger load profile
    LogManager logManager = LogManager.getLogManager();
    logManager.readConfiguration(in);
    Logger logger = Logger.getLogger("my.logger");

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
    logger.finest("finest");
}

2. Log4j learning

2.1 Log4j introduction

Log4j is an open source log framework under Apache. By using log4j in the project, we can control the location of log information output (console, file and database); we can also control the output format of each log. By defining the output level of the log, we can more flexibly control the log output process and facilitate the debugging of the project.

Log4j component

Log4j is mainly composed of Loggers, Appenders and Layout.

  • Loggers: controls the output level of logs and whether logs are output
  • Appenders: specifies how logs are output (console, file)
  • Layout: output format of console log information

1. Loggers

Loggers: loggers, which are responsible for processing log records. The naming of instances is the fully qualified name of classes. The name of loggers is case sensitive. Its naming has an inheritance mechanism. For example, the logger of org.apache.commons inherits the logger of org.apache.

In Log4j, there is a special logger called root, which is the root of all loggers. The root logger can be obtained through the Logger.getRootLogger() method.

2. Appenders

Appenders is used to specify where the log is output. You can also specify the output destination of the log. There are several common destinations:

  • Console appender: output logs to the console
  • FileAppender: outputs logs to a file
  • Daily rolling file appender: output the log to a log file and a new file every day
  • RollingFileAppender: output the log to a log file and specify the file size. When the file size reaches the specified size, the file name will be automatically changed and a new file will be generated
  • JDBC appender: save log to database

3. Layouts

Layouts is used to control the format of log output content, so that we can output logs in various required formats. Common layouts:

  • HTML Layout: format the log output in HTML tabular form
  • Simple Layout: simple log output format. The printed log format is (info - message)
  • Pattern Layout: the most powerful formatter. You can output the log according to the custom format. If no conversion format is specified, the default conversion format is used

2.2 quick start

Create a new SpringBoot project and introduce log4j dependency:

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

Introductory case:

public class Log4jTest {

    @Test
    public void testQuick() {
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.info("info");
    }

}

After execution, view the console:

It can be seen that the system configuration is required. Generally, it is configured with a configuration file. Here, it is configured with code for the time being.

@Test
public void testQuick() {
    BasicConfigurator.configure();
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.info("info");
}

In this way, the log information can be output normally.

2.3 log level

Log level:

  • Fatal: fatal error. It usually causes the system to crash and terminate the operation
  • Error: error message. It will not affect the system operation
  • warn: warning message. Problems may occur
  • info: operation information. Data connection, network connection, IO operation, etc
  • Debug: debug information. It is generally used in development to record program variables, parameters, transfer information, etc
  • Trace: trace information. Record all process information of the program

The default level of Log4j is debug. As long as the log level is higher than debug, it will be output.

2.4 using configuration files

Create a new configuration file log4j.properties under resources:

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = info,console
# Specifies the appender for console log output
log4j.appender.console = org.apache.log4j.ConsoleAppender
# Specify message format layout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout

Use in Code:

@Test
public void testProperties() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.fatal("fatal");
    logger.error("error");
    logger.warn("warn");
    logger.info("info");
    logger.debug("debug");
    logger.trace("trace");
}

1. Customize the format of the configuration Appender

In the log4j.properties configuration file, we define the log output level and output end, and configure the log output format in the output end respectively:

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = info,console
# Specifies the appender for console log output
log4j.appender.console = org.apache.log4j.ConsoleAppender
# Specify message format layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#Specifies the content of the message format
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

log4j uses the print format similar to the printf() function of C language to format the log information. The specific placeholders and their meanings are as follows:

%m=Output the information specified in the code
%p=Output priority
%n=Newline character
%r=Output from application startup to output log The number of milliseconds the message took
%c=Output the fully qualified name of the class to which the print statement belongs
%t=Output the full name of the thread that generated the log
%d=The current time of the output server. Default to ISO8601. Format can be specified:%d{yyyy year MM month dd day HH:mm:ss}
%l=Where the output log occurred. Including: class name, thread name and the number of lines in the code
%F=The name of the file where the output log message is generated
%L=Line number in output code
%%=Output a % character

You can add modifiers between% and characters to control the minimum width, maximum width, and how the text is aligned. For example:

%5c=The fully qualified name of the output class. The minimum width is 5. The class name is less than 5. By default, it is right aligned
%-5c=The fully qualified name of the output class. The minimum width is 5, and the class name is less than 5“-" Specify left alignment, there will be spaces
%.5c=The fully qualified name of the output class. The maximum width is 5. If the class name is greater than 5, the extra characters on the left will be truncated; if it is less than 5, there will be no spaces
%20.30c%=If the class name is less than 20, fill in spaces and align right; if it is greater than 30, the extra characters on the left will be truncated

2. FileAppender of custom configuration file

log4j.properties: output the log information to the file FileAppender

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = info,console,rollFile
# Specifies the appender for console log output
log4j.appender.console = org.apache.log4j.ConsoleAppender
# Specify message format layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# Specifies the content of the message format
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

# Specifies the appender for console log output
log4j.appender.file = org.apache.log4j.FileAppender
# Specify message format layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# Specifies the content of the message format
log4j.appender.file.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# Specify the path to save the log file
log4j.appender.file.file = E:/temp/logs.log
# Specifies the character set of the log file
log4j.appender.file.encoding = UTF-8

log4j.properties: split by file size

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = info,console,rollFile
# Specifies the appender for console log output
log4j.appender.console = org.apache.log4j.ConsoleAppender
# Specify message format layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# Specifies the content of the message format
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

# appender object split by file size
log4j.appender.rollFile = org.apache.log4j.RollingFileAppender
# Specify message format layout
log4j.appender.rollFile.layout = org.apache.log4j.PatternLayout
# Specifies the content of the message format
log4j.appender.rollFile.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# Specify the path to save the log file
log4j.appender.rollFile.file = E:/temp/logs.log
# Specifies the character set of the log file
log4j.appender.rollFile.encoding = UTF-8
# Specifies the size of the log file contents
log4j.appender.rollFile.maxFileSize = 1MB
# Specifies the number of log files
log4j.appender.rollFile.maxBackupIndex = 10
@Test
public void testPropertiesBySize() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    for (int i = 0; i < 10000; i++) {
        logger.fatal("fatal");
        logger.error("error");
        logger.warn("warn");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
}

log4j.properties: split by time

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = info,dailyFile

# appender object split by time size
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
# Specify message format layout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
# Specifies the content of the message format
log4j.appender.dailyFile.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# Specify the path to save the log file
log4j.appender.dailyFile.file = E:/temp/logs.log
# Specifies the character set of the log file
log4j.appender.dailyFile.encoding = UTF-8
# Specify rules for log file splitting
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss

3. User defined Logger

log4j.properties:

# Specifies the default configuration information of the RootLogger top-level parent element
# Specify the log level = info, and the appender used is console
log4j.rootLogger = trace,console

# The custom logger will also inherit the RootLogger, so it will also be output to the console
log4j.logger.com.zzc.sbexp.log.log4j = info,file
# apache's logger will be output to the console only if it is at or above the error level, and will not be output to a file
log4j.logger.org.apache = error

...
@Test
public void testMyLogger() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.fatal("fatal");
    logger.error("error");
    logger.warn("warn");
    logger.info("info");
    logger.debug("debug");
    logger.trace("trace");

    // apache logger
    Logger logger1 = Logger.getLogger(Logger.class);
    logger1.fatal("fatal1");
    logger1.error("error1");
    logger1.warn("warn1");
    logger1.info("info1");
    logger1.debug("debug1");
    logger1.trace("trace1");
}

After operation:

Keywords: Java Spring Spring Boot

Added by alex_lana on Thu, 02 Dec 2021 02:30:13 +0200