Java log Ultimate Guide
Java log Basics
Java uses a custom and scalable method to output logs. Although Java provides a set of basic log processing APIs through the java. util. logging package, you can easily use one or more other log solutions. Although these solutions use different methods to create log data, their ultimate goal is the same, that is, to output logs from your application to the target address.
In this section, we will explore the principles behind Java logs and explain how to use logs to make you a better Java developer.
Java log component
Java log API consists of the following three core components:
-
Loggers: Logger is responsible for capturing events and sending them to the appropriate Appender.
-
Appenders: Handlers, which records log events to the target location. Before outputting log events, Appenders uses Layouts to format the events.
-
Layouts: it is also known as Formatters. It is used to convert and format data in log events. Layouts determines the final form of data in a log record.
When Logger records an event, it forwards the event to the appropriate Appender. Appender then uses Layout to format the log record and send it to the console, file, or other target location. In addition, Filters allows you to specify whether an Appender can be applied to a specific log. In log configuration, Filters is not necessary, but it allows you to control the flow of log messages more flexibly.
Log framework
In Java, one or more log frameworks are required to output logs. These frameworks provide the necessary objects, methods, and configurations to transmit messages. Java provides a default framework in the java. util. logging package. In addition, there are many other third-party frameworks, including Log4j, Logback, and tinylog. There are other development kits, such as SLF4J and Apache Commons Logging, which provide some abstraction layers to decouple your code and log framework, this allows you to switch between different log frameworks.
How to choose a log solution depends on the complexity of your log Requirements, compatibility with other log solutions, ease of use, and personal preferences. Logback is developed based on version 1 earlier than Log4j. Therefore, their function sets are very similar. However, Log4j references some improvements in the latest version 2. For example, it supports multiple APIs and improves the performance of the Disruptor library. Tinylog is suitable for small projects because it lacks some functions and runs fast.
Another factor is the degree of support of the Framework for different Java-based projects. For example, the Android program can only use Log4j, Logback, or a third-party package to record logs. Apache Tomcat can use Log4j to record Internal messages, but can only use Log4j of version 1.
Abstraction Layer
Abstraction layers such as SLF4J decouple your applications from the log framework. The application can be bound to a specific log framework such as java at runtime. util. logging, Log4j, or Logback), which is achieved by adding the corresponding log framework to the application's class path. If the log framework configured in the class path is unavailable, the abstraction layer immediately cancels the corresponding logic of the call log. The abstraction layer makes it easier to change the existing Log framework of the project, or to integrate projects that use different log frameworks.
Configuration
Although all Java log frameworks can be configured through code, most of the configurations are completed through external configuration files. These files determine when to process log messages, and the log framework can load these files at runtime. Most configuration examples provided in this section use the configuration file.
Java. util. logging
The default Java log framework stores the configuration in a file named logging. properties. In this file, each line is a configuration item, and the configuration item uses the dot mark (dot notation) format. Java installs a global configuration file under the lib folder of its installation directory. However, when starting a Java program, you can specify. util. logging. config. A separate log configuration file can also be used to create and store logging in a personal project. properties file.
The following example describes how to define an Appender in the global logging. properties file:
# Default file output is in user's home directory.
Java. util. logging. FileHandler. pattern = % h/java % u. log
Java. util. logging. FileHandler. limit = 50000
Java. util. logging. FileHandler. count = 1
Java. util. logging. FileHandler. formatter = java. util. logging. XmlFormatter
Log4j
The syntax used by Log4j version 1 is similar to that used by java. util. logging. A program using Log4j looks for a file named log4j. properties in the project directory. By default, Log4j configuration outputs all log messages to the console. Log4j also supports configuration files in XML format. The corresponding configuration information is stored in the log4j. xml file.
Log4j version 2 supports configurations in XML, JSON, and YAML formats. These configurations are stored in the log4j2. xml, log4j2. json, and log4j2. yaml files respectively. Similar to version 1, version 2 looks for these files in the project directory. You can find the corresponding configuration file examples in each version of the document.
Logback
For Logback, most configurations are completed in the logback. xml file, which uses XML syntax similar to Log4j. Logback also supports configuration in the Groovy language. The configuration information is stored in the logback. groovy file. You can find the corresponding configuration file example through the link of each type of configuration file.
Loggers
Loggers are the objects used to trigger log events. They are created and called in our Java application before they pass the events to Appender. A class can contain multiple independent Loggers for different events. You can also embed a logger in a logger to create a logger hierarchy.
Create a new Logger
The process of creating a new Logger under different log frameworks is similar, although the specific method names called may be different. When using java. util. logging, you can use the Logger. getLogger (). getLogger () method to create a new Logger. This method receives a string parameter to specify the Logger name. If the Logger with the specified name already exists, you only need to return the existing Logger; otherwise, the program will create a new Logger. Generally, we use class. getName () as the name of the new Logger in the current class.
Logger logger = Logger. getLogger (MyClass. class. getName ());
Log events
Logger provides several methods to trigger log events. However,Before you record an event, you also need to set the level. The log level is used to determine the log severity. It can be used to filter log events or send them to different Appender. For more information, see the "Log Level" section.), Logger. in addition to log messages, the log () method also requires a log level as a parameter:
Logger. log (Level. WARNING, "This is a warning !");
Most log frameworks provide shortcuts for outputting specific levels of logs. For example, the following statement serves the same purpose as the preceding statement:
Logger. warning ("This is a warning !");
You can also prevent Logger from outputting messages lower than the specified log level. In the following example, Logger can only output log messages higher than the WARNING level, and discard messages whose log level is lower than the WARNING level:
Logger. setLevel (Level. WARNING );
We also have other methods to record additional information. Logp () Precise logs) allows you to specify the source class and method of each log record, while logrb () uses the logs bound to resources) you can specify the resource used to extract log messages. The entering () and exiting () methods allow you to record method call information to track program execution.
Appenders
Appenders forwards log messages to the expected output. It is responsible for receiving log events, formatting events using Layout, and sending them to the corresponding target. For a log event, we can use multiple Appenders to send the event to different target locations. For example, we can display a simple log event on the console and send it to the specified receiver via email.
Note that in java. util. logging, Appenders is called Handlers.
Add Appender
The Appender of most log frameworks performs similar functions, but the implementation is quite different. If java. util. logging is used, you can use the Logger. addHandler () method to add the Appender to the Logger. For example, the following code adds a new ConsoleHandler, which outputs logs to the console:
Logger. addHandler (new ConsoleHandler ());
A more common method to add an Appender is to use a configuration file. If java. util. logging is used, Appenders defines a list separated by commas. The following example outputs log events to the console and files:
Handlers = java. util. logging. lelehandler, java. util. logging. FileHandler
If an XML-based configuration file is used, Appenders will be added to the <Appenders> element. If Log4j is used, we can easily add a new leleappender to send log messages to the System. out:
<Console name = "console" target = "SYSTEM_OUT">
<PatternLayout pattern = "[% p] % t: % m % n"/>
</Console>
Appenders type
This section describes some more common Appenders and how they are implemented in various log frameworks.
ConsoleAppender
ConsoleAppender is one of the most common Appenders. It only displays log messages on the console. Many log frameworks use it as the default Appender and pre-configure it in the basic configuration. For example, the configuration parameters of ConsoleAppender in Log4j are as follows.
Parameters |
Description |
Filter |
Used to determine whether to use this Appender to process log events |
Layout |
Used to determine how to format the log record. By default, "% m % n" is used. It displays a log record in each line. |
Follow |
Used to determine whether the Appender needs to understand the changes of the output system. out or system. err. By default, this change does not need to be tracked. |
Name |
Used to set the Appender name |
IgnoreExceptions |
Used to determine whether to record exceptions during log event processing |
Target |
Specifies the output target location. SYSTEM_OUT is used by default, but it can also be changed to SYSTEM_ERR. |
A complete Log4j2 configuration file is as follows:
<? Xml version = "1.0" encoding = "UTF-8"?>
<Configuration status = "warn" name = "MyApp">
<Appenders>
<Console name = "MyAppender" target = "SYSTEM_OUT">
<PatternLayout pattern = "% m % n"/>
</Console>
</Appenders>
<Loggers>
<Root level = "error">
<AppenderRef ref = "MyAppender"/>
</Root>
</Loggers>
</Configuration>
This configuration file creates a ConsoleAppender named MyAppender. It uses PatternLayout to format log events and then outputs them to System. out. <Loggers> the element configures the Loggers defined in the program code. Here, we only configure one LoggerConfig, that is, the Logger named Root, which will receive log messages at the log level above ERROR. If we use logger. error () to record a message, it will appear on the console, like this:
An unexpected error occurred.
You can also use Logback to achieve the same effect:
<Configuration>
<Appender name = "MyAppender" class = "ch. qos. Logback. core. leleappender">
<Encoder>
<Pattern> % m % n </pattern>
</Encoder>
</Appender>
<Root level = "error">
<Appender-ref = "MyAppender"/>
</Root>
</Configuration>
FileAppenders
FileAppenders writes the log records to the file. It is responsible for opening and closing the file, appending the log records to the file, and locking the file to avoid data corruption or overwriting.
In Log4j, to create a FileAppender, you must specify the name of the target file, whether to append or overwrite the file, and whether to lock the file when writing logs:
...
<Appenders>
<File name = "MyFileAppender" fileName = "myLog. log" append = "true" locking = "true">
<PatternLayout pattern = "% m % n"/>
</File>
</Appenders>
...
In this way, we create a FileAppender named MyFileAppender, and lock the file when appending logs to the file.
If Logback is used, you can enable the prudent mode to ensure file integrity. Although the Prudent mode increases the time it takes to write files, it ensures the integrity of the files when multiple FileAppender or even multiple Java programs write logs to the same file.
...
<Appender name = "FileAppender" class = "ch. qos. Logback. core. FileAppender">
<File> myLog. log </file>
<Append> true </append>
<Prudent> true </prudent>
<Encoder>
<Pattern> % m % n </pattern>
</Encoder>
</Appender>
...
SyslogAppender
SyslogAppenders sends logs to the log service of the local or remote system. Syslog is a service that receives log events from operating systems, processes, other services, or other devices. The range of events can be from diagnostic information to hardware logon failures. Syslog events are classified by devices. It specifies the type of events being recorded. For example, auth facility indicates that this event is related to security and authentication.
Both Log4j and Logback have built-in support for SyslogAppenders. In Log4j, when creating SyslogAppender, you must specify the host number, port number, and Protocol of the syslog service listener. The following example shows how to set the device:
...
<Appenders>
<Syslog name = "SyslogAppender" host = "localhost" port = "514" protocol = "UDP" facility = "Auth"/>
</Appenders>
...
In Logback, we can achieve the same effect:
...
<Appender name = "SyslogAppender" class = "ch.qos.Logback.classic.net. SyslogAppender">
<SyslogHost> localhost </syslogHost>
<Port> 514 </port>
<Facility> Auth </facility>
</Appender>
...
Other Appender
We have already introduced some frequently used Appenders and many other Appender. They have added new features or implemented new features based on some other Appender. For example, RollingFileAppender in Log4j extends FileAppender, which can automatically create new log files when the specific conditions are met; SMTPAppender will send the log Content by email; failoverAppender automatically switches to another Appender if one or more Appender fails during log processing.
If you want to know