During the project operation, functional debugging and user behavior are often required. Some people are used to using it, but this is not recommended. It is only convenient to use but not easy to maintain and has no scalability. Compared with log4j, log4j can control the destination, output format and level of log information, etc., so that we can control the log generation process more carefully.
Log4j2 is an upgrade to Log4j1, with significant improvements in performance and functionality, including enhanced throughput in multithreads, support for placeholders, automatic configuration file reloading, etc.
1. Introduction
1. Download the jar package
<dependencies> <dependency> <groupId>.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.10.0</version> </dependency> </dependencies>
2. Configuration file
Log4j contains four configuration factory implementations: JSON, YAML, properties, and XML. This article introduces the commonly used method XML.
Log4j has the ability to automatically configure itself during initialization. When Log4j starts, it will locate all names-compliant files under the classpath, in priority order: > > >
3. A simple example
xml configuration:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
Java code:
private static final Logger logger = (); @Test public void testLog4j(){ ("hello world!"); } }
Console information
22:17:47.146 [main] INFO MyApp - hello world!
2. Module introduction
<Configuration>
property | describe |
monitorInterval | If the file is modified, the configuration will be reloaded after the specified time. Units of seconds, minimum value is 5 |
packages | A comma-separated list of package names used to search for plug-ins, such as custom filters, appenders, etc. The plugin will only load once, so you must restart the project if it wants to take effect after modification. |
status | The internal log level, setting the value to debug can clearly see the entire log event flow on the console, and the Logger used is. |
strict | Strict XML format is allowed. JSON configuration is not supported |
verbose | Enable diagnostic information when loading plugin |
<Appenders>
Log4j allows log requests to be printed to multiple destinations. In the log4j language, the output destination is called Appender. Currently, appenders exist in consoles, files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog daemons and various database apis. The following introduces several more commonly used appenders. If you need to know more, you can check it on the official website.
1、ConsoleAppender
Output to console, <Console>
Parameter name |
type |
describe |
filter |
Filter |
Filter |
layout |
Layout |
Log output format |
follow |
boolean |
|
direct |
boolean |
|
name |
String |
The name of Appender |
ignoreExceptions |
boolean |
Default true, ignore write exceptions |
target |
String |
SYSTEM_OUT or SYSTEM_ERR, default is SYSTEM_OUT |
2、FileAppender
Output to file, <File>
parameter |
type |
describe |
---|---|---|
append |
boolean |
The default is true, and new records will be appended to the end of the file |
bufferedIO |
boolean |
The default is true, using buffers can significantly improve performance |
bufferSize |
int |
When bufferedIO is true, the buffer size of this property is 8192 bytes by default. |
createOnDemand |
boolean |
appender creates files on demand. The appender will create this file only when a log event passes through all filters and is routed to the appender. The default value is false |
filter |
Filter |
A filter to determine whether the event should be handled by this Appender. Multiple filters can be used with composite filters |
fileName |
String |
The name of the file to be written. If the file or any of its parent directories does not exist, they will be created |
immediateFlush |
boolean |
By default true, there will be a refresh after each write. This will ensure that the buffer's data is written to disk, but may affect performance. |
layout |
Layout |
Log format |
locking |
boolean |
File lock, default false |
name |
String |
The name of Appender |
ignoreExceptions |
boolean |
Default true, ignore write exceptions |
filePermissions |
String |
Define file permissions Example: rw------ or rw-rw-rw- etc... |
fileOwner |
String |
Define file owner |
fileGroup |
String |
Define file groups |
3、JDBCAppender
JDBCAppender uses standard JDBC to write log events into relational database tables. It can be configured to obtain a JDBC connection using a JNDI data source or a custom factory method. Regardless of the method, it must be supported by the connection pool.
Otherwise, logging performance will be greatly affected.
If the configured JDBC driver supports batch statements and configures the buffer size to a positive number, the log event will be batched.
(1)<JDBC>
parameter |
type |
describe |
---|---|---|
name |
String |
Must, name of appender |
ignoreExceptions |
boolean |
Default true, ignore log event exceptions |
filter |
Filter |
Filter |
bufferSize |
int |
If an integer greater than 0, this will cause the appender to buffer the log event and refresh the write data when the buffer reaches that size |
connectionSource |
ConnectionSource |
Must be retrieved database connection |
tableName |
String |
Required, insert the data table name of the log event |
columnConfigs |
ColumnConfig[] |
Must, fields that need to be inserted into the database are composed of multiple <Column> elements |
columnMappings |
ColumnMapping[] |
Required, field mapping configuration |
(2) Use <DataSource> to obtain JDBC connection, only jndi is listed here:
parameter | type | describe |
---|---|---|
jndiName | String | Required,If the configured jndi is jdbc/LoggingDatabase, the value here is java:comp/env/jdbc/LoggingDatabase.The data source must be supported by a connection pool;Otherwise, logging will be very slow. |
(3) Use <Column> to specify which columns in the table to be written and how to write them. It has no SQL injection vulnerability.
parameter | type | describe |
---|---|---|
name | String |
Required, table field name |
pattern | String |
Insert values using PatternLayout mode. Note: In the same Column element, only one of the three attributes of pattern, literal, and isEventTimestamp can exist in the same Column element. |
literal | String |
This value will be directly included in the SQL statement and executed, for example: the rand() function will generate a random number, similar to ${} in myibats |
isEventTimestamp | boolean |
Whether the time format |
isUnicode | boolean |
This property is ignored unless a pattern is specified. If true, the value will be inserted into Unicode. Otherwise, the value will be inserted into a non-Unicode. |
isClob | boolean |
This property is ignored unless a pattern is specified. If true, the value will be inserted into the CLOB, otherwise the varchar, nvarchar will be inserted into |
Example:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error"> <Appenders> <JDBC name="databaseAppender" tableName="dbo.application_log"> <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" /> <Column name="eventDate" isEventTimestamp="true" /> <Column name="level" pattern="%level" /> <Column name="logger" pattern="%logger" /> <Column name="message" pattern="%message" /> <Column name="exception" pattern="%ex{full}" /> </JDBC> </Appenders> <Loggers> <Root level="warn"> <AppenderRef ref="databaseAppender"/> </Root> </Loggers> </Configuration>
<PatternLayout>
(1) Date, %d/%date
Pattern |
Example |
---|---|
%d{DEFAULT} |
2012-11-02 14:34:02,781 |
%d{ISO8601} |
2012-11-02T14:34:02,781 |
%d{ISO8601_BASIC} |
20121102T143402,781 |
%d{ABSOLUTE} |
14:34:02,781 |
%d{DATE} |
02 Nov 2012 14:34:02,781 |
%d{COMPACT} |
20121102143402781 |
%d{HH:mm:ss,SSS} |
14:34:02,781 |
%d{dd MMM yyyy HH:mm:ss,SSS} |
02 Nov 2012 14:34:02,781 |
%d{HH:mm:ss}{GMT+0} |
18:34:02 |
%d{UNIX} |
1351866842 |
%d{UNIX_MILLIS} |
1351866842781 |
Of course you can also customize the format, such as %d{yyyy-MM-dd HH:mm:ss}
(2) Logger, %c/%logger
Conversion Pattern |
Logger Name |
result |
---|---|---|
%c{1} |
Foo |
|
%c{2} |
||
%c{10} |
||
%c{-1} |
||
%c{-2} |
||
%c{-10} |
||
%c{1.} |
||
%c{1.1.~.~} |
.~.~.Foo |
|
%c{.} |
....Foo |
{?} - When ? is a positive integer, it means taking n parts from the right, and a negative integer means removing n parts from the left. So why %c{-10} is the complete name, I don't know. Welcome to leave a message
(3) Log information, %m/%msg/%message
(4) Log level, %level
<Filter>
log4j2 comes with a variety of filters for direct use, and we can also define filters ourselves:
import .; import .; import .; import .; import .; import .; import .; import .; import .; import .; @Plugin(name = "MyFilter", category = "Core", elementType = "filter", printObject = true) public final class MyFilter extends AbstractFilter { private final Level level; private MyFilter(Level level, Result onMatch, Result onMismatch) { super(onMatch, onMismatch); = level; } public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) { return filter(level); } public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) { return filter(level); } public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) { return filter(level); } @Override public Result filter(LogEvent event) { return filter(()); } private Result filter(Level level) { /* * Business logic * */ return () ? onMatch : onMismatch; } @Override public String toString() { return (); } @PluginFactory public static MyFilter createFilter(@PluginAttribute(value = "level", defaultString = "ERROR") Level level, @PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch, @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) { return new MyFilter(level, onMatch, onMismatch); } }
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" monitorInterval="5" packages="your packages" verbose="false" strict="true"> <Appenders> <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="true"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %level %logger{10} - %msg"/> <MyFilter level="info" onMatch="ACCEPT"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
Replenish:
In practical applications, it is sometimes necessary to record user access information, such as request parameters, user ID, etc. In log4j1, we will use MDC and NDC to store the application context information, while log4j2 uses ThreadContext to implement the functions of both MDC and NDC.
(1) NDC uses a stack-like mechanism to store context information, and threads are independent.
Use %x to output in PatternLayout, note that x is lowercase.
Example:
("hello world!");
<Column name="tip" pattern="%x" />
(2) MDC uses a map-like mechanism to store information, and threads are independent.
Use %X{userId} in PatternLayout to output, note that X is capitalized.
Example:
("userId","1");
<Column name="userId" pattern="%X{userId}" />
Note that after using it, call clearAll() to clear the context map and stack.
api:/log4j//
Official website address:/log4j//
The above example code of the log4j2 project log component is all the content I share with you. I hope you can give you a reference and I hope you can support me more.