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
- 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.
- Monitoring of operational status: Logs allow you to understand the operational status of the program, such as user actions, system performance, etc.
- 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
Java
comes 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 theLog4j
,Log4j2
Significantly 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)Log4j
One of the original developers ofSpring Boot
Default logging, lightweight, excellent performance, and more comprehensive features
III. JUL logging framework
3.1 Main components
- Logger: The logger, the heart of the logging system, is used to generate log records.
-
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 more
Handler
- Formatter: Log formatter responsible for defining the output format of the log. For example, timestamp, log level, message, etc.
-
Level: Set the log level, the common levels are
SEVERE
、WARNING
、INFO
、CONFIG
、FINE
、FINER
、FINEST
etc. - Filter: This component is used to filter logging. You can set some rules and only logs that fulfill these rules will be logged.
- 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
- gain
Logger
Example. - increase
Handler
- Added for the previous step
Handler
Set the log level (Level
) and format output (Formatter
) - establish
Filter
(machine) filter - because of
Logger
instance adds a log handler (Handler
) and log filters (Filter
) - Record logs.
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});;
}
}
3.4 Log level
Log level system to differentiate the importance of logs
3.4.1 Log level
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
② Log file outputelement
code interpretation:
-
Logger Fetch: First get a file named
LoggingExample
(used form a nominal expression)Logger
Example. -
Setting the log level: Set the Logger's logging level to
INFO
, which means that logs at the INFO level and above will be logged. -
Console Handler: Create a
ConsoleHandler
instance, set its log level toWARNING
and customize the output format of the log. -
File Handler: Trying to create a
FileHandler
instance that writes logs to thefile and set its log level to
ALL
, meaning that all levels of logging will be logged to a file. -
Custom Formatter: Create a customized
SimpleFormatter
, used to define the output format of the log. -
Filter Settings: Creates a file that implements the
Filter
interface's anonymous inner class and overrides theisLoggable
method, which implements the filtering logic, only logs messages that contain the string "important". - Apply Filter: Apply the created Filter to the Logger.
- log: Record different levels of logs, showing how different levels of logs are processed by Handler and Filter.
- 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-dd
which1$
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 the
String
classformat
The use of this method
3.7.1 String
(used form a nominal expression)format
methodologies
String
(used form a nominal expression)format
method is used to format the string.
format
A 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
%s
cap (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$s
Reuse 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. x
Discontinued. Users are advised to upgrade to Log4j 2
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:
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
-
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. -
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. -
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
Log4j
There is a speciallogger
be known asroot
It'slogger
The root of the otherlogger
All 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 is
The 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 atLogManager
Log 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, add
It is also inherited from
rootLogger
, 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 .
JCL
full nameJakarta Commons Logging
is a generic log provided by ApacheAPI
,JCL
comes with a logging implementation in thesimplelog
But this function is very simple.
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 own
JUL
to 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
① Introductionlog4j
Logging 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:
We can see that using theJCL
After the log facade, we start with thesimplelog
The logging framework switches to thelog4j
Logging framework, no code changed.
VI. SLF4j log facade
SLF4j
The full name isSimple Logging Facade For Java
Java's simple logging facade and the last subsection talks about theJCL
Doing the same job.
In most current Java projects, the logging framework will basically choose theslf4j-api
As a facade, with a concrete realization frameworklogback
、log4j
equal use
SLF4j
It 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 website
slf4j
Log Binding Chart, by the way, the official website is here https:///
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
- Only the log facade is imported, no log implementation is imported, no log output will be performed
-
logback
、simplelog
、no-operation
The framework followsSLF4j
Specification Import the jar package to use -
log4j
、JUL
are relatively old log frames that do not followSLF4j
specification, adapters need to be introduced to use the - When we import the
slf4j-nop
No 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
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 Bindingslog4j
Logging 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
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
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)API
This 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-slf4j
、jul-to-slf4j
、jcl-over-slf4j
It is then possible to realize the effect of theNo changes to the original codeThe logs are removed from thelog4j
、jul
、jcl
migrate toslf4j
+logback
Log Portfolio
6.3.3 Bridging steps
summarized below
Log4j
migrate toslf4j
+logback
Examples of log combinations
- Removing the old log frame
Log4j
dependencies
-
increase
SLF4J
Bridging components provided -
Adding to the project
SLF4J
Specific 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"); }
}
}
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?
-
Logger
: Logger for logging different levels of log messages such as errors, warnings, messages, debugging and tracing. -
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. -
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. -
Layout
: Older versions ofLogback
The component used to define the log format in the Encoder has replaced Layout's functionality in this new version. -
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. -
Configuration
: Used to configureLogback
settings, such as setting the logging level, the type and parameters of the Appender, and so on. Configuration can be done via theXML
、JSON
orGroovy
script 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 aConsoleAppender
Console 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 aFileAppender
Output 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:/logs
directory to generate a file
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 ofio
operation, 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//
Log4j2
beLog4j
The upgraded version of the referenceLogback
Some 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 log:
Log4j2
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 Configuration:
Log4j2
Support for dynamically modifying log levels without restarting the application is borrowed from theLogback
design -
no-spam mechanism:
Log4j2
In most cases, a garbage-free mechanism is used to avoid frequent log collection caused by theJVM GC2
。 -
Exception handling:
Log4j2
provides an exception handling mechanism whereby exceptions in the Appender can be sensed by the application, and theLogback
Exceptions in the
Log4j2
There are so many advantages, so in the futureSLF4j
+Log4j2
combinatorial
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
8.2 Using the slf4j+log4j2 combination
As we mentioned earlier
SLF4j
+Log4j2
Combinations 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
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
Log4j2
The 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 beLogback
cap (a poem)Log4j
The 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
- 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 theresources
Add 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:
- topology
AsyncAppender
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 (Log4j
、Logback
) in theAPI
and should instead rely on the use of a logging framework (SLF4J
、JCL--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 = ();
- 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/access
etc; -
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 practice:mppserver
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 the
StringBuilder
(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 the
debug(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 the
Jboss
Scrolling 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 the
get
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 scenario
error
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 (●'◡'●)