文档
https://logback.qos.ch/documentation.html
manual
https://logback.qos.ch/manual/index.html
introduction
https://logback.qos.ch/manual/introduction.html
architecture
https://logback.qos.ch/manual/architecture.html
logger & appender & layout word meaning
The Logger
class is part of the logback-classic module.
On the other hand, the Appender
and Layout
interfaces are part of logback-core.
As a general-purpose module, logback-core has no notion of loggers.
Logger
logger具有Named Hierarchy,参考https://logback.qos.ch/manual/architecture.html
logger还具有Effective Level Inheritance,参考https://logback.qos.ch/manual/architecture.html
Appender
https://logback.qos.ch/manual/architecture.html
Logback allows logging requests to print to multiple destinations. In logback speak, an output destination is called an appender. Currently, appenders exist for the console, files, remote socket servers, to MySQL, PostgreSQL, Oracle and other databases, JMS, and remote UNIX Syslog daemons.
More than one appender can be attached to a logger.
In other words, appenders are inherited additively from the logger hierarchy.
For example, if a console appender is added to the root logger, then all enabled logging requests will at least print on the console.
If in addition a file appender is added to a logger, say L, then enabled logging requests for L and L’s children will print on a file and on the console.
Appender Additivity
The output of a log statement of logger L will go to all the appenders in L and its ancestors. This is the meaning of the term “appender additivity”.
However, if an ancestor of logger L, say P, has the additivity flag set to false, then L’s output will be directed to all the appenders in L and its ancestors up to and including P but not the appenders in any of the ancestors of P.
Loggers have their additivity flag set to true by default.
The table below shows an example:
Logger Name | Attached Appenders | Additivity Flag | Output Targets | Comment |
---|---|---|---|---|
root | A1 | not applicable | A1 | Since the root logger stands at the top of the logger hierarchy, the additivity flag does not apply to it. |
x | A-x1, A-x2 | true | A1, A-x1, A-x2 | Appenders of “x” and of root. |
x.y | none | true | A1, A-x1, A-x2 | Appenders of “x” and of root. |
x.y.z | A-xyz1 | true | A1, A-x1, A-x2, A-xyz1 | Appenders of “x.y.z”, “x” and of root. |
security | A-sec | false | A-sec | No appender accumulation since the additivity flag is set to false . Only appender A-sec will be used. |
security.access | none | true | A-sec | Only appenders of “security” because the additivity flag in “security” is set to false . |
Layout
More often than not, users wish to customize not only the output destination but also the output format. This is accomplished by associating a layout with an appender.
The layout is responsible for formatting the logging request according to the user’s wishes, whereas an appender takes care of sending the formatted output to its destination.
The PatternLayout
, part of the standard logback distribution, lets the user specify the output format according to conversion patterns similar to the C language printf
function.
For example, the PatternLayout with the conversion pattern “%-4relative [%thread] %-5level %logger{32} - %msg%n” will output something akin to:
176 [main] DEBUG manual.architecture.HelloWorld2 - Hello world.
The first field is the number of milliseconds elapsed since the start of the program. The second field is the thread making the log request. The third field is the level of the log request. The fourth field is the name of the logger associated with the log request. The text after the ‘-’ is the message of the request.
configuration
https://logback.qos.ch/manual/configuration.html
basic config
<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>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
If everything goes well, you should see the following output on the console
17:44:58,578 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml]
17:44:58,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
17:44:58,671 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
17:44:58,687 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack
17:44:58,812 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root]
17:44:58.828 [main] INFO chapters.configuration.MyApp2 - Entering application.
17:44:58.828 [main] DEBUG chapters.configuration.Foo - Did it again!
17:44:58.828 [main] INFO chapters.configuration.MyApp2 - Exiting application.
reloading configuration file upon modification
<configuration scan="true" scanPeriod="30 seconds" >
...
</configuration>
Configuring loggers
A logger is configured using the <logger>
element. A <logger>
element takes exactly one mandatory name attribute, an optional level attribute, and an optional additivity attribute, admitting the values true or false. The value of the level attribute admitting one of the case-insensitive string values TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. The special case-insensitive value INHERITED, or its synonym NULL, will force the level of the logger to be inherited from higher up in the hierarchy. This comes in handy if you set the level of a logger and later decide that it should inherit its level.
The <logger>
element may contain zero or more <appender-ref>
elements; each appender thus referenced is added to the named logger. Note that unlike log4j, logback-classic does not close nor remove any previously referenced appenders when configuring a given logger.
Configuring the root logger
https://logback.qos.ch/manual/configuration.html#rootElement
The <root>
element configures the root logger. It supports a single attribute, namely the level attribute. It does not allow any other attributes because the additivity flag does not apply to the root logger. Moreover, since the root logger is already named as “ROOT”, it does not allow a name attribute either. The value of the level attribute can be one of the case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. Note that the level of the root logger cannot be set to INHERITED or NULL.
Similarly to the <logger>
element, the <root>
element may contain zero or more <appender-ref>
elements; each appender thus referenced is added to the root logger. Note that unlike log4j, logback-classic does not close nor remove any previously referenced appenders when configuring the root logger.
Suppose we are no longer interested in seeing any DEBUG messages from any component belonging to the “chapters.configuration” package. The following configuration file shows how to achieve that.
<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>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO"/>
<!-- Strictly speaking, the level attribute is not necessary since -->
<!-- the level of the root level is set to DEBUG by default. -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Note that the message of level DEBUG generated by the “chapters.configuration.Foo” logger has been suppressed
You can configure the levels of as many loggers as you wish. In the next configuration file, we set the level of the chapters.configuration logger to INFO but at the same time set the level of the chapters.configuration.Foo logger to DEBUG
.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO" />
<logger name="chapters.configuration.Foo" level="DEBUG" />
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Running MyApp3
with this configuration file will result in the following output on the console:
17:39:27.593 [main] INFO chapters.configuration.MyApp3 - Entering application.
17:39:27.593 [main] DEBUG chapters.configuration.Foo - Did it again!
17:39:27.593 [main] INFO chapters.configuration.MyApp3 - Exiting application.
Configuring Appenders
https://logback.qos.ch/manual/configuration.html#configuringAppenders
An appender is configured with the <appender>
element, which takes two mandatory attributes name and class.
The name attribute specifies the name of the appender whereas the class attribute specifies the fully qualified name of the appender class to instantiate.
The <appender>
element may contain zero or one <layout>
elements, zero or more <encoder>
elements and zero or more <filter>
elements.
Apart from these three common elements, <appender>
elements may contain any number of elements corresponding to JavaBean properties of the appender class.
The <layout>
element takes a mandatory class attribute specifying the fully qualified name of the layout class to instantiate. As with the <appender>
element, <layout>
may contain other elements corresponding to properties of the layout instance.
Since it’s such a common case, if the layout class is PatternLayout
, then the class attribute can be omitted as specified by default class mapping rules.
The <encoder>
element takes a mandatory class attribute specifying the fully qualified name of the encoder class to instantiate.
Since it’s such a common case, if the encoder class is PatternLayoutEncoder
, then the class attribute can be omitted as specified by default class mapping rules.
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>myApp.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
These configuration scripts define two appenders called FILE and STDOUT. The FILE appender logs to a file called myApp.log.
The encoder for this appender is a PatternLayoutEncoder
that outputs the date, level, thread name, logger name, file name and line number where the log request is located, the message and line separator character(s).
The second appender called STDOUT
outputs to the console. The encoder for this appender outputs only the message string followed by a line separator.
Appenders accumulate
https://logback.qos.ch/manual/configuration.html#cumulative
By default, appenders are cumulative: a logger will log to the appenders attached to itself (if any) as well as all the appenders attached to its ancestors. Thus, attaching the same appender to multiple loggers will cause logging output to be duplicated.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration">
<appender-ref ref="STDOUT" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Running MyApp3
with duplicate.xml will yield the following output:
14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application.
14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application.
14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again!
14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again!
14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application.
14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application.
Notice the duplicated output.
Variable substitution
https://logback.qos.ch/manual/configuration.html#variableSubstitution
As in many scripting languages, logback configuration files support definition and substitution of variables. Variables have a scope (see below). Moreover, variables can be defined within the configuration file itself, in an external file, in an external resource or even computed and defined on the fly.
Variable substitution can occur at any point in a configuration file where a value can be specified. The syntax of variable substitution is similar to that of Unix shells. The string between an opening *{aName}" will be replaced with the value held by the aName property.
As they often come in handy, the HOSTNAME and CONTEXT_NAME variables are automatically defined and have context scope. Given that in some environments it may take some time to compute the hostname, its value is computed lazily (only when needed). Moreover, HOSTNAME can be set from within the configuration directly.
Defining variables
Variables can be defined one at a time in the configuration file itself or loaded wholesale from an external properties file or an external resource. For historical reasons, the XML element for defining variables is <property>
although in logback 1.0.7 and later the element <variable>
can be used interchangeably.
The next example shows a variable declared at the beginning of the configuration file. It is then used further down the file to specify the location of the output file.
<configuration>
<variable name="USER_HOME" value="/home/sebastien" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
Scopes
A property can be defined for insertion in local scope, in context scope, or in system scope. Local scope is the default. Although it is possible to read variables from the OS environment, it is not possible to write into the OS environment.
LOCAL SCOPE A property with local scope exists from the point of its definition in a configuration file until the end of interpretation/execution of said configuration file. As a corollary, each time a configuration file is parsed and executed, variables in local scope are defined anew.
CONTEXT SCOPE A property with context scope is inserted into the context and lasts as long as the context or until it is cleared. Once defined, a property in context scope is part of the context. As such, it is available in all logging events, including those sent to remote hosts via serialization.
SYSTEM SCOPE A property with system scope is inserted into the JVM’s system properties and lasts as long as the JVM or until it is cleared.
<configuration>
<variable scope="context" name="nodeId" value="firstNode" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/opt/${nodeId}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
Appenders
https://logback.qos.ch/manual/appenders.html
several appenders
ConsoleAppender
<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>
FileAppender
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>testFile.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>
RollingFileAppender
There are two important subcomponents that interact with RollingFileAppender
.
The first RollingFileAppender
sub-component, namely RollingPolicy
, (see below) is responsible for undertaking the actions required for a rollover.
A second subcomponent of RollingFileAppender
, namely TriggeringPolicy
, (see below) will determine if and exactly when rollover occurs.
Thus, RollingPolicy
is responsible for the what and TriggeringPolicy
is responsible for the when.
To be of any use, a RollingFileAppender
must have both a RollingPolicy
and a TriggeringPolicy
set up. However, if its RollingPolicy
also implements the TriggeringPolicy
interface, then only the former needs to be specified explicitly.
TimeBasedRollingPolicy
’s
TimeBasedRollingPolicy
is possibly the most popular rolling policy. It defines a rollover policy based on time, for example by day or by month. TimeBasedRollingPolicy
assumes the responsibility for rollover as well as for the triggering of said rollover. Indeed, TimeBasedTriggeringPolicy
implements both RollingPolicy
and TriggeringPolicy
interfaces.
TimeBasedRollingPolicy
’s configuration takes one mandatory fileNamePattern property and several optional properties.
Property Name | Type | Description |
---|---|---|
fileNamePattern | String |
The mandatory fileNamePattern property defines the name of the rolled-over (archived) log files. Its value should consist of the name of the file, plus a suitably placed %d conversion specifier. The %d conversion specifier may contain a date-and-time pattern as specified by the java.text.SimpleDateFormat class. If the date-and-time pattern is omitted, then the default pattern yyyy-MM-dd is assumed. **The rollover period is inferred from the value of fileNamePattern.**Note that the file property in RollingFileAppender (the parent of TimeBasedRollingPolicy ) can be either set to a value or omitted (=null). By setting the file property of the containing FileAppender , you can decouple the location of the active log file and the location of the archived log files. The current logs will always be targeted at the file specified by the file property. It follows that the name of the currently active log file will not change over time.However, if you choose to omit the file property, then the active file will be computed anew for each period based on the value of fileNamePattern. In this configuration no roll over occur, unless file compression is specified. The examples below should clarify this point.The date-and-time pattern, as found within the accolades of %d{} follow java.text.SimpleDateFormat conventions. The forward slash ‘/’ or backward slash ‘’ characters anywhere within the fileNamePattern property or within the date-and-time pattern will be interpreted as directory separators.Multiple %d specifiersIt is possible to specify multiple %d specifiers but only one of which can be primary, i.e. used to infer the rollover period. All other tokens must be marked as auxiliary by passing the ‘aux’ parameter (see examples below).Multiple %d specifiers allow you to organize archive files in a folder structure different than that of the roll-over period. For example, the file name pattern shown below organizes log folders by year and month but roll-over log files every day at midnight./var/log/**%d{yyyy/MM, aux}**/myapplication.**%d{yyyy-MM-dd}**.log TimeZoneUnder certain circumstances, you might wish to roll-over log files according to a clock in a timezone different than that of the host. It is possible to pass a timezone argument following the date-and-time pattern within the %d conversion specifier. For example:aFolder/test.**%d**{yyyy-MM-dd-HH, **UTC**}.log If the specified timezone identifier is unknown or misspelled, the GMT timezone is assumed as dictated by the TimeZone.getTimeZone(String) method specification. |
maxHistory | int | The optional maxHistory property controls the maximum number of archive files to keep, asynchronously deleting older files. For example, if you specify monthly rollover, and set maxHistory to 6, then 6 months worth of archives files will be kept with files older than 6 months deleted. Note as old archived log files are removed, any folders which were created for the purpose of log file archiving will be removed as appropriate.Setting maxHistory to zero disables archive removal. By default, maxHistory is set to zero, i.e. by default there is no archive removal. |
totalSizeCap | int | The optional totalSizeCap property controls the total size of all archive files. Oldest archives are deleted asynchronously when the total size cap is exceeded. The totalSizeCap property requires maxHistory property to be set as well. Moreover, the “max history” restriction is always applied first and the “total size cap” restriction applied second.The totalSizeCap property can be specified in units of bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5000000, 5000KB, 5MB and 2GB are all valid values, with the first three being equivalent. A numerical value with no suffix is taken to be in units of bytes.By default, totalSizeCap is set to zero, meaning that there is no total size cap. |
cleanHistoryOnStart | boolean | If set to true, archive removal will be executed on appender start up. By default this property is set to false.Archive removal is normally performed during roll over. However, some applications may not live long enough for roll over to be triggered. It follows that for such short-lived applications archive removal may never get a chance to execute. By setting cleanHistoryOnStart to true, archive removal is performed at appender start up. |
<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>
SizeAndTimeBasedRollingPolicy
Sometimes you may wish to archive files essentially by date but at the same time limit the size of each log file, in particular if post-processing tools impose size limits on the log files. In order to address this requirement, logback ships with SizeAndTimeBasedRollingPolicy
.
<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>
Note the “%i” conversion token in addition to “%d”. Both the %i and %d tokens are mandatory. Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.
Encoders
https://logback.qos.ch/manual/encoders.html
What is an encoder
Encoders are responsible for transforming an event into a byte array as well as writing out that byte array into an OutputStream
. Encoders were introduced in logback version 0.9.19. In previous versions, most appenders relied on a layout to transform an event into a string and write it out using a java.io.Writer
. In previous versions of logback, users would nest a PatternLayout
within FileAppender
. Since logback 0.9.19, FileAppender
and subclasses expect an encoder and no longer take a layout.
Why the breaking change?
Layouts, as discussed in detail in the next chapter, are only able to transform an event into a String. Moreover, given that a layout has no control over when events get written out, layouts cannot aggregate events into batches. Contrast this with encoders which not only have total control over the format of the bytes written out, but also control when (and if) those bytes get written out.
At the present time, PatternLayoutEncoder
is the only really useful encoder. It merely wraps a PatternLayout
which does most of the work. Thus, it may seem that encoders do not bring much to the table except needless complexity. However, we hope that with the advent of new and powerful encoders this impression will change.
LayoutWrappingEncoder
Until logback version 0.9.19, many appenders relied on the Layout instances to control the format of log output. As there exists substantial amount of code based on the layout interface, we needed a way for encoders to interoperate with layouts. LayoutWrappingEncoder bridges the gap between encoders and layouts. It implements the encoder interface and wraps a layout to which it delegates the work of transforming an event into string.
package ch.qos.logback.core.encoder;
public class LayoutWrappingEncoder<E> extends EncoderBase<E> {
protected Layout<E> layout;
private Charset charset;
// encode a given event as a byte[]
public byte[] encode(E event) {
String txt = layout.doLayout(event);
return convertToBytes(txt);
}
private byte[] convertToBytes(String s) {
if (charset == null) {
return s.getBytes();
} else {
return s.getBytes(charset);
}
}
}
The doEncode
() method starts by having the wrapped layout convert the incoming event into string. The resulting text string is converted to bytes according to the charset encoding chosen by the user.
PatternLayoutEncoder
Given that PatternLayout
is the most commonly used layout, logback caters for this common use-case with PatternLayoutEncoder
, an extension of LayoutWrappingEncoder
restricted to wrapping instances of PatternLayout
.
layouts
https://logback.qos.ch/manual/layouts.html
PatternLayout
Logback classic ships with a flexible layout called PatternLayout
. As all layouts, PatternLayout
takes a logging event and returns a String
. However, this String
can be customized by tweaking PatternLayout
’s conversion pattern.
The conversion pattern of PatternLayout
is closely related to the conversion pattern of the printf()
function in the C programming language. A conversion pattern is composed of literal text and format control expressions called conversion specifiers. You are free to insert any literal text within the conversion pattern.
Each conversion specifier starts with a percent sign ‘%’ and is followed by optional format modifiers, a conversion word and optional parameters between braces. The conversion word controls the data field to convert, e.g. logger name, level, date or thread name. The format modifiers control field width, padding, and left or right justification.
Conversion Word | Effect |
---|---|
c{length} lo{length} logger{length} | Outputs the name of the logger at the origin of the logging event.This conversion word takes an integer as its first and only option. The converter’s abbreviation algorithm will shorten the logger name, usually without significant loss of meaning. Setting the value of length option to zero constitutes an exception. It will cause the conversion word to return the sub-string right to the rightmost dot character in the logger name. The next table provides examples of the abbreviation algorithm in action.Conversion specifierLogger nameResult%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar%logger{0}mainPackage.sub.sample.BarBar%logger{5}mainPackage.sub.sample.Barm.s.s.Bar%logger{10}mainPackage.sub.sample.Barm.s.s.Bar%logger{15}mainPackage.sub.sample.Barm.s.sample.Bar%logger{16}mainPackage.sub.sample.Barm.sub.sample.Bar%logger{26}mainPackage.sub.sample.BarmainPackage.sub.sample.BarPlease note that the rightmost segment in a logger name is never abbreviated, even if its length is longer than the length option. Other segments may be shortened to at most a single character but are never removed. |
C{length} class{length} | Outputs the fully-qualified class name of the caller issuing the logging request.Just like the %logger conversion word above, this conversion takes an integer as an option to shorten the class name. Zero carries special meaning and will cause the simple class name to be printed without the package name prefix. By default the class name is printed in full.Generating the caller class information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue. |
contextName cn | Outputs the name of the logger context to which the logger at the origin of the event was attached to. |
d{pattern} date{pattern} d{pattern, timezone} date{pattern, timezone} | Used to output the date of the logging event. The date conversion word admits a pattern string as a parameter. The pattern syntax is compatible with the format accepted by java.text.SimpleDateFormat (in logback 1.2.x) and java.time.format.DateTimeFormatter (in logback 1.3.x).You can specify the string “ISO8601” for the ISO8601 date format. Note that the %date conversion word defaults to the ISO 8601 date format in the absence of a pattern parameter.Here are some sample parameter values. They assume that the actual date is Friday 20th of October, 2006 and that the author has returned to working on this document just after lunch.Conversion PatternResult%d2006-10-20 14:06:49,812%date2006-10-20 14:06:49,812%date{ISO8601}2006-10-20 14:06:49,812%date{HH:mm:ss.SSS}14:06:49.812%date{dd MMM yyyy;HH:mm:ss.SSS}20 oct. 2006;14:06:49.812The second parameter specifies a timezone. For example, the '%date{HH:mm:ss.SSS, Australia/Perth} would print the time in the time zone of Perth, Australia, the world’s most isolated city. Note that in the absence of the timezone parameter, the default timezone of the host Java platform is used. If the specified timezone identifier is unknown or misspelled, the GMT timezone is assumed as dictated by the TimeZone.getTimeZone(String) method specification.If the option includes special characters such as a braces, spaces or commas, you can enclose it between single or double quotes.COMMON ERROR Given that the comma ‘,’ character is interpreted as the parameter separator, the pattern HH:mm:ss,SSS will be interpreted as the pattern HM:mm:ss and the timezone SSS . If you wish to include a comma in your date pattern, then simply enclose the pattern between single or double quotes. For example, %date{"HH:mm:ss,SSS"} or %date{'HH:mm:ss,SSS’}. |
micros / ms | SINCE 1.3 Outputs the microseconds of the timestamp included in the event.For performance reasons, the microseconds have to be specified separately and in addition to %date. |
F / file | Outputs the file name of the Java source file where the logging request was issued.Generating the file information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue. |
kvp{NONE,SINGLE,DOUBLE} | Outputs the key value pairs contained in the logging event. By default, the value part will be surrounded by double quotes. You can override the default by specifying NONE or SINGLE, for no quote character or the single quote character ’ respectively.The value key pairs {k1, v1} and {k2, v2} contained in the event will be output as follows:NONEv1=k1 v2=k2DOUBLEv1=“k1” v2="k2"SINGLEv1=‘k1’ v1='k1’defaultsame as if DOUBLE were specified |
L / line | Outputs the line number from where the logging request was issued.Generating the line number information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue. |
m / msg / message | Outputs the application-supplied message associated with the logging event. |
M / method | Outputs the method name where the logging request was issued.Generating the method name is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue. |
n | Outputs the platform dependent line separator character or characters.This conversion word offers practically the same performance as using non-portable line separator strings such as “\n”, or “\r\n”. Thus, it is the preferred way of specifying a line separator. |
p / le / level | Outputs the level of the logging event. |
r / relative | Outputs the number of milliseconds elapsed since the start of the application until the creation of the logging event. |
t / thread | Outputs the name of the thread that generated the logging event. |
X{key:-defaultVal} mdc{key:-defaultVal} | Outputs the MDC (mapped diagnostic context) associated with the thread that generated the logging event.If the mdc conversion word is followed by a key between braces, as in %mdc{userid}, then the MDC value corresponding to the key ‘userid’ will be output. If the value is null, then the default value specified after the :- operator is output. If no default value is specified than the empty string is output.If no key is given, then the entire content of the MDC will be output in the format “key1=val1, key2=val2”.See the chapter on MDC for more details on the subject. |
filters
https://logback.qos.ch/manual/filters.html
Logback-classic offers two types of filters, regular filters and turbo filters.
Regular filters
Regular logback-classic filters extend the Filter
abstract class which essentially consists of a single decide()
method taking an ILoggingEvent
instance as its parameter.
Filters are organized as an ordered list and are based on ternary logic. The decide(ILoggingEvent event)
method of each filter is called in sequence. This method returns one of the FilterReply
enumeration values, i.e. one of DENY
, NEUTRAL
or ACCEPT
. If the value returned by decide
() is DENY
, then the log event is dropped immediately without consulting the remaining filters. If the value returned is NEUTRAL
, then the next filter in the list is consulted. If there are no further filters to consult, then the logging event is processed normally. If the returned value is ACCEPT
, then the logging event is processed immediately skipping the invocation of the remaining filters.
In logback-classic, filters can be added to Appender
instances. By adding one or more filters to an appender, you can filter events by arbitrary criteria, such as the contents of the log message, the contents of the MDC, the time of day or any other part of the logging event.
LevelFilter
LevelFilter
filters events based on exact level matching. If the event’s level is equal to the configured level, the filter accepts or denies the event, depending on the configuration of the onMatch and onMismatch properties. Here is a sample configuration file.
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
ThresholdFilter
The ThresholdFilter
filters events below the specified threshold. For events of level equal or above the threshold, ThresholdFilter
will respond NEUTRAL when its decide
() method is invoked. However, events with a level below the threshold will be denied. Here is a sample configuration file.
<configuration>
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
与springBoot整合
https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/boot-features-logging.html
The <springProperty>
tag lets you expose properties from the Spring Environment
for use within Logback. Doing so can be useful if you want to access values from your application.properties
file in your Logback configuration. The tag works in a similar way to Logback’s standard <property>
tag. However, rather than specifying a direct value
, you specify the source
of the property (from the Environment
). If you need to store the property somewhere other than in local
scope, you can use the scope
attribute. If you need a fallback value (in case the property is not set in the Environment
), you can use the defaultValue
attribute. The following example shows how to expose properties for use within Logback:
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
![]() |
---|
The source must be specified in kebab case (such as my.property-name ). However, properties can be added to the Environment by using the relaxed rules. |
工作中使用过的
logback-spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 请不要修改该文件!!!!!! -->
<configuration debug="false" scan="true" scanPeriod="20 seconds">
<springProperty name="moduleid" scope="context" source="properties.application.group"/>
<springProperty name="brand" scope="context" source="properties.application.brand"/>
<springProperty name="env" scope="context" source="properties.application.zone"/>
<conversionRule conversionWord="txlog" converterClass="com.hoperun.util.TxlogConverter"/>
<!-- 文件输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [${moduleid:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}] [%thread] %-5level %logger{40} %X{txlog} - %msg%n"/>
<property name="monitor.log.pattern" value="{"timestamp": "%d{HH:mm:ss.SSS}", "trace":"%X{X-B3-TraceId:-}","span":"%X{X-B3-SpanId:-}","thread": "%thread", "level": "%-5level", "msg": %msg}%n"/>
<!-- 每天产生一个文件 -->
<appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="logfile">
<!-- 文件路径 -->
<file>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.yum.ec3.base.logback.ThrowableEnhancedPatternLayout">
<pattern>${log.pattern}</pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="error-log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}.%d{yyyy-MM-dd}-error.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.yum.ec3.base.logback.ThrowableEnhancedPatternLayout">
<pattern>${log.pattern}</pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="monitor">
<!-- 文件路径 -->
<file>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}-monitor.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>/opt/log/${brand}/${moduleid}-${env}-${HOSTNAME}-monitor.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${monitor.log.pattern}</pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender class="ch.qos.logback.core.ConsoleAppender" name="console">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${log.pattern}</pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>
<logger level="WARN" name="com.netflix.discovery.InstanceRegionChecker"/>
<logger level="WARN" name="org.springframework"/>
<logger level="WARN" name="org.eclipse"/>
<logger level="WARN" name="org.apache"/>
<logger level="WARN" name="com.netflix"/>
<logger level="WARN" name="springfox.documentation"/>
<logger level="WARN" name="com.zaxxer.hikari.pool" />
<logger level="WARN" name="com.microsoft.sqlserver.jdbc" />
<logger level="INFO" name="monitor">
<appender-ref ref="monitor"/>
</logger>
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="logfile"/>
<appender-ref ref="error-log" />
</root>
</configuration>