Location>code7788 >text

10,000-word article to take you through the Java logging framework using the Java logging framework

Popularity:53 ℃/2024-08-14 07:50:53

Hello, everyone.let sb know

I. Concept of the logbook

I don't need to tell you the importance of logs, which, simply put, are records.

It is used to record what happens when a program is running. For example, if the program starts, performs an operation, encounters a problem, etc., all of these can be recorded by the log.

Imagine you run a store and you keep a daily log of your turnover, customer feedback, merchandise in and out, inventory, and so on. It's like a log of the program. For example:

  • E-commerce websiteRecord the user's login, browsing and purchasing behavior, monitor the transaction process, and discover abnormal transactions in a timely manner; analyze your browsing records through logs to achieve accurate push and so on.
  • server (computer): Records the startup, operation, and shutdown status of the server, as well as the occurrence of various errors, to help administrators find and solve problems in a timely manner.

1.1 Role of logs

  1. Debugging Help: When there is a problem with a program, by looking at the logs, you can quickly pinpoint where the problem occurred and why.
  2. Monitoring of operational status: Logs allow you to understand the operational status of the program, such as user actions, system performance, etc.
  3. security audit: Logs can be used as a basis for auditing in situations where user behavior or system operations need to be recorded.

1.2 Specific examples

public class SimpleApp {
    public static void main(String[] args) {
        ("Program start");;

        // Assuming this is user input
        String userInput = "Hello, World!"; ("User Input"); // Assume this is user input.
        ("The user has entered: " + userInput);

        // Process the data
        String result = processInput(userInput); // Process the data.
        ("Result: " + result); // Process the data.
        try {
            // Logic code for possible exceptions
        }catch(Exception e){
            ()
        }

        // End of program
        ("End of program");
    }

    private static String processInput(String input) {
        // Here's the processing logic
        return "Processed: " + input; }
    }
}

The above code is not new to us, is it, we use theto print the running status of the program, use the()to print messages and errors

This is the simplest and most straightforward way to print logs without a logging framework

This approach is simple and straightforward, but has some drawbacks:

  • Poor flexibility: You cannot easily control the output format, level, etc. of the log.
  • Performance issues: Large amounts of log output may affect program performance.
  • unmanageable: Log messages are mixed in with the standard output and are not easy to find and analyze.

So we have to introduce various powerful logging frameworks for log management

Mainstream logging framework

The logging framework consists of a logging facade and a logging implementation, as shown below

主流日志框架

2.1 Log facade

As the name suggests, the log facade, like a team leader, is only responsible for setting the rules and arranging tasks, while the specific work is handed over to the hard hitters (log specific implementation) can be.

The logging facade provides a standard set of logging interfaces, while specific logging is done by different logging frameworks.

The advantage of this is that you can switch between different logging frameworks via configuration without modifying the code.

Just as in the workplace, when a laborer runs away, a new cheaper laborer can perform the same tasks without much cost or change, so it seems a bit far-fetched to make a quick switch!

The main mainstream log facade frames are:

  • SLF4J: This is a very popular logging facade , which provides a simple set of logging interfaces , and can be used with a variety of logging frameworks (such as Log4j, Logback , etc.) .
  • JCL: this is one of the early log facades

2.2 Logging implementation

By is the implementation of the log facade interface to complete the logging, the real hit workers no doubt!

The mainstream logging implementation frameworks are:

  • JUL

    Javacomes with a logging framework , relatively basic functionality , general performance , but for simple logging needs enough to use .

  • Log4j

A very old logging framework , very powerful , you can customize a lot of logging details , such as logging levels , output formats , output destinations and so on. Now maintained by the Apache Software Foundation

  • Log4j2

Also developed by the Apache Software Foundation, compared to theLog4jLog4j2Significantly improved in performance, while maintaining rich functionality, support for asynchronous logging processing, suitable for high-performance needs of the scenario

  • Logback

leave it (to sb)Log4jOne of the original developers ofSpring BootDefault logging, lightweight, excellent performance, and more comprehensive features

III. JUL logging framework

3.1 Main components

  1. Logger: The logger, the heart of the logging system, is used to generate log records.
  2. Handler: Logger processor that is responsible for outputting log messages to different destinations such as console, files, etc. Each Logger can be configured with one or moreHandler
  3. Formatter: Log formatter responsible for defining the output format of the log. For example, timestamp, log level, message, etc.
  4. Level: Set the log level, the common levels areSEVEREWARNINGINFOCONFIGFINEFINERFINESTetc.
  5. Filter: This component is used to filter logging. You can set some rules and only logs that fulfill these rules will be logged.
  6. Log Record:This is the log record itself, which contains all the information about the log, such as time, log level, messages, etc.

3.2 Procedure for use

  1. gainLoggerExample.
  2. increaseHandler
  3. Added for the previous stepHandler Set the log level (Level) and format output (Formatter
  4. establishFilter(machine) filter
  5. because ofLoggerinstance adds a log handler (Handler) and log filters (Filter
  6. Record logs.

jul使用步骤

3.3 Getting Started Cases

public class LogQuickTest {
    public void testLogQuick() {
    public void testLogQuick(){
        // Create the logging object
        Logger logger = ("");
        // Logging output
        ("This is an info log");.
        (, "This is an info log");;

        String name="Programmer Xiaofan";
        Integer age=18;
        (, "Name: {0},Age: {1}",new Object[]{name,age});;

    }
}

JUT入门案例

3.4 Log level

Log level system to differentiate the importance of logs

3.4.1 Log level
  1. SEVERE(Critical): This is the highest level of logging and is used to record serious errors such as system crashes, data loss, etc. This type of log usually requires immediate attention and handling.
  2. WARNING(Warning): Used to log information that may not immediately affect system operation, but may indicate a potential problem. For example, an operation did not have the desired effect, or system resources are nearing exhaustion.
  3. INFO(Information): Used to record general information, such as the status of program operation, important operation steps, and so on. This type of information is useful for understanding how the program is running, but usually does not need to be processed immediately.
  4. CONFIG(Configuration): Used to log configuration information, such as configuration files loaded when the program is started, parameters initialized, etc. This type of logging helps debugging and verifying that the program is configured correctly.
  5. FINE(Detailed): Used to log more detailed information, such as the execution details inside the program, the values of variables, and so on. This type of log is very useful for developers to understand the internal state of the program when debugging it.
  6. FINER(more detailed): A log that is more granular than the FINE level, recording more in-depth execution details. Often used for in-depth analysis of program operation.
  7. FINEST(most detailed): This is the lowest level of logging, recording the most detailed information, including details of every step in the execution of the program. This type of logging can produce a lot of output and is usually only used when very detailed debugging information is needed.
3.4.2 Level relationships

SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST

The higher the log level, the more important the information recorded. When you set a log level, such as INFO, then logs at the INFO level and above (SEVERE and WARNING) are logged, while logs at the FINE, FINER, and FINEST levels are ignored!

3.5 Detailed use cases (hard-coded)

Here we follow the steps above to create a logger that outputs log files to the console and to a file respectively

public class LoggingExampleTest {

    public void testLogging() {
    public void testLogging() {
        // Get the logger
        Logger logger = ("LoggingExample");

        // Set the logging level to INFO, which means that logs of INFO level and above will be logged
        ();

        // Create a console handler to output the log to the console
        // and set its LogLevel and Formatter.
        ConsoleHandler consoleHandler = new ConsoleHandler();
        (); // The console only outputs logs at the WARNING level and above.
        (new SimpleFormatter() {
            @Override
            public synchronized String format(LogRecord record) {
                // Customize the log format
                return ("%1$tF %1$tT [%2$s] %3$s %n", (), (), ()); }
            }
        });
        (consoleHandler).

        // Create a file Handler to output the logs to a file
        // and set its log level and formatter.
        try {
            FileHandler fileHandler = new FileHandler("", true); // The file will log all levels of logging.
            (); // The file will record all levels of logging
            (new SimpleFormatter() {
                @Override
                public synchronized String format(LogRecord record) {
                    // Customize the log format
                    return ("%1$tF %1$tT [%2$s] %3$s %n", (), (), ()); }
                }
            });
            (fileHandler);
        } catch (IOException e) {
            (); }); (fileHandler); }); (fileHandler); })
        }

        // Create and set up the Filter
        Filter filter = new Filter() {
            @Override
            public boolean isLoggable(LogRecord record) {
                // Here you can add filtering logic, such as logging only logs that contain certain strings
                return ().contains("important");
            }
        }

        // Apply the Filter to the Logger.
        //(filter).

        // Logging different levels of logging
        ("Critical error messages - should be logged to the console and to a file");; // Logging different levels of logging.
        ("Warning messages - should be logged to the console and to a file").
        ("General Messages - should be logged to file only"); ("Configuration Messages - should be logged to console and file"); and
        ("Configuration Messages - Logged to File Only"); ("Detailed Logging - Should Log to Console and File Only"); ("Detailed Logging - Should Log to File Only"); and
        ("Detailed logs - log to file only"); ("Detailed logs - log to file only").


        // This log will be filtered out by the Filter and will not be logged.
        ("This message is not important and will be filtered"); // This log will be filtered by Filter and will not be logged.

        // This log will be logged because the message contains "important".
        ("This message is important and will be logged to the console and file"); // This log will be logged because the message contains "important".
    }
}

① Console log output

1、控制台输出结果

② Log file outputelement

2、文件中输出日志

code interpretation

  1. Logger Fetch: First get a file namedLoggingExample(used form a nominal expression)LoggerExample.
  2. Setting the log level: Set the Logger's logging level toINFO, which means that logs at the INFO level and above will be logged.
  3. Console Handler: Create aConsoleHandlerinstance, set its log level toWARNINGand customize the output format of the log.
  4. File Handler: Trying to create aFileHandlerinstance that writes logs to thefile and set its log level toALL, meaning that all levels of logging will be logged to a file.
  5. Custom Formatter: Create a customizedSimpleFormatter, used to define the output format of the log.
  6. Filter Settings: Creates a file that implements theFilterinterface's anonymous inner class and overrides theisLoggablemethod, which implements the filtering logic, only logs messages that contain the string "important".
  7. Apply Filter: Apply the created Filter to the Logger.
  8. log: Record different levels of logs, showing how different levels of logs are processed by Handler and Filter.
  9. Logging: Some logs will be logged to the console or to a file, or ignored, depending on the set logging level, Handler and Filter rules.

3.6 Log Configuration File

The above 3.4 subsection through the hard-coded way to print out the log, this way is not conducive to the management and maintenance of the later, this subsection we will use the configuration file for logging output

① Under resources, create a newThe document reads as follows

# Specify the log handler as: ConsoleHandler,FileHandler to use both console and file handlers.
handlers= ,

# Set the default logging level to: ALL
.level= ALL

# Configure a custom Logger
 =
 = CONFIG

# If you want to use a custom configuration, you need to turn off the default configuration
 =true

# Handler object to output to the log file
# Specify the path to the log file. When the number of files is 1, the log is /logs/.
 = /logs/java%
# Specify the size of the log file content, the following configuration means that when the log file reaches 50000 bytes, a new log file will be created automatically.
 = 50000
# Specify the number of log files, the following configuration indicates that only 1 log file will be retained
 = 1
# Specify the handler object log message format object
 = 1
# Specify the character set of the handler object as UTF-8 to prevent garbled code.
 = UTF-8
# Specify whether to append to the end of the file when writing log message to the file, true means append, false means overwrite.
 = true


# The handler object to be output to the console
# Specify the logging level of the handler object.
 = WARNING
# Specify the log message format object of the handler object.
 =
# Specify the character set of the handler object
 = UTF-8

# Specify the log message format
 = [%1$tF %1$tT] %4$s: %5$s %n

Attention: In Setting the Log Message Format (explained in detail in a later subsection)

  • %1$tF: This placeholder indicates the time of the log entry in the formatyyyy-MM-ddwhich1$ Indicates that this is the first parametertF is the formatting code for the date
  • %1$tT: This placeholder indicates the time of the log entry in the formatHH:mm:i.e. hours : minutes : seconds . milliseconds1$ indicates that this is the first parameter.tT It's the formatting code for the time
  • %4$s:: Indicates the log level.level =WARNING Output warning level =INFO Output message
  • %5$s: Indicates a log message
  • %n: This placeholder indicates a line break, which will follow each log entry so that each entry can be clearly distinguished when viewing the log.

② Log Test

@Test
public void testLogProperties()throws Exception{

    // 1. Read the configuration file, through the class loader
    InputStream ins = ().getResourceAsStream("");
    // 2. Create the LogManager
    LogManager logManager = (); // 3.
    // 3. Load the configuration file through the LogManager.
    (ins).

    // 4. Create the logger
    Logger logger = (""); // Create a logger.

    // 5. Record different levels of logging
    ("This is a severe level message"); ("This is a warning level message"); ("This is a warning level message"); ("This is a warning level message")
    ("This is a WARNING level message").


}

After executing the above code

Console Output

控制台输出

File Output:

文件输出

3.7 Log Formatting

In the above two subsections, the logs are formatted, either by coding or configuration files.

① Code Setting Log Format

(new SimpleFormatter() {
    @Override
    public synchronized String format(LogRecord record) {
        // Customized log format
        return ("%1$tF %1$tT [%2$s] %3$s %n", (), (), ());
    }
});

② Configuration file specifies the log format

# Specify the log message format
 = [%1$tF %1$tT] %4$s: %5$s %n

Do you understand the log formatting settings set above?

Regardless of which way the log format is set up, we see that the source code ends up going through thefunction to realize, all we need to learn theStringclassformatThe use of this method

new SimpleFormatter

3.7.1 String(used form a nominal expression)formatmethodologies

String(used form a nominal expression)formatmethod is used to format the string.

formatA method is like a template into which you can insert the data you want, and it generates a formatted string for you.

Let's take a look at the following simple example

@Test
public void testStringFormatter()throws Exception{
    String name = "let sb know";
    Integer age = 18;

    // utilization()method to format a string
    String xiaofan = ("%slast year%dyear (of crop harvests)", name, age);
    (xiaofan);
}
//exports
let sb knowlast year18year (of crop harvests)
3.7.2 Common Placeholders

%scap (a poem)%d are placeholders, and different types require different placeholders, so what are some other common converters?

placeholder particular typical example
%s String type **** "Please follow if you like Xiaofan."
%c character type ‘x’
%b Boolean type true
%d Integer type (decimal) 666
%x Integer type (hexadecimal) FF
%o Integer type (octal) 77
%f Floating point type 8.88
%a hexadecimal floating-point type FF.34
%e Type of index 1.28e+5
%n line break
%tx Date and time types (x for different date and time converters)
3.7.3 Use of special symbols together
notation clarification typical example in the end
0 Specify a number or character preceded by a zero for alignment. ("%04d",6) 0006
blank space Specify the number, the character in front of the complementary space, used to align the ("[% 4s]",x) [ x]
Grouping of numbers by "," (often used for amounts) ("%,f,666666.66") 666,666.6600

Attention: By default, variable parameters are replaced sequentially, but we can reuse variable parameters with the "number $"

@Test
public void testStringFormatter()throws Exception{
    
    String name = "Xiaofan"; Integer age = 18; String

    // Format the string using the () method
    String xiaofan = ("%s this year %d years old", name, age);
    (xiaofan);
    //
    String xiaofan1 = ("%s is %d years old this year,%1$s public number is: programmer xiaofan", name, age); (xiaofan)
    (xiaofan1);
}
// Output
Xiaofan is 18 years old.
xiaofan is 18 years old, xiaofan's public name is: programmer xiaofan.

In the above example we passed the%1$sReuse the first parametername

3.7.4 Date formatting

Above we said %tx,x stands for the date conversion character, its specific meaning is as follows

notation descriptive typical example
c Contains all date and time information Sat Aug 03 17:16:37 CST 2024
F "Year-Month-Day" format 2024-08-03
D "mm/dd/yyyy" format 08/03/24
d date 03
r HH:MM:SS PM"Format (12-hour format) 05:16:37 PM
R HH:MM"Format (24-hour format) 17:16
T HH:MM:SS "Format (24-hour format) 17:16:37
b Monthly Localization August
y two-year old 24
Y quadrennial 2024
m moon 08
H Hours (24-hour system) 17
I Hours (12-hour system) 05
M ingredient 16
S unit of angle or arc equivalent one sixtieth of a degree 37
s Timestamps in seconds 1722677530
p Morning or afternoon afternoon

Log4j logging framework

Log4j is an open source logging framework under the Apache Software Foundation organization , is a relatively old logging framework , currently out of log4j2, which made great changes in log4j, performance has improved a lot. But some of the old project will still be in use , so we also say a few

Official website:/log4j//

Attention: From the official website, we can see that the Program Management Committee announced thatLog4j 1. xDiscontinued. Users are advised to upgrade to Log4j 2

log4j官网

4.1 Quick Start

4.1.1 Adding dependencies
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<!--For testing purposes,We introducejunit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
4.1.2 Log4j Getting Started Code
@Test
public void testLog4jQuick(){

    //Initialize logging configuration information without a configuration file
    ();
    //Get the logger
    Logger logger = ();
    // Print the log by various logging levels
    ("This is a fatal message"); // Serious error, generally causing a system crash
    ("This is an error message"); // When an error occurs, e.g. an error that does not affect the system's ability to continue running.
    ("This is a warning message"); // Warning level, e.g. if an alarm is issued.
    ("This is a general message"); // General information, e.g. to record the execution of a common method.
    ("This is a debug message"); // Debugging information, such as what is printed when debugging.
    ("This is a trace message"); // Trace information, e.g., tracing the path of a program.
}
// Output
0 [main] FATAL Log4jTest - This is a fatal message.
0 [main] ERROR Log4jTest - This is an error message.
0 [main] WARN Log4jTest - This is a warning message.
0 [main] INFO Log4jTest - this is a normal message
0 [main] DEBUG Log4jTest - This is a debug message.

Attention: (); Initialize the default logging configuration information for log4j without adding a configuration file, if neither the default configuration information nor the configuration file is available

The following error is reported

未配置报错

4.2 Log levels

Log levels, which are like different markers in a journal, are used to distinguish the importance of information. In log4j, log levels are categorized from low to high as follows:

  1. TRACE: Trace level, usually used to record the detailed trajectory of the program operation, such as the order of method calls and so on. This level is very detailed and is usually used more during the development phase or debugging.
  2. DEBUG: The debug level, which is used to record the running state of a program, such as the values of variables, the flow of the program, etc. The DEBUG level is useful when you need to dig deeper into the inner workings of a program.
  3. INFO: Information level, used to record the normal operation status of the program, such as program startup, configuration information, normal end, etc. INFO level logs are helpful for users and developers to understand the operation of the program.
  4. WARN: A warning level to record situations that may cause problems, but the program can still continue to run. For example, the program encounters an uncommon situation, or an operation fails but doesn't affect the big picture.
  5. ERROR: The error level, which is used to record errors in the running of a program that usually affect the normal functioning of the program, but the program may still be able to continue running.
  6. FATAL: The fatal level, which is used to record very serious errors that would cause the program to fail to continue running at all. For example, a critical part of the program fails and the entire application may need to be restarted.

Out of the above, there are two special levels as follows

1. **OFF**: used to disable logging
1. **ALL**: to enable logging of all messages

4.3 Log4j Components

  1. Logger: This component is like the brain of the journal, responsible for recording journal information. You can imagine it as the owner of a journal, deciding what is worth recording and what can be ignored.
  2. Appender: Appender is like the pen of the journal, it decides where the log messages are to be written to. It can be the console, a file, a database, or even sent over the network to a remote server. Each Appender has different uses and features.
  3. Layout: Layout determines the appearance of the journal, that is, the format of the journal. For example, you can choose the time to include in the log, the log level, the name of the class and method in which the logging occurs, and the specific content of the log, etc. Layout is like styling the look and feel of a journal.
4.3.1 Logger

Log4jThere is a specialloggerbe known asrootIt'sloggerThe root of the otherloggerAll will inherit directly or indirectly fromroot

In the introductory example, we pass the(); The acquisition isroot logger

The name is will inherit from the logger whose name isThe logger of the

4.3.2 Appender

Used to specify where the log is to be logged to, the main types are as follows

Appender type corresponds English -ity, -ism, -ization
ConsoleAppender Output logs to the console
FileAppender Outputting logs to a file
DailyRollingFileAppender Output logs to a file and to a log file per day
RollingFileAppender Outputs logs to a file and specifies the size of the file. When the file is larger than the specified size, a new log file will be generated.
JDBCAppender Save logs to database
4.3.3 Layout

Used to control the output format of the log content, Log4j commonly used in the following output formats

Log Formatter clarification
HTMLLayout Output logs as html tables
SimpleLayout Simple log format output, e.g. (info-message)
PatternLayout The most powerful formatter and the one we use the most, we can customize the output formatting

Example: Below we pass thePatternLayout Formatting logs

@Test
public void testLog4jLayout(){
    //Initialize logging configuration information, no configuration file is required
    ();
    //Get the logger
    Logger logger = ();
    Layout patternLayout = new PatternLayout("%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n");// Apply the customized Layout to the consoleAppender
    ConsoleAppender consoleAppender = new ConsoleAppender(patternLayout);
    (consoleAppender); // Apply the custom Layout to the ConsoleAppender.
    // Record the log
    ("This is a custom-formatted log message");;

}
// Output
2024-08-04 13:55:35 [INFO] - Log4jTest.testLog4jLayout(:44) - This is a custom formatted log message
placeholder clarification
%m Outputs the log messages specified in the code
%p Output Priority
%n line break
%r Outputs the number of milliseconds consumed from the time the application is enabled to the time the log message is outputted
%c Full name of the class to which the output statement belongs
%t Output the full name of the thread
%d Output the current time of the server, %d
%l Outputs the location where the log time occurred, including the class name, thread, and function in the code For example: Log4jTest.testLog4jLayout(:44)
%F Name of the folder where the output log message was generated
%L Line numbers in the output code
%5c If the category name is less than 5 digits, the left side is supplemented with a space, i.e., right-justified.
%-5c If the category name is less than 5 digits, the right side is supplemented with a space, i.e. left-justified.
.5c If the category name is larger than 5 digits, the extra character on the left will be intercepted, and if it is smaller than 5 digits, it will be supplemented by a space.

4.4 Configuring Logging via Configuration Files

(); The above code initializes the logging configuration information through this code, and in this subsection, we configure the logging configuration through a configuration file.

by looking atLogManagerLog Manager source code, we know that we can load configuration files in the following formats by default (where the cap (a poem) (It's the one we use most often)

  • wait a minute!

日志管理器源码

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO and the appender bit Console to use.
=INFO,Console
# Specify the console log output appender
 = .
# Specify the message formatter layout
=.
# Specify message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n

or

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

4.5 Examples of various log outputs

The console output configuration has already been described in the above subsection, so for reasons of space, I won't repeat it here.

① File Output Configuration

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO, the appender bit Console used
=INFO,File
# Specify the file log output appender
 = .
# Specify log file name
=D:/logs/
# Specify whether to add new logs to existing ones
=true
# Specify the message formatter layout
=.
# Specify the message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n
# Specify log file encoding format
=UTF-8

② Log file split output according to size

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO, the appender bit Console used
=INFO,RollingFile
# Specify that the file log is split for output based on size appender
 = .
# Specify the log file name
=D:/logs/
# Set whether to add new logs to the existing logs when restarting the service
=true
# Set the maximum number of log files to be saved
=5
# Set the file size above which another file will be generated
=1

# Specify the message formatter layout
=.
# Specify the message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n
# Specify log file encoding format
=UTF-8

The final effect of generating logs is shown below

按照日志大小切割文件

③ Split log files by date

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO, the appender used bit Console
=INFO,DailyRollingFile
# Specify that file logs are output split by date appender
 = .
# Specify the log file name
=D:/logs/
# Set whether to add new logs to the existing logs when restarting the service
=true

# Specify the message formatter layout
=.
# Specify the message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n
# Specify log file encoding format
=UTF-8

The final effect of generating logs is shown below

日志文件根据日期进行分割

④ Custom Logging Configuration

When we want to define our own logging configuration, we can add it as follows. For example, addIt is also inherited fromrootLogger, so we have to add

=false Avoid duplicate log prints

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO, the appender used bit Console
= INFO,DailyRollingFile

# Customize the logging configuration
=DEBUG,Console
# Set the log overlay, this configuration must be added, otherwise the log will be output repeatedly
=false

⑤ Store log information in the database

First, we create a new testlog database, and under the database, we create a new log table

CREATE TABLE `log` (
  `log_id` int(11) NOT NULL AUTO_INCREMENT,
  `project_name` varchar(255) DEFAULT NULL COMMENT 'Project name', `create_date` varchar(255) DEFAULT NULL COMMENT
  `create_date` varchar(255) DEFAULT NULL COMMENT 'Creation Time', `level` varchar(255) DEFAULT NULL COMMENT
  `level` varchar(255) DEFAULT NULL COMMENT 'Priority', `category` varchar(255) DEFAULT NULL COMMENT
  `category` varchar(255) DEFAULT NULL COMMENT 'Full name of the category', `file_name` varchar(255) DEFAULT NULL COMMENT
  `file_name` varchar(255) DEFAULT NULL COMMENT 'Name of the file where the output log message was generated ', `thread_name` varchar(255) DEFAULT NULL COMMENT
  `thread_name` varchar(255) DEFAULT NULL COMMENT 'The name of the thread on which the log event was generated ', `thread_name` varchar(255) DEFAULT NULL COMMENT
  `line` varchar(255) DEFAULT NULL COMMENT 'Numbered line', `all_category` varchar(255) DEFAULT NULL COMMENT
  `all_category` varchar(255) DEFAULT NULL COMMENT 'Location of log event', `all_category` varchar(255) DEFAULT NULL COMMENT 'Location of log event', `message` varchar(255)
  `message` varchar(4000) DEFAULT NULL COMMENT 'The message specified in the output code',
  PRIMARY KEY (`log_id`)
).

Secondly, new constructionJDBCAppender, and forJDBCAppender To set the database connection information, the code is as follows

@Test
public void testLog4j2db(){
    //Initialize the logging configuration information without the configuration file
    ();
    //Get the logger
    Logger logger = ();
    // Create a new JDBCAppender
    JDBCAppender jdbcAppender = new JDBCAppender(); // Create a new JDBCAppender.
    ("");
    ("jdbc:mysql://localhost:3308/testlog?useSSL=false&serverTimezone=UTC");;
    ("root");
    ("123456").
    ("INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('Xiaofan log test','%d{yyyy- MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')");

    (jdbcAppender);
    // Record the log
    ("This is a custom formatted log message.");
    ("This is a custom formatted error log message.");
}

Finally, run the code and see the results

日志信息已经村到数据库中了

V. JCL Log Facade

What constitutes a log facade is covered in subsection 2, so we won't go into that here.

The introduction of the log facade , so that we can interface-oriented development , no longer rely on specific implementation of the class , reduce code coupling .

JCLfull nameJakarta Commons Loggingis a generic log provided by ApacheAPI,JCLcomes with a logging implementation in thesimplelogBut this function is very simple.

jcl实现图

5.1 JCL Quick Start

① Two abstract classes of LCL

  • Log: Basic Logger
  • LogFactory: responsible for creating specific instances of Log, if log4j, then create instances of log4j, if jul, then create instances of jul

② Example code

Introducing dependencies

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>

base code

We haven't imported any logging implementations, so here we default to the jdk's ownJULto implement logging

@Test
public void test(){

    Log log = ();

    ("This is an error"); ("This is a warn"); ("This is an error"); ("This is an error.
    
    ("This is an info"); ("This is an info").
    ("This is a debug"); ("This is a debug"); ("This is a debug"); ("This is a debug"); ("This is a debug").
    ("This is a trace"); ("This is a trace").
}

日志输出

5.2 Quickly Switching Log4j Logging Frameworks

① Introductionlog4jLogging dependencies

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

② Addconfiguration file

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO and the appender bit Console to use.
=INFO,Console
# Specify the console log output appender
 = .
# Specify the message formatter layout
=.
# Specify message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n

③ Test Log Output

@Test
public void testJclLog4j(){

    Log log = (); ("This is an error."); ("This is an error.")
    ("This is an error"); ("This is a warn"); ("This is an error"); ("This is an error.
    ("This is a warn"); ("This is an info"); ("This is an info")
    ("This is an info"); ("This is an info").
    ("This is a debug"); ("This is a debug"); ("This is a debug"); ("This is a debug"); ("This is a debug").
    ("This is a trace"); ("This is a trace").
}

The log output is as follows:

log4j日志输出

We can see that using theJCLAfter the log facade, we start with thesimplelogThe logging framework switches to thelog4jLogging framework, no code changed.

VI. SLF4j log facade

SLF4j The full name isSimple Logging Facade For JavaJava's simple logging facade and the last subsection talks about theJCLDoing the same job.

In most current Java projects, the logging framework will basically choose theslf4j-api As a facade, with a concrete realization frameworklogbacklog4j equal use

SLF4jIt is the most popular logging facade on the market today and offers the following two main features

  • Binding of log frames
  • Bridging of logframes

6.1 Quick Start

① Add dependency

<!--Add log facadesl4j-->
 <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.13</version>
 </dependency>
 <!--increaseslf4j Self-contained simple logging implementation-->
 <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>2.0.13</version>
  </dependency>

② Log Output

 //Assertion of the log object
public final static Logger logger = ();
@Test
public void testSlf4j(){
    //Print the log
    ("This is the ERROR log").
    ("This is the warn log");
    ("This is the info log"); ("This is the log of info"); ("This is the log of info"); ("This is the log of info")
    ("This is the debug log").
    ("This is the trace log").

    //Use placeholders to output log information
    String name = "Xiaofan";; Integer age = 18;; //Output log information using placeholders.
    Integer age = 18; ("{{This is the trace log"); ("This is the trace log")
    ("{}, is {} years old", name, age);

    // Write system exceptions to the log
    try {
        int i = 1/0; }catch (Exception e){
    }catch (Exception e){
        ("Error executing", e); }catch (Exception e){
    }

}

The above code outputs the following log

日志输出

6.2 SLF4j Log Binding Features

6.2.1 Log Binding Principles

The picture below is gleaned from the official websiteslf4j Log Binding Chart, by the way, the official website is here https:///

logback

Guys may be a little confused when they see the picture above, it's all in English, so you can't read it.

一脸懵逼

So Xiaofan simply translated it as follows

slf4j实现原理图

  • Only the log facade is imported, no log implementation is imported, no log output will be performed
  • logbacksimplelogno-operation The framework followsSLF4jSpecification Import the jar package to use
  • log4jJUL are relatively old log frames that do not followSLF4jspecification, adapters need to be introduced to use the
  • When we import theslf4j-nopNo logging framework will be used after
6.2.2 Binding the logback logging framework

① Introduce logback dependency

<dependency>
    <groupId></groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.14</version>
</dependency>

② Log output

The code in the Quick Start remains unchanged, and after running it, the logback logging framework is used to enter the logs as follows

logback日志输出

6.2.3 Bindingslf4j-nop

① Introducing dependency

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>2.0.13</version>
</dependency>

② No logs will be output from the console at this time.

6.2.4 Using Adapter Bindingslog4jLogging framework

① Importing dependencies

<!--log4jadapter (device)-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>2.0.13</version>
</dependency>
<!--log4jLogging framework dependencies-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

② Add Configuration File

# Specify the RootLogger top-level parent element default configuration information
# Specify the logging level bit INFO and the appender bit Console to use.
=INFO,Console
# Specify the console log output appender
 = .
# Specify the message formatter layout
=.
# Specify message content format
 =%d{yyyy-MM-dd HH:mm:ss} [%p] - %l - %m%n

③ The code remains unchanged and the log output is as follows

log4j日志输出

6.2.5 Binding the JUL Logging Framework with Adapters

① Introducing dependency

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>2.0.13</version>
</dependency>

② The code remains unchanged and the log output is as follows

jul日志输出结果

6.3 SLF4j Log Bridging

6.3.1 Scenarios of use

If your project already uses theLog4j and other old logging frameworks, but you want to migrate to using theSLF4J(used form a nominal expression)APIThis is when you can use theSLF4J(used form a nominal expression)Log4j Bridges to smooth the transition

6.3.2 Bridging Principles

桥接器原理

The above figure shows the bridging schematic provided by the SLF4j official website, from the figure, we can see that we only need to introduce different bridgeslog4j-over-slf4jjul-to-slf4jjcl-over-slf4j

It is then possible to realize the effect of theNo changes to the original codeThe logs are removed from thelog4jjuljclmigrate toslf4j+logbackLog Portfolio

6.3.3 Bridging steps

summarized belowLog4j migrate toslf4j+logbackExamples of log combinations

  1. Removing the old log frameLog4j dependencies

去除老项目中的日志依赖

  1. increaseSLF4JBridging components provided

    引入桥接器

  2. Adding to the projectSLF4JSpecific implementations

引入新的日志实现

VII. Logback logging framework

Official website:/

7.1 Quick Start

① Add dependency

<!--Add log facadeSLF4jdependencies-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.13</version>
</dependency>
<!--increaseLogback日志实现dependencies-->
<dependency>
    <groupId></groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.14</version>
</dependency>

② Print log code

public class LogbackTest {

    private static final Logger logger = ();

    LogbackTest { private static final Logger logger = (); @Test
    public void testLogbackQuick(){
        ("This is an error log.");
        ("This is a warning log"); ("This is a warning log"); ("This is a warning log"); ("This is a warning log")
        
        ("This is a debugging log"); ("This is a debugging log").
        ("This is a trace log"); }
    }
}

Logback打印日志

7.2 Logback Configuration

Logback can be configured programmatically (by adding configuration classes) or through configuration files.

Configuration file is the most commonly used in daily development, we here in this way configuration, if the configuration file is interested in the partners can go to the official website to see for themselves!

7.2.1 What components does Logback contain?
  1. Logger: Logger for logging different levels of log messages such as errors, warnings, messages, debugging and tracing.
  2. Appender: Specifies that log messages are output to different places. For example, you can set one Appender to output logs to the console, and another Appender to write logs to a file, or send them to a remote server.
  3. Encoder: If you are using File Appender, Encoder is used to define the format of the log file contents. For example, you can choose whether the format of the log is simple text or XML.
  4. Layout: Older versions ofLogbackThe component used to define the log format in the Encoder has replaced Layout's functionality in this new version.
  5. Filter: Specify specific rules to filter log messages, such as logging only logs with more than an error, or logging only logs that contain specific keywords.
  6. Configuration: Used to configureLogbacksettings, such as setting the logging level, the type and parameters of the Appender, and so on. Configuration can be done via theXMLJSONorGroovyscript to accomplish this.
7.2.2 What file formats can be configured?

Logback reads the following types of configuration files in turn

  • (top)

    If none exist, the default configuration is used

7.2.3 Adding aConsoleAppenderConsole Log Output Configuration

configuration file

<?xml version="1.0" encoding="UTF-8"? >;xml version="1.0" encoding="UTF-8"?
<configuration>
    <! -- Add a property named pattern to set the log output to be--> <!
    <! --format output: %d for date, %thread for thread name, %-5level: level shows 5 character widths from left %msg: log message, %n is a line break -->!
    <property name="pattern" value="%d{yyyyy-MM-dd HH:mm:} %c [%thread]%-5level %msg%n" />

    <! --Output to console -->
    <appender name="console" class="" >
        <encoder>
            <! --referencing the pattern attribute configured above -->
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>
    <! --Set the logging level-->; </encoder> </appender>!
    <root level="ALL">
        <! --Referencing the consoleAppender configured above to output logs to the console --> <!
        <appender-ref ref="console" />
    </root>
</configuration>

The log inputs are as follows

日志输出

Log output format: In the previous several logging frameworks we have introduced, much the same. Here is a brief description of the commonly used ones

notation hidden meaning
%d{pattern} Formatted Date
%m or %msg Log messages
%M method
%L line number
%c Full class name
%thread Thread Name
%n line feed (computing)
%-5level Log level, and left-justified
7.2.4 Adding aFileAppenderOutput logs to file

configuration file

<?xml version="1.0" encoding="UTF-8"? >;xml version="1.0" encoding="UTF-8"?
<configuration>
    <! -- Add a property named pattern to set the log output to be--> <!
    <! --format output: %d for date, %thread for thread name, %-5level: level shows 5 character widths from left %msg: log message, %n is a line break -->!
    <property name="pattern" value="%d{yyyyy-MM-dd HH:mm:} %c [%thread]%-5level %msg%n" />

    <! --Set log file storage path -->
    <property name="log_file" value="d:/logs"> </property>

    <! -- Output to file -->!
    <appender name="file" class="">
        <encoder>
            <! --referencing the pattern attribute configured above -->
            <pattern>${pattern}</pattern>
        </encoder>
        <! -- The name of the file being written to, can be a relative or absolute directory, if the parent directory doesn't exist it will be created automatically, there is no default value. -->
        <file>${log_file}/</file>
    </appender>
    <! --Set the log level -->
    <root level="ALL">
        <! --Referencing the FileAppender configured above to output logs to a file --> <!
        <appender-ref ref="file" />
    </root>
</configuration>

The log output is as follows

将日志输出到文件中

7.2.5 Generating html appender objects
<?xml version="1.0" encoding="UTF-8"? >;xml version="1.0" encoding="UTF-8"?
<configuration>
    <! -- Add a property named pattern to set the log output to be--> <!
    <! --format output: %d for date, %thread for thread name, %-5level: level shows 5 character widths from left %msg: log message, %n is a line break -->!
    <property name="pattern" value="%-5level%d{yyyyy-MM-dd HH:mm:ss}%c%M%L%thread%m"/>

    <! --Set the log file storage path-->
    <property name="log_file" value="d:/logs"> </property>

    <! -- Output to file -->!
    <appender name="htmlFile" class="">

        <encoder class="">

            <layout class="">
                <! --Referencing the pattern attribute configured above -- >
                <pattern>${pattern}</pattern>
            </layout>
        </encoder>
        <! -- The name of the file being written to, can be a relative or absolute directory, if the parent directory doesn't exist it will be created automatically, there is no default value. -->
        <file>${log_file}/</file>
    </appender>
    <! --Set the log level -->
    <root level="ALL">
        <! --Referencing the FileAppender configured above to output logs to a file --> <!
        <appender-ref ref="htmlFile" />
    </root>
</configuration>

Log Output: existd:/logsdirectory to generate a file

image-20240810171050844

7.3 Logback log splitting and compression ⭐

Split logs by time, log size and compress logs in production environmentsVery, very important.That's why we're singling it out.

configuration file

<?xml version="1.0" encoding="UTF-8"? >;xml version="1.0" encoding="UTF-8"?
<configuration>
    <! -- Add a property named pattern to set the log output to be--> <!
    <! --format output: %d for date, %thread for thread name, %-5level: level shows 5 character widths from the left %msg: log message, %n is a line break -->!
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c %M %L [%thread] %m %n" />

    <! --Set the log file storage path -->
    <property name="log_file" value="d:/logs"> </property>

    <! -- Output to file -->!
    <appender name="rollFile" class="">
        <encoder class="">
            <! --Referencing the pattern attribute configured above -- >
            <pattern>${pattern}</pattern>
        </encoder>
        <! -- The name of the file being written to, can be a relative or absolute directory, if the parent directory doesn't exist it will be created automatically, there is no default value. -->
        <file> ${log_file}/roll_logback.log</file>
        <! --roll_log file: rolling policy based on time -- >
        < rollingPolicy class="">
            <! --File name for log file output -- > < <fileNamePolicy class="">!
            <fileNamePattern> ${log_file}/roll_logback.%d{yyyy-MM-dd}.log%</fileNamePattern>
            <! --Specify the file split size -->.
            <maxFileSize>1MB</maxFileSize>
            <! --Log file retention days -->
            <MaxHistory>3</MaxHistory>
        </rollingPolicy>
    </appender>
    <! --Set the logging level-->!
    <root level="ALL">
        <! --Referencing the FileAppender configured above to output logs to a file --> <!
        <appender-ref ref="rollFile" />
    </root>
</configuration>

Log rolling output: Split by date and file size

按日期和文件大小进行拆分

7.4 Asynchronous logs

Let's start by explaining what asynchronous logging is?

We output the logs to a file, which would involve a lot ofiooperation, very time-consuming, if you need to output a large number of logs, it may affect the normal main thread business logic.

To solve this problem, asynchronous logging came into play. Instead of writing log messages directly to a log file or to the console, the log messages are first sent to a queue, the

A dedicated thread then handles the writing of these log messages.

This has the advantage of reducing the impact of logging on the operation of the main program and increasing the efficiency of the program.

7.4.1 No asynchronous logging
private static final Logger logger = ();

    @Test
    public void testLogbackQuick(){

        // Log output
        ("This is an error log.");
        ("This is a warning log");
        ("This is a message log"); ("This is a message log"); ("This is a message log")
        ("This is a debug log"); ("This is a debug log").
        ("This is a trace log").

        // Simulate the business logic here
        ("Xiaofan is 18 years old");; //This is a debugging log.
        ("Xiaofan's personal blog is:");;
        ("Xiaofan's personal public number is: programmer Xiaofan"); ("Xiaofan's personal public number is: programmer Xiaofan"); ("Xiaofan's personal public number is: programmer Xiaofan");
        ("Xiaofan's personal weibo is: xie_zhr"); ("Xiaofan's personal weibo is: xie_zhr").
        ("Welcome to pay attention to Xiaofan, continuous output of dry goods !!!!!") ;
    }

Output results:

未加异步日志

From the console output above, only when the log output is completed after our business logic code is executed. If the logging takes a long time, it affects the efficiency very much!

7.4.2 Adding asynchronous logs

We simply add the following key configuration to the original configuration file

<! --add asynchronous logging configuration-->
<appender name="async" class="">
    <appender-ref ref="console" />
</appender>
<root level="ALL"> <!
    <! --Referencing the consoleAppender configured above to output logs to the console -->
    <appender-ref ref="console" />;
    <! --Refers to the asyncAppender configured above to output logs to the console --> <appender-ref ref="console" /> <!
    <appender-ref ref="async" />; <!
</root>

Log output effect:

异步日志输出效果

From the above log log output, it is no longer log output and then business logic code execution, but asynchronous execution of the

VIII. Log4j2 logging framework

Official website:/log4j//

Log4j2beLog4jThe upgraded version of the referenceLogbackSome of the best designs, bug fixes, performance and functionality have been greatly improved

This is mainly reflected in the following areas

  • Performance Enhancement: Log4j2 Exhibits higher throughput in multi-threaded environments than theLog4j cap (a poem)Logback 10 times higher

  • Asynchronous logLog4j2 Asynchronous logging is supported with theAsyncAppender maybeAsyncLogger Implementation. Asynchronous logging reduces the impact of logging on the performance of the main program, especially in highly concurrent scenarios

  • Auto Reload ConfigurationLog4j2 Support for dynamically modifying log levels without restarting the application is borrowed from theLogback design

  • no-spam mechanismLog4j2 In most cases, a garbage-free mechanism is used to avoid frequent log collection caused by theJVM GC2

  • Exception handlingLog4j2 provides an exception handling mechanism whereby exceptions in the Appender can be sensed by the application, and theLogback Exceptions in the

Log4j2There are so many advantages, so in the futureSLF4j+Log4j2combinatorial

8.1 Quick Start

Log4j2 is not only the logging implementation but also the logging facade. In our quick start, we'll use Log4j2 as both the logging facade and the logging implementation to get started quickly!

8.1.1 Adding dependencies
<!--increaselog4j2Journal facadeAPI-->
<dependency>
    <groupId>.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.23.1</version>
</dependency>
<!--increaselog4j2Logging Implementation-->
<dependency>
    <groupId>.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.23.1</version>
</dependency>
8.1.2 Adding Logging Implementation Code
public class Log4j2Test {

    private static final Logger logger = ();
    Log4j2Test { private static final Logger logger = (); @Test
    public void Log4j2Test(){
        ("This is a fatal message.");
        ("This is an error message"); ("This is an error message").
        ("This is a warning message"); ("This is a warning message"); ("This is a warning message"); ("This is a warning message")
        ("This is a general message").
        ("This is a debugging message"); ("This is a debugging message"); ("This is a debugging message"); ("This is a debugging message").
        ("This is a trace message").

    }
}

The log output is as follows

log4j2 日志输出结果

8.2 Using the slf4j+log4j2 combination

As we mentioned earlierSLF4j+Log4j2Combinations will be a big trend in the future of logging, so next we'll use this combination to output logs

Importing dependencies

<!--increaselog4j2Journal facadeAPI-->
<dependency>
    <groupId>.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.23.1</version>
</dependency>
<!--increaselog4j2Logging Implementation-->
<dependency>
    <groupId>.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.23.1</version>
</dependency>

<!--increaseslf4j作为Journal facade,utilizationlog4j2作为Logging Implementation-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.13</version>
</dependency>
<!--increaselog4j2together withslf4jbridge-->
<dependency>
    <groupId>.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.23.1</version>
</dependency>

Log Output Code

public class Log4j2Test {
// Here we switch to the slf4j facade interface
    private static final Logger logger = ();

    @Test
    public void Log4j2Test(){
        ("This is an error message.");
        ("This is a warning message"); ("This is a warning message"); ("This is a warning message"); ("This is a warning message")
        ("This is a general message"); ("This is a general message").
        ("This is a debugging message"); ("This is a debugging message").
        ("This is a trace message").

    }
}

Log output effect

slf4j+log4j2组合日志输出

8.3 Log4j2 Configuration

log4j2 loads the configuration in the file under the classpath by default.

The following test through the configuration file, the configuration is similar, we will not explain here, to give the complete configuration of the

<?xml version="1.0" encoding="UTF-8" ? >!
<! --status="warn" The output logging level of the logging framework itself can be changed to debug monitorInterval="5" The interval for automatically loading the configuration file is no less than 5 seconds; modifying the configuration file in the production environment is a hot update without restarting the application --> <!
<configuration status="warn" monitorInterval="5">!
    <! --Centralized configuration properties for management Used via :${name} --> <properties>!
    <properties>
        <property name="LOG_HOME"> D:/logs</property>
    </properties>
    <! --Log Processing -->
    <Appenders>.
        <! --Console output appender, SYSTEM_OUT outputs black, SYSTEM_ERR outputs red -->!
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>
        <! -- Log file output appender -->!
        <File name="file" fileName="${LOG_HOME}/">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:}] [%-5level] %l %c{36} - %m%n" />
        </File>
        <! -- Log file output appender with random read/write streams for performance improvement -->
        <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:}] [%-5level] %l %c{36} - %m%n" />
        < /RandomAccessFile>
        <! --appender for log files split according to certain rules -->!
        <! -- appender of the split file -->!
        <! -- Naming rules for split log files:,, -->!
        < RollingFile name="rollingFile" fileName="${LOG_HOME}/"
                     filePattern="${LOG_HOME}/$${date:yyyy-MM-dd}/rolling-%d{yyyy-MM-dd}-%" >
            <! -- Log Level Filter -->!
            < ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            <! -- Log message format -->
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:}] [%-5level] %l %c{36} - %msg%n" />
            <Policies>.
                <! -- On system startup, the departure split rule produces a new log file -->
                < OnStartupTriggeringPolicy />
                <! -- Split by file size, 1MB -->.
                < SizeBasedTriggeringPolicy size="1MB" />
                <! -- Split by timestamp, rule defined according to filePattern -->
                <TimeBasedTriggeringPolicy />.
            < /Policies>
            <! -- The number of files in the same directory is limited to 10, overriding --> < DefaultRolloverPolicy
            <DefaultRolloverStrategy max="10" /> </RollingStrategy> </RolloverStrategy
        </RollingFile>
    </Appenders>
    <! -- logger definition -- &>.
    <Loggers>.
        <! --Configuration using rootLogger Logging level level="trace" --> <Root level="trace" -->!
        <Root level="trace">
            <! --Specify the processor used for logging -->!
            <AppenderRef ref="Console" />
<! -- <AppenderRef ref="file"/> -->!
            <AppenderRef ref="rollingFile" />
            <AppenderRef ref="accessFile" />
        </Root>.
    </Loggers>.
</configuration>.

The log output is as follows

日志按天拆分

The following screenshot for the log of 2024-08-11 according to the log file size of 1MB split into 10 and compressed, split the full 10 files after the new log will overwrite the old log, the other days of similar

按日志大小和文件数进行拆分

8.4 Log4j2 Asynchronous Logging

Log4j2The biggest feature is the asynchronous logging, which just because of the asynchronous logging, improves the performance so much.

Below is the performance comparison chart given by the official website, from which we can see that in theglobal asynchronous mode(Loggers all async) andhybrid asynchronous mode(Loggers mixed sync/async)

The performance will simply beLogbackcap (a poem)Log4jThe logging framework dumped a street.

What is global asynchronous mode and mixed asynchronous mode? We'll explain this in more detail later

日志框架性能比较

8.4.1 Explanation of unfamiliar terms
  • Synchronization Log: Imagine you have a bunch of letters to write, and you have to write each one by hand, and finish it before you can go do anything else. In this process, you have to write one letter at a time and can't do anything else at the same time, which is similar to synchronized logging. In a program, synchronized logging means that every time you record a log, the program has to stop and wait for the log to finish before it can continue with other tasks. The good thing about this is that you don't lose the letter (log), but the bad thing is that the process of writing the letter (logging the log), if it's too slow, delays you from doing other things (running the program)

  • Asynchronous log: If you are particularly busy, you might get an assistant to write the letter for you. All you have to do is tell him what to write, and then you can go on about your business while the assistant writes and mails the letter for you. This process is like asynchronous logging. In a program, asynchronous logging means that the program can give the log messages to a dedicated "helper" (usually another thread or process), and then the program can go on with its other tasks without waiting for the log to be written. The advantage of this is that tasks can be processed faster without delaying business, but occasionally a letter or two (the log) may not get sent due to unforeseen circumstances.

  • global asynchronous: All logging is done asynchronously.

  • hybrid asynchronous: to use both synchronous and asynchronous logging in an application, which makes logging configuration more flexible

8.4.2 Synchronous versus Asynchronous Logging
  1. Synchronizing the logging process

同步日志流程

2、Asynchronous logging process

异步日志流程图

8.5 Asynchronous Logging Configuration

Asynchronous logging is implemented in a total of two ways

  • AsyncAppender [Hardly used in production due to low performance]

  • AsyncLogger [Used a lot in production because of the high performance]

    • global asynchronous
    • hybrid asynchronous

The first way is not good enough for performance because it's not used much, so we won't talk about it here, let's be specific with the second configuration

Either way, the first step is to introduce asynchronous dependencies

<!--Asynchronous logging dependencies-->
<dependency>
    <groupId></groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.4</version>
</dependency>

global asynchronous

Simply click on theresourcesAdd the, as follows

Log4jContextSelector=.

全局异步

Log output results

全局异步日志开启,

② Hybrid Asynchronous Configuration

First, we need to turn off the global asynchronous configuration, and add the above added Content notes are sufficient

configure

<?xml version="1.0" encoding="UTF-8" ? >!
<! --status="warn" The output logging level of the logging framework itself can be changed to debug monitorInterval="5" The interval for automatically loading the configuration file is no less than 5 seconds; modifying the configuration file in the production environment is a hot update, no need to restart the application --> <!
<configuration status="debug" monitorInterval="5">!
    <! --Centralized configuration properties for management Used via :${name} --> <properties>!
    <properties>
        <property name="LOG_HOME"> D:/logs</property>
    </properties>
    <! --Log Processing -->
    <Appenders>.
        <! --Console output appender, SYSTEM_OUT outputs black, SYSTEM_ERR outputs red -->!
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>
        <! -- Log file output appender -->!
        <File name="file" fileName="${LOG_HOME}/">
            <! -- <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:}] [%-5level] %l %c{36} - %m%n" /> -->!
            <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
        </File>
        <Async name="Async">
            <AppenderRef ref="file" />
        </Async>
    </Appenders>
    <! --logger Definitions -->!
    <Loggers>.
        <! --Customizing logger objects includeLocation="false" Turns off line numbering information for logging; turning it on can severely impact the performance of asynchronous output additivity="false" No longer inherits the rootlogger object -->.
        <AsyncLogger name="" level="trace" includeLocation="false" additivity="false">
            <AppenderRef ref="Console" />
        </AsyncLogger>
        <! -- Configure logging level with rootLogger level="trace" -->
        <Root level="trace"> <!
            <! -- Specify the processor to be used for logging -->!
            <AppenderRef ref="Console" />; <!
            <! -- Use asynchronous appender -->!
            <AppenderRef ref="Async" />
        </Root>
    </Loggers>
</configuration>.

Output results:

开启混合异步日志,控制台输出采用异步日志

Caveats:

  • topologyAsyncAppender The global and hybrid configurations must not be present at the same time, or logging performance will be affected.
  • includeLocation="false" Turn off line number information for logging Configuration must be added, otherwise logging performance will be degraded

IX. Alibaba Log Statute

Through the above eight subsections we should be very familiar with the Java logging framework, and also know how to use it. However, in the logging development, the use of logging still have to write the statute we need to comply with.

The following is the logging protocol from the Alibaba Java Development Manual.

❶【obligatoryThe logging system may not be used directly in the] application (Log4jLogback) in theAPIand should instead rely on the use of a logging framework (SLF4JJCL--Jakarta Commons Logging) in theAPI, the logging framework using the facade pattern facilitates maintenance and uniformity of log handling across classes.

Description: logging framework (SLF4J, JCL - Jakarta Commons Logging) to use (recommended SLF4J)

1) UseSLF4J

import org.;
import org.;
private static final Logger logger = ();
  1. utilization JCL
import ;
import ;
private static final Log log = ();

❷【obligatoryAll log files should be kept for at least 15 days because some exceptions are characterized by a "weekly" frequency. For the day's log, the name of the log file should be "Application Name.log"to save.

Saved in "/home/admin/application-name/logs/" directory, the past logs are formatted as.{logname}.log.{save date}, date format:yyyy-MM-dd

standard practice: In the case of the aap application, for example, the logs are stored in the/home/admin/aapserver/logs/The name of the history log is.2021-03-23

❸【obligatory】According to national laws, the network operation status, network security events, personal sensitive information operation and other related records, retained logs of not less than six months, and network multi-computer backup.

❹【obligatory]Naming of extended logs (e.g., punching, temporary monitoring, access logs, etc.) in the application:appName_logType_logName.log

  • logType:Log type, e.g.stats/monitor/accessetc;

  • logName:Log Description.

    The benefits of this naming: through the file name you can know what application the log file belongs to, what type, what purpose, but also conducive to categorization to find.

Description: It is recommended to categorize the logs, such as storing the error logs and business logs separately, so that it is easy for the developers to view them, and it is also easy to monitor the system in a timely manner through the logs.

standard practicemppserver The application monitors time zone conversion anomalies individually, for example:

mppserver_monitor_timeZoneConvert.log

❺ 【obligatory] The splicing between string variables during logging output is done using a placeholder approach.

Note: Because String strings are spliced using theStringBuilder (used form a nominal expression)append()way, there is some performance loss. Using placeholders to simply replace actions can be an effective performance boost.

Positive Example:

("Processing trade with id: {} and symbol: {}", id, symbol);

❻【obligatory]Fortrace/debug/info level of log output, log level switching judgment must be performed.

Note: While in thedebug(parameter)The first line of code inside the method ofisDisabled(Level.DEBUG_INT)is true (the common implementations of Slf4j, Log4j, and Logback), it is straightforward toreturn, but the arguments may perform string splicing operations. In addition, if thedebug(getName())Within such parameters aregetName() method calls, needlessly wasting the overhead of method calls.

Positive Example:

// If this is true, then you can output trace and debug level logs
if (()) {
    ("Current ID is: {} and name is: {}", id, getName()); }
}

❼【obligatory] to avoid duplicate log printing and wasting disk space, be sure to set the log configuration file in theadditivity=false

Positive Example:

<logger name="" additivity="false">

❽ [Mandatory] Direct use is prohibited in production environments. maybe Output logs or use the() Print the exception stack .

Description: Standard log output and standard error output files are output each time theJbossScrolling only on reboot, if a lot of output is sent to these two files, it can easily cause the file size to exceed the operating system size limit.

❾ [Mandatory] Exception information should include two types of information: crime scene information and exception stack information. If they are not handled, then by the keywordthrows Throw it upwards.

Positive Example:

("inputParams:{} and errorMessage:{}", each type of parameter or object toString(), (), e);

❿ 【obligatoryThe JSON utility is prohibited from directly converting objects intoString

Description: If some of theget Methods are overridden and there are cases where exceptions are thrown, then the normal execution of the business process may be affected by the printing of logs.

Positive Example:

Printing the log prints out only the values of business-related attributes or calls to its object'stoString() Methods.

⓫ 【testimonials]Logging is done carefully. Production environments prohibit outputdebug Logs; selective outputinfo Log;

If you use thewarn to record information about business behavior when you first go online, be sure to pay attention to the amount of log output to avoid bursting the server disk, and remember to delete these observation logs in a timely manner.

Note: Outputting a large number of invalid logs is not conducive to system performance improvement, nor is it conducive to quickly locating points of error. When logging, please think: Is anyone really reading these logs? What can you do when you see this log? Can it bring benefits to problem troubleshooting?

⓬ 【testimonials] can be usedwarn Log level to record user input parameter errors to avoid users complaining about nothing.

Note: If not necessary, please do not play in this scenarioerror level to avoid frequent alarms. Pay attention to the level of log output thaterror level logs only system logic errors, exceptions, or important error messages.

⓭ 【testimonials】 Try to use English to describe the log error information, if the error information in the log is not described clearly in English then use the Chinese description can be, otherwise it is easy to produce ambiguity.

Note: Internationalized teams or servers deployed overseas use all English to annotate and describe log error messages due to character set issues.

That's the end of this installment.★,°:.☆( ̄▽ ̄)/$:.°★ . I hope this helps.

We'll see you next issue ヾ(-ω-`)o (●'◡'●)