Introduction to the

Logback is one of the most popular logging tools in the world, with high performance, full functionality and documentation. The author is also the developer of log4j series.

This article introduces the common components and function points of Logback, and provides simple examples


javaHow to uselogback

Two key packages are introduced in POM.xml

 <! -- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

        <! -- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
Copy the code

Then create a logback.xml file in the Resources directory, as described in the section full configuration files available


The level of logging

You are advised to use the following levels in descending order

Level describe
ERROR The error event may still allow the application to continue running
WARN Specify potentially hazardous situations
INFO Specifies a message that highlights information about how the application is performing at the coarse-grained level
DEBUG Specifying fine-grained information events is the most useful application debugging
* * *
# # Appender level

What is an Appender?

ConsoleAppender(Output logs to the console)

Print the log information in the console

configuration type describe
encoder Encoder Log Output format
target String The log output target can be system. out or system. err. The default is system. out
withJansi boolean Default is false, this is not used, it seems that the output ANSI will have color, see the official website for details

sample:

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <! -- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
Copy the code

FileAppender(Output the log to a file)

FileAppender A subclass of OutputStreamAppender that outputs logs to the specified file. If the file already exists, append or rebuild the file at the end according to the configuration properties

configuration type describe
append boolean The default is true and the log is appended to the end of an existing file
encoder Encoder Log Output format
file String If the file or directory does not exist, it will be created. For example:logs/info.log, which has no default value
immediateFlush boolean Flush to the file as soon as a log is generated, by setting it to false to improve performance because of frequent Flush buffer;

sample:

<configuration>
  <! -- Use timestamp as filename -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile-${bySecond}.log</file>
    <append>true</append>
    <! -- set immediateFlush to false for much higher logging throughput -->
    <immediateFlush>true</immediateFlush>
    <! -- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
Copy the code

RollingFileAppender(Rolling output)

RollingFileAppender inherits from FileAppender and generates a rolling file according to certain policies. For example, in conjunction with TimeBasedRollingPolicy, a new file is generated when the file reaches a specified time. This will be explained in detail in later chapters.

configuration type describe
append boolean See a FileAppender configuration
encoder Encoder See a FileAppender configuration
file String See a FileAppender configuration
rollingPolicy RollingPolicy Log scroll policy: Configuring this option causes log files to scroll according to the specified policy
triggeringPolicy TriggeringPolicy Trigger rollingPolicy: usually used with a rollingPolicy to set the trigger conditions for rolling

sample:

<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/error.log</file>
    <! TimeBasedRollingPolicy -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <! -- Set log naming mode -->
        <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <! Keep log for up to 30 days -->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <! When the file exceeds 150MB, the scroll policy is triggered immediately to generate a new file.
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>
Copy the code

Log file Policy *Policy(Common)

TimeBasedRollingPolicy(Scroll by date strategy)

TimeBasedRollingPolicy is probably logBack’s most popular rollingpolicy. TimeBasedRollingPolicy is logBack’s most popular rollingpolicy. TimeBasedRollingPolicy is logBack’s most popular rollingpolicy

configuration type describe
fileNamePattern String The generated file is similar to errorfile.2018-10-09.log. After the date is added, the name of the file generated every day will not be repeated. This also supports time zone selection, such as %d{YYYY-MM-dd,UTC}
maxHistory int Log retention period. The historical log files that exceed this period will be deleted by LogBack asynchronously
totalSizeCap int The total size of the archive, with the maxHistory policy preferred.
cleanHistoryOnStart boolean The default value is false, which triggers the immediate deletion of the archive.

Gz or. Zip file names, for example, /wombat/foo.%d.gz

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <! -- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <! -- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
Copy the code

SizeAndTimeBasedRollingPolicy(Scroll policy by size and time)

This is probably the most common one, scrolling logs according to a specified time and file size policy. Without further ado, let’s look at the following example

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <! -- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <! -- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>
Copy the code

Note the “% I” conversion flags other than “% d”. Both % I and % d tokens are mandatory. Whenever the current log file reaches maxFileSize before the end of the current time period, it will be archived with the added index, starting at 0


FixedWindowRollingPolicy(Generating scrolling files with fixed algorithmic policies is not commonly used)

This strategy is not common, za not bb, property and other rolling strategy is the same, usually the file naming convention is this: tests. % i.l og, when arrive condition triggered rolling test1 generated file. The log, test2. Log, test3. The log…


SizeBasedTriggeringPolicy(Policies that trigger scrolling based on size)

The Settings in this TAB that trigger the scroll time, such as when the file size reaches a specified value, trigger the scroll

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
Copy the code

fileNamePatten(examples, scroll by year, month, day, day, hour, minute, second)

example describe
/wombat/foo.%d Scroll by day, format year – month – day, all generated in a folder
/wombat/%d{yyyy/MM}/foo.txt Scroll by month to generate the same file each month in a different month folder, for example, first: /wombat/2018/09/foo.txt, next: /wombat/2018/10/foo.txt
/wombat/foo.%d{yyyy-ww}.log It is generated once a week and starts to be generated on the first day of each week
/wombat/foo%d{yyyy-MM-dd_HH}.log It’s generated every hour
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log Every minute
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log Generated every minute for the specified time zone
/foo/%d{yyyy-MM,aux}/%d.log It is generated every day, divided by year and month, for example, /foo/2018-09/ contains a log of one month, and the log name is the date of each day

patternConfiguration (Log output formatting)

example

The following describes some common configuration rules.

<encoder>
    <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
Copy the code
  • %-4relative: Left-align the log output time with the width of 4.
  • %thread: Specifies the number of the thread that will output logs
  • %-5level: Displays five log levels and aligns them left.
  • %logger{35}: Outputs logsloggerThe name is usually the class name and is 35 in length.
  • %msg%n: Prints the information provided by the application and wraps it.

Note: all keywords must be marked with %, as above, – to mark them

patternform

The keyword describe
c{length}

lo{length}
Output the name of the class to which logger belongs, usually the full name of the class. The parameter is reserved for the logger name. The full name is not filled in by default.

%logger com.util.StringUtils com.util.StringUtils
%logger{0} com.util.StringUtils StringUtils
%logger{10} com.util.StringUtils c.u.StringUtils
C{length}

class{length}
Similar to the above usage, output the full name of the caller, poor performance, not recommended.
contextName

cn|
Output context name
d{pattern}

date{pattern}
The printing time of the output log is similar to the date formatting in Java

%d The 18:00:00 2019-02-12, 000
%date The 18:00:00 2019-02-12, 000
%date{ISO8601} The 18:00:00 2019-02-12, 000
%date{HH:mm:ss,SSSS} 18:00:00, 000
%date{yyyy-MM-dd HH:mm:ss,SSSS} The 18:00:00 2019-02-12, 000
caller{depth} Output log caller’s call stack depth information. The larger the value is, the more stack information is output

%caller{2} [main]-[INFO]: log test

Caller+0 at com.util.StringUtil.subString(StringUtil.java :22)

Caller+1 at com.util.Main.exec(Main.java :17)
L

line
Output the location of the log event, including the category name, the thread in which it occurred, and the number of lines in the code. If performance is not considered, it can be used
m

msg

message
Information provided by the application
M

method
The method name that outputs execution logs has poor performance and can be used if performance concerns are not considered
n Output a carriage return newline, “/r/n” on Windows, “/n” on Unix
p

le

level
The output log levels are DEBUG, INFO, WARN, ERROR, and FATAL
t

thread
The name of the thread that prints logs
replace(msg){r,t} MSG is the log content, and r is the regular expression. Replace the content matching R in MSG with T.

For example: % the replace (MSG) % {\ ‘s’, “”}
r

relative
Output The number of milliseconds elapsed between the start of the application and the output of the log information

Configuration:

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <! -- Date [thread] [class]-[log level] log content carriage return symbol -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n</pattern>
        </encoder>

    </appender>

    <! -- Output INFO and above logs -->
    <root level="INFO">
        <! Make custom appender work -->
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

Copy the code

Console output:

2018-10-09 14:27:55 [main] [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping]-[INFO] Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-10-09 14:27:55 [main] [org.springframework.jmx.export.annotation.AnnotationMBeanExporter]-[INFO] Registering beans for JMX exposure on startup 2018-10-09 14:27:55 [main] [org.apache.coyote.http11.Http11NioProtocol]-[INFO] Starting ProtocolHandler ["http-nio-6677"] 2018-10-09 14:27:55 [main] [org.apache.tomcat.util.net.NioSelectorPool]-[INFO] Using a  shared selector for servlet write/read 2018-10-09 14:27:55 [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer]-[INFO] Tomcat started on port(s): 6677 (http) with context path '' 2018-10-09 14:27:55 [main] [com.xj.plugins.Springboot2AnalyzeApplication]-[INFO] Started Springboot2AnalyzeApplication in 2.014 seconds (JVM running for 3.949)Copy the code

Log configuration color for console output

format describe
%black black
%red red
%green green
%yellow yellow
%blue blue
%magenta magenta
%cyan cyan
%white white
%gray gray
%highlight High light
%bold More vivid color color, enhance all the above colors, such as %boldRed,%boldBlack

Example:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <! -- Date [thread] [class]-[log level] log content carriage return symbol -->
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss,SSS}) [%cyan(%t)] [%yellow(%c)]-[%highlight(%p)] %m%n</pattern>         
        </encoder>
    </appender>

    <! -- Output INFO and above logs -->
    <root level="INFO">
        <! Make custom appender work -->
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
Copy the code

Console output after configuration


Log Oriented Output

In logback.xml, how do you need to output a particular log to a file using a filter, like this example

XML configures filters, for example, to output error logs to error.log

    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
           <encoder>
               <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%c]-[%p] %m%n</pattern>
           </encoder>

           <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
               <! -- rollover daily -->
               <fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
               <! -- Maximum file size: 30MB, 60 days, 20GB -->
               <maxFileSize>30MB</maxFileSize>
               <maxHistory>60</maxHistory>
               <totalSizeCap>20GB</totalSizeCap>
           </rollingPolicy>

           <! -- filter, only write error level log -->
           <filter class="ch.qos.logback.classic.filter.LevelFilter">
               <level>ERROR</level>
               <onMatch>ACCEPT</onMatch>
               <onMismatch>DENY</onMismatch>
           </filter>

       </appender>
Copy the code

You can override the Filter method if you need a special log that needs to be directed to output

public class MyLogFilter extends Filter<ILoggingEvent> {
       @Override

       public FilterReply decide(ILoggingEvent event) {
           
           if(event.getMessage() ! =null
                   && (event.getMessage().startsWith("test")
                   || event.getMessage().startsWith("demo"))) {
               return FilterReply.ACCEPT;
           } else {
               returnFilterReply.DENY; }}}Copy the code

Then add the filter to your appender

<! -- filter, write logs starting with test and demo -->
<filter class="xx.xxx.xxxx.MyLogFilter" />
Copy the code

Turns off a level of log output from a class

Add the following configuration to logback.xml

OFF: disables all functions. You can set a specific level, such as INFO, DEBUG…

<logger name="xx.xx.class" level="OFF" />
Copy the code

logback.xmlReading environment variables

Logback.xml can be read in two ways, from the system environment and from the Spring configuration file

The system environment variables are obtained by ${envName}

<! Read log output directory from system environment variable -->
<property name="LOG_HOME" value="${log.dir}"/>
Copy the code

How to read the Spring configuration file

<! ${} -->
<springProperty scope="context" name="LOG_HOME" source="logback.dir"/>
Copy the code

Default Settings

If the value of LOG_HOME is not taken in the environment variable, logs is used as the default, similar to the default set in Shell syntax

<file>${LOG_HOME:-logs}/test/test-info.log</file>
Copy the code

Full available configuration files

Three log files are generated in the following configuration: A new log file is generated every day. When the size of a log file reaches the specified size, a new log file is automatically compressed and generated for recording.

  • main.log(only recordsinfoLog output of levels and above)
  • warn.log(only recordswarnLevel of log output)
  • error.log(only recordserrorLevel of log output)

      
<configuration debug="false">
    <! -- Get the configuration from Spring, if not use the default value -->
    <springProperty scope="context" name="LOG_HOME" source="logging.path"/>
    <springProperty scope="context" name="LOG_LEVEL" source="logging.output.level"/>
    <springProperty scope="context" name="LOG_MAX_SIZE" source="logging.file.max-size"/>
    <springProperty scope="context" name="LOG_TOTAL_SIZE_CAP" source="logging.file.total-size-cap"/>
    <springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
    <! -- Output style -->
    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%logger{10}]-[%p] %m%n"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%cyan(%t)] [%yellow(%logger{10})]-[%highlight(%p)] %m%n</pattern>
        </encoder>
    </appender>

    <appender name="Main-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/main.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/main-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <appender name="Error-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/error-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="Warn-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/warn-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <! -- log filter -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <! -- Disable output at a certain level in a class. OFF Disable all output, INFO,DEBUG... <logger name="x.x.Constants"> <level value="OFF"/> </logger> -->

    <! -- log output level -->
    <root level="${LOG_LEVEL:-INFO}">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="Main-Log"/>
        <appender-ref ref="Warn-Log"/>
        <appender-ref ref="Error-Log"/>
    </root>

</configuration>
Copy the code