3

前言

主要涉及logback中的一个重要组件——Appender——输出器。

正文

Appender的简单介绍——输出器

chapter 1

An Appender is a class that can be seen as an output destination. Appenders exist for many different destinations including the console, files, Syslog, TCP Sockets, JMS and many more. Users can also easily create their own Appenders as appropriate for their specific situation.

介绍了类Appender,从这段文字来看,不妨将Appender翻译理解为输出器。类Appender可以为控制台,文件等多种输出目标服务,用户也可以自定义自己的Appender以适配特定的场景。
具体如何配置这里没有讲,自然是期待往后看会有了。

再讲输出器:Appender类。

chapter 2:

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.

尽管是第二章的内容,但是和前面几乎一模一样。

What is an Appender

chapter 4
Logback 将输出日志记录的任务交给名为 appender 的组件来完成。 Appender 组件在代码级别上是接口ch.qos.logback.core.Appender的实现类。这个接口中最重要,与完成任务最相关的的方法为void doAppend(E event);

Logback delegates the task of writing a logging event to components called appenders. Appenders must implement the ch.qos.logback.core.Appenderinterface.

package ch.qos.logback.core;
  
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.LifeCycle;
  
/*
The salient methods of this interface are summarized below:
*/
public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {

  public String getName();
  public void setName(String name);
  void doAppend(E event);
  
}

A notable method is the doAppend() method taking an object instance of type E as its only parameter. The actual type of E will vary depending on the logback module. Within the logback-classic module E would be of type ILoggingEvent and within the logback-access module it would be of type AccessEvent. The doAppend() method is perhaps the most important in the logback framework. It is responsible for outputting the logging events in a suitable format to the appropriate output device.

一个 Appender 组件能使用多个 Filter 组件。

The Appender interface extends the FilterAttachable interface. It follows that one or more filters can be attached to an appender instance. Filters are discussed in detail in a subsequent chapter.

Appender 组件是负责输出日志记录的最后一环的组件,但格式化日志记录的任务交由 Layout 或/和 Encoder 组件来完成。一个 Layout / Encoder 组件仅能被绑定到一个 Appender 组件上。有些 Appender 组件有内置的格式化日志记录的工具,所以它们可以不需要这两个组件。

Appenders are ultimately responsible for outputting logging events. However, they may delegate the actual formatting of the event to a Layout or to an Encoder object. Each layout/encoder is associated with one and only one appender, referred to as the owning appender. Some appenders have a built-in or fixed event format. Consequently, they do not require nor have a layout/encoder. For example, the SocketAppender simply serializes logging events before transmitting them over the wire.

输出器:指定我要为哪些记录器工作

chapter 2

More than one appender can be attached to a logger.

The addAppender(ch.qos.logback.core.Appender#addAppender) adds an appender to a given logger. Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy. 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. It is possible to override this default behavior so that appender accumulation is no longer additive by setting the additivity flag of a logger to false.

一个记录器可以拥有多个输出器为自己工作。

一个输出器可以调用addAppender方法为自己增设一个为之工作的输出器对象。

可以看到这里这个方法是ch.qos.logback.core.Appender#addAppender类的,这是logback的一个实现类,而不是slf4j规范中的内容。因此如果真的在代码中使用,会加剧耦合。若有实践经验或继续阅读到后面xml文档配置,则会明白,为记录器加输出器是通过xml文件中输出器元素标签<logger>...</logger>中加<appender-ref ref="appendername"/>来实现的。之所以能做到解耦,是因为程序硬写的代码都是slf4j规范中的内容。当发现引入了logback库后启动它,它又发现配置文件,根据配置文件生成实现类,这些实现类都是slf4j规范的结构或抽象类的实现。然后它在此基础上调用addAppender方法。如果不用logback了,把导入的库换掉,配置文件也换掉,引入另一个库。那么实现类就由另一个库来定义和实现,也用不到上面的addAppender方法。这就解耦了。

另外,最后这句话:“It is possible to override this default behavior so that appender accumulation is no longer additive by setting the additivity flag of a logger to false.”,我也不知道该怎么翻译,什么意思。

appender元素必需属性

appender组件的结构

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.

<appender>元素标签必需(mandatory)的两个属性为name和class。即要用appender标签,<appender>白哦前至少形如<appender class="..." name="...">...</appender>

chapter 4

Appenders are named entities. This ensures that they can be referenced by name, a quality confirmed to be instrumental in configuration scripts.

Appender 是用名字指定的实体。尽管这里没说,但体现在配置文件中的<appdener name="" class="...">name属性上。而class指定到底使用Appender接口的哪个实现类

appender标签内部元素(标签)

chapter 3

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. Seamlessly supporting any property of a given logback component is one of the major strengths of Joran as discussed in a later chapter.

appender的appender标签内部元素(标签)有layout,encoder,filter以及对应于appender自身的JavaBean属性的配置标签。

这个所谓的JavaBean属性的配置标签,我推测和Spring的xml配置应该差不多。比如一个<bean></bean>元素标签,内部可以通过<property name="..."></property>这样来指定这个bean的内部成员变量。

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.

<layout></layout>元素有一个必需的class属性 ==> layout元素的标签至少为<layout class="fully qualified name of the layout class"></layout>

<layout></layout>元素和<appender></appender>元素一样可以配置javabean属性。

不过因为这个组件用的实在是太普遍了,所以class属性省略也行,省略的话会自动根据default class mapping中的规则指定。

default class mapping中的规则是这样弄的:首先根据所在的appender元素标签的class属性,从'parent class'类中选出对应的,然后自己是'layout',就从剩下的里面选出property namelayout的,再检索表格,此时就只有唯一剩下的了,从而选定完毕。

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.

和上一段对<layout>元素标签讲明的内容没有什么区别。

encoderlayout并不具备提出到appender元素标签外以复用的设计

chapter 3

Note that each appender has its own encoder. Encoders are usually not designed to be shared by multiple appenders. The same is true for layouts. As such, logback configuration files do not provide any syntactical means for sharing encoders or layouts.

Appender 组件的基础实现

chapter 4

The ch.qos.logback.core.AppenderBase class is an abstract class implementing the Appender interface. It provides basic functionality shared by all appenders, such as methods for getting or setting their name, their activation status, their layout and their filters. It is the super-class of all appenders shipped with logback. Although an abstract class,AppenderBase actually implements the doAppend() method in the Append interface.

This implementation of the doAppend() method is synchronized. It follows that logging to the same appender from different threads is safe.

Since such synchronization is not always appropriate, logback ships with ch.qos.logback.core.UnsynchronizedAppenderBase which is very similar to the AppenderBase class.

logback提供的Appender接口的实现类

OutputStreamAppender

OutputStreamAppender appends events to a java.io.OutputStream. This class provides basic services that other appenders build upon. Users do not usually instantiate OutputStreamAppender objects directly, since in general the java.io.OutputStream type cannot be conveniently mapped to a string, as there is no way to specify the target OutputStream object in a configuration script.

The OutputStreamAppender is the super-class of three other appenders, namely ConsoleAppender, FileAppender which in turn is the super class of RollingFileAppender. The next figure illustrates the class diagram for OutputStreamAppender and its subclasses.

class diagram for codeOutputStreamAppender/code

OutputStreamAppenderjava.io.OutputStream的实现类为目标,但由于无法在logback.xml这类配置文件中直接指定一个具体实例而一般不被使用。它是经常被使用的ConsoleAppender, FileAppender的父类。
Filter类和OutputStreamAppender为聚合关系,可以如此理解这个关系:

聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义;例如一个部门由多个员工组成;

与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在;例如, 部门撤销了,人员不会消失,他们依然存在;

Encoder类和OutputStreamAppender为组合关系,可以如此理解这个关系:

与聚合关系一样,组合关系同样表示整体由部分构成的语义;比如公司由多个部门组成;

但组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了;例如, 公司不存在了,部门也将不存在了;

因此可以说,每个Encoder的类的实例都至少必须具体绑定到一个OutputStreamAppender类的实例上。

However, this does not mean that OutputStreamAppender lacks configurable properties. These properties are described next.

Property Name Type Description
encoder Encoder Determines the manner in which an event is written to the underlying OutputStreamAppender. Encoders are described in a dedicated chapter.
immediateFlush boolean The default value for immediateFlush is 'true'. Immediate flushing of the output stream ensures that logging events are immediately written out and will not be lost in case your application exits without properly closing appenders. On the other hand, setting this property to 'false' is likely to quadruple (your mileage may vary) logging throughput. Again, if immediateFlush is set to 'false' and if appenders are not closed properly when your application exits, then logging events not yet written to disk may be lost.

immediateFlush属性决定记录是否先输出到缓存,在程序结束或者其它条件满足时再输出到指定目标。immediateFlush默认值为false,一般也不开启。

immediateFlush属性虽然不会在之后的子类的属性列表中显式地列出,但是仍然是子类的属性,故可以通过形如

<appender name="STDOUT" class="ch.qos.logback.core.FileAppender">
    ...
    <immediateFlush>false</immediateFlush>
</appender>

这样的代码重新赋值。

ConsoleAppender

The ConsoleAppender, as the name indicates, appends on the console, or more precisely on System.out or System.err, the former being the default target. ConsoleAppender formats events with the help of an encoder specified by the user. Encoders will be discussed in a subsequent chapter. Both System.out and System.err are of type java.io.PrintStream. Consequently, they are wrapped inside an OutputStreamWriter which buffers I/O operations.

Property Name Type Description
encoder Encoder See OutputStreamAppender properties.
target String One of the String values System.out or System.err. The default target is System.out.
withJansi boolean By the default withJansi property is set to false. Setting withJansi to true activates the Jansi library which provides support for ANSI color codes on Windows machines. On a Windows host, if this property is set to true, then you should put "org.fusesource.jansi:jansi:1.17" on the class path. Note that Unix-based operating systems such as Linux and Mac OS X support ANSI color codes by default.Under the Eclipse IDE, you might want to try the ANSI in Eclipse Console plugin.

Here is a sample configuration that uses 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>

这里这种把encoder元素写在<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">元素内部,对应于ConsoleAppender类有encoder属性的写法,就是之前说的javabean的支持。也正因此,在appender元素中添加一个<target>System.out</target>也是可行的,改成<target>System.err</target>也同样可行,但是弄成其它的就会导致错误。

FileAppender

The FileAppender, a subclass of OutputStreamAppender, appends log events into a file. The target file is specified by the File option. If the file already exists, it is either appended to, or truncated depending on the value of the append property.

Property Name Type Description
append boolean If true, events are appended at the end of an existing file. Otherwise, if append is false, any existing file is truncated. The append option is set to true by default.
encoder Encoder See OutputStreamAppender properties.
file String The name of the file to write to. If the file does not exist, it is created. On the MS Windows platform users frequently forget to escape back slashes. For example, the value c:temptest.log is not likely to be interpreted properly as 't' is an escape sequence interpreted as a single tab character (u0009). Correct values can be specified as c:/temp/test.log or alternatively as c:\temp\test.log. The File option has no default value.If the parent directory of the file does not exist, FileAppender will automatically create it, including any necessary but nonexistent parent directories.

输出记录到文件的输出器,输出的文件的路径由file属性决定。如果文件已经存在,是追加还是删光重写由appender属性决定。在使用\转义符作为路径中的分隔符的Windows系统中使用时,要注意转义转义符\,否则肯定会出错。同时指定路径上的任何文件夹以及文件本身若不存在,就地创建而不报错。如果使用相对路径,则相对的是项目的根目录,即包含src文件夹的文件夹。

prudent属性,默认值为false。它用于指示该输出器是否开启审慎模式,以确保当同一个文件被多个文件输出器输出时的并发安全。当审慎模式开启时,append属性将会被自动置为true。审慎模式虽然确保了并发安全,但因为使用了文件锁而可能会导致死锁问题,性能问题等。我们一般不使用审慎模式

RollingFileAppender

RollingFileAppender extends FileAppender with the capability to rollover log files. For example, RollingFileAppender can log to a file named log.txt file and, once a certain condition is met, change its logging target to another file.

这个是我们最常用的输出器之一,一般用它来实现日志文件达到多少大小了就重开一个新的记录,并且检查日志占用的空间。如果已经达到最大值,则删除最旧的日志文件。

There are two important sub-components 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 sub-component 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 RollingPolicyalso implements the TriggeringPolicy interface, then only the former needs to be specified explicitly.

Here are the available properties for RollingFileAppender:

Property Name Type Description
file String See FileAppender properties.
append boolean See FileAppender properties.
encoder Encoder See OutputStreamAppender properties.
rollingPolicy RollingPolicy This option is the component that will dictate RollingFileAppender's behavior when rollover occurs. See more information below.Overview of rolling policies
triggeringPolicy TriggeringPolicy This option is the component that will tell RollingFileAppender when to activate the rollover procedure. See more information below.Overview of triggering policies
prudent boolean TriggeringPolicy implementa TriggeringPolicy implementaFixedWindowRollingPolicy is not supported in prudent mode.RollingFileAppender supports the prudent mode in conjunction with TimeBasedRollingPolicy albeit with two restrictions.In prudent mode, file compression is not supported nor allowed. (We can't have one JVM writing to a file while another JVM is compressing it.)The file property of FileAppender cannot be set and must be left blank. Indeed, most operating systems do not allow renaming of a file while another process has it opened.See also properties for FileAppender.

审慎模式仍然一般不使用。

Overview of rolling policies
RollingPolicy is responsible for the rollover procedure which involves file moving and renaming.

The rollover method accomplishes the work involved in archiving the current log file. The getActiveFileName() method is called to compute the file name of the current log file (where live logs are written to). As indicated by getCompressionModemethod a RollingPolicy is also responsible for determining the compression mode. Lastly, a RollingPolicy is given a reference to its parent via the setParent method.

RollingPolicy是一个接口。其主要管理 file moving and renaming 。但什么是 file moving and renaming ?这一点结合TimeBasedRollingPolicy中的fileNamePattern属性可用的同时,file属性也可用更好解释。

The RollingPolicy interface is presented below:

package ch.qos.logback.core.rolling;  

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;

public interface RollingPolicy extends LifeCycle {

  public void rollover() throws RolloverFailure;
  public String getActiveFileName();
  public CompressionMode getCompressionMode();
  public void setParent(FileAppender appender);
}

The rollover method accomplishes the work involved in archiving the current log file. The getActiveFileName() method is called to compute the file name of the current log file (where live logs are written to). As indicated by getCompressionModemethod a RollingPolicy is also responsible for determining the compression mode. Lastly, a RollingPolicy is given a reference to its parent via the setParent method.

这里setParent,翻译过来是”设置父级“,感觉莫名其妙,你哪里来的父级(类)。其实看它接收的对象,是接收一个FileAppender,也就是说绑定到对应的输出器上。

TimeBasedRollingPolicy
TimeBasedRollingPolicy assumes the responsibility for rollover as well as for the triggering of said rollover. Indeed, TimeBasedTriggeringPolicy implements both RollingPolicy and TriggeringPolicy interfaces.

the responsibility for rollover 就是 RollingPolicy接口的责任,for the triggering of said rollover 就是TriggeringPolicy的责任了。

TimeBasedRollingPolicyfileNamePattern属性

Property Name Type Description
fileNamePattern String 第一,该属性是必须的。第二,以/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log为例,一般的fileNamePattern由普通的字符串和路径分割符(log,/),以及一个或多个%d{yyyy/MM}这样的用来代表时间日期的占位符组成。其中yyyy/MM部分遵照java.text.SimpleDateFormat类中的标准。第三,根据代表时间日期的占位符,logback能够推算出一个日志记录文件的时间间隔,比如%d{yyyy/MM}就说明每个月的记录肯定是存在不同的文件(路径)上了。这一作用与之后的maxHistory属性差不多。第四,既然说了可以有多个,那么多个的时候以谁为主进行推断呢?以没有带,aux的那个来推断。第五,可以使用形如,aux那样来写时区:%d{yyyy-MM-dd-HH, UTC}。第六,无视系统差别的,\/均会被处理为文件路径分隔符。
第七,可以和RollingFileAppender的父FileAppender中的属性File连用,使得当前在写的日志是输出到file属性指定的文件中的,只有当前这个文件写完了,开始写下一个的时候才会把当前日志文件按照fileNamePattern的要求保存下来。因此中途退出的话,保存的文件的名字应当是file属性指定的。

之后文档又给了几个例子

注意这里第七点, file moving and renaming 便从中而来。输出记录时,总是按照file属性的值生成文件并向其中写入记录。但写着写着就会触发限制条件,引起 rollover。此时文件将会被按照fileNamePattern的要求进行重命名,甚至路径不一样还会发生移动。然后新的记录写入新的,仍然是file属性指定的文件中。

fileNamePattern Rollover schedule Example
/wombat/foo.%d Daily rollover (at midnight). Due to the omission of the optional time and date pattern for the %d token specifier, the default pattern of yyyy-MM-dd is assumed, which corresponds to daily rollover. file property not set: During November 23rd, 2006, logging output will go to the file /wombat/foo.2006-11-23. At midnight and for the rest of the 24th, logging output will be directed to/wombat/foo.2006-11-24.file property set to /wombat/foo.txt: During November 23rd, 2006, logging output will go to the file /wombat/foo.txt. At midnight, foo.txt will be renamed as /wombat/foo.2006-11-23. A new /wombat/foo.txt file will be created and for the rest of November 24th logging output will be directed to foo.txt.
/wombat/%d{yyyy/MM}/foo.txt Rollover at the beginning of each month. file property not set: During the month of October 2006, logging output will go to /wombat/2006/10/foo.txt. After midnight of October 31st and for the rest of November, logging output will be directed to /wombat/2006/11/foo.txt.file property set to /wombat/foo.txt: The active log file will always be /wombat/foo.txt. During the month of October 2006, logging output will go to /wombat/foo.txt. At midnight of October 31st, /wombat/foo.txt will be renamed as /wombat/2006/10/foo.txt. A new /wombat/foo.txt file will be created where logging output will go for the rest of November. At midnight of November 30th, /wombat/foo.txt will be renamed as /wombat/2006/11/foo.txt and so on.

还有更多,不继续复制粘贴了。

其它属性如下:

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.
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.
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.

其实这些属性都是为TriggeringPolicy接口的实现相关了,因为很显然,它们管理的是什么时候保存,命名和移动日志记录文件了。

TimeBasedRollingPolicy supports automatic file compression. This feature is enabled if the value of the fileNamePattern option ends with .gz or .zip.

使用.gz或者.zip结尾会自动引发压缩功能。

For various technical reasons, rollovers are not clock-driven but depend on the arrival of logging events. For example, on 8th of March 2002, assuming the fileNamePattern is set to yyyy-MM-dd (daily rollover), the arrival of the first event after midnight will trigger a rollover. If there are no logging events during, say 23 minutes and 47 seconds after midnight, then rollover will actually occur at 00:23'47 AM on March 9th and not at 0:00 AM.

这段话其实就是说,输出器不会平白无故意识到已经从 2002-03-08 变到了 2002-03-09 ,它能意识到是因为进入 2002-03-09 这天后发生了一个消息记录事件。于是它意识到了,并且会随之保存 2002-03-08 对应的日志文件,使用 2002-03-09 开始新的日志文件。

Here is a sample configuration for RollingFileAppender in conjunction with a TimeBasedRollingPolicy.

<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.

Note that TimeBasedRollingPolicy already allows limiting the combined size of archived log files. If you only wish to limit the combined size of log archives, then TimeBasedRollingPolicy described above and setting the totalSizeCap property should be amply sufficent.

相比TimeBasedRollingPolicySizeAndTimeBasedRollingPolicy更进一步的给日志文件的大小做了限制。注意这里的大小是指单个的,如果只是对所有日志文件的总和的大小有限制,靠TimeBasedRollingPolicytotalSizeCap属性就能解决。

Here is a sample configuration file demonstrating time and size based log file archiving.

<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.

Size and time based archiving supports deletion of old archive files. You need to specify the number of periods to preserve with the maxHistory property. When your application is stopped and restarted, logging will continue at the correct location, i.e. at the largest index number for the current period.

那么SizeAndTimeBasedRollingPolicy是怎么做到的呢?通过增加一个属性maxFileSize去限制单个日志文件的大小,并通过%i占位符使得当时间上不满足使用另一个文件但文件占用空间已经满足时,用 0 1 2 ... 这样的序号替换%i的位置从而结束当前文件,开始新文件。

FixedWindowRollingPolicy

Here are the available properties for FixedWindowRollingPolicy

Property Name Type Description
minIndex int This option represents the lower bound for the window's index.
maxIndex int This option represents the upper bound for the window's index.
fileNamePattern String This option represents the pattern that will be followed by the FixedWindowRollingPolicy when renaming the log files. It must contain the string %i, which will indicate the position where the value of the current window index will be inserted.For example, using MyLogFile%i.log associated with minimum and maximum values of 1 and 3will produce archive files named MyLogFile1.log, MyLogFile2.log and MyLogFile3.log.Note that file compression is also specified via this property. For example, fileNamePattern set toMyLogFile%i.log.zip means that archived files must be compressed using the zip format; gzformat is also supported.

Let us go over a more concrete example of the fixed window rollover policy. Suppose that minIndex is set to 1, maxIndex set to 3, fileNamePattern property set to foo%i.log, and that file property is set to foo.log.

Number of rollovers Active output target Archived log files Description
0 foo.log - No rollover has happened yet, logback logs into the initial file.
1 foo.log foo1.log First rollover. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
2 foo.log foo1.log, foo2.log Second rollover. foo1.log is renamed as foo2.log. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
3 foo.log foo1.log, foo2.log, foo3.log Third rollover. foo2.log is renamed as foo3.log. foo1.log is renamed as foo2.log. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
4 foo.log foo1.log, foo2.log, foo3.log In this and subsequent rounds, the rollover begins by deleting foo3.log. Other files are renamed by incrementing their index as shown in previous steps. In this and subsequent rollovers, there will be three archive logs and one active log file.

简单来说就是这东西至多生成maxIndex-minIndex+1个log文件,然后当前正在写的日志文件因为TriggeringPolicy而要被保存的话,会保存为foo${minIndex}.log,之前已经保存的文件的序号依次加一,加一后大过maxIndex的那个文件直接删掉。

另外这东西并没有实现TriggeringPolicy,所以在配置文档里还要专门为它写TriggeringPolicy元素。

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>tests.%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>
Overview of triggering policies
TriggeringPolicy implementations are responsible for instructing the RollingFileAppender when to rollover.

TriggeringPolicy负责指定RollingFileAppender (怎么输出)在何时进行。

The TriggeringPolicy interface contains only one method.

package ch.qos.logback.core.rolling;

import java.io.File;
import ch.qos.logback.core.spi.LifeCycle;

public interface TriggeringPolicy<E> extends LifeCycle {

  public boolean isTriggeringEvent(final File activeFile, final <E> event);
}

The isTriggeringEvent() method takes as parameters the active file and the logging event currently being processed. The concrete implementation determines whether the rollover should occur or not, based on these parameters.

相关实现如上。

The most widely-used triggering policy, namely TimeBasedRollingPolicy which also doubles as a rolling policy, was already discussed earlier along with other rolling policies.

因为RollingFileAppender在它之前介绍,而常用的 TimeBasedRollingPolicy和进一步的SizeAndTimeBasedRollingPolicy是两个接口都实现,它们都在前面讲掉了就弄得后面没啥可讲得了。

就一个SizeBasedTriggeringPolicy,。

SizeBasedTriggeringPolicy

这东西其实就是SizeAndTimeBasedRollingPolicy相比TimeBasedRollingPolicy多的那部分。

SizeBasedTriggeringPolicy looks at the size of the currently active file. If it grows larger than the specified size, it will signal the owning RollingFileAppender to trigger the rollover of the existing active file.

SizeBasedTriggeringPolicy accepts only one parameter, namely maxFileSize, with a default value of 10 MB.

The maxFileSize option can be specified in 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.

SocketAppender and SSLSocketAppender:将日志记录输出到网络上的其它主机。

chapter 4

The appenders covered thus far are only able to log to local resources. In contrast, the SocketAppender is designed to log to a remote entity by transmitting serialized ILoggingEvent instances over the wire. When using SocketAppender logging events on the wire are sent in the clear. However, when using SSLSocketAppender, logging events are delivered over a secure channel.

之前讲的那些输出器,都只能在本地处理消息。SocketAppenderSSLSocketAppender则能将记录输出到网络上的其它主机上。区别在于前者不会在传递过程中加密记录,后者会加密记录。

The SocketAppender component (and its SSL-enabled counterpart) discussed previously are designed to allow an application to connect to a remote logging server over the network for the purpose of delivering logging events to the server.

ServerSocketAppender and SSLServerSocketAppender:中转站;收到其它主机的记录请求,按一定规则转发到其它主机去记录。

chapter 4

Instead of initiating a connection to a remote logging server, ServerSocketAppender passively listens on a TCP socket awaiting incoming connections from remote clients. Logging events that are delivered to the appender are distributed to each connected client. Logging events that occur when no client is connected are summarily discarded.

The ServerSocketAppender subtypes are intended to be used exclusively with Logback receiver components. See Receiversfor additional information on this component type.

SMTPAppender:把记录(日志)以邮件发送

chapter 4

The SMTPAppender accumulates logging events in one or more fixed-size buffers and sends the contents of the appropriate buffer in an email after a user-specified event occurs. SMTP email transmission (sending) is performed asynchronously. By default, the email transmission is triggered by a logging event of level ERROR. Moreover, by default, a single buffer is used for all events.

DBAppender:把记录(日志)保存到数据库

chapter 4

The DBAppender inserts logging events into three database tables in a format independent of the Java programming language.

These three tables are logging_event, logging_event_property and logging_event_exception. They must exist beforeDBAppender can be used. Logback ships with SQL scripts that will create the tables. They can be found under the logback-classic/src/main/java/ch/qos/logback/classic/db/script folder. There is a specific script for each of the most popular database systems. If the script for your particular type of database system is missing, it should be quite easy to write one, taking example on the already existing scripts. If you send them to us, we will gladly include missing scripts in future releases.

If your JDBC driver supports the getGeneratedKeys method introduced in JDBC 3.0 specification, assuming you have created the appropriate database tables as mentioned above, then no additional steps are required. Otherwise, there must be an SQLDialect appropriate for your database system. Currently, logback has dialects for H2, HSQL, MS SQL Server, MySQL, Oracle, PostgreSQL, SQLLite and Sybase.

SyslogAppender:把记录(日志)保存到系统日志文档中

chapter 4

The syslog protocol is a very simple protocol: a syslog sender sends a small message to a syslog receiver. The receiver is commonly called syslog daemon or syslog server. Logback can send messages to a remote syslog daemon. This is achieved by using SyslogAppender.

SiftingAppender:比如说,按照user session区分是哪个用户产生的记录并输出到不同的目标。

chapter 4

As its name implies, a SiftingAppender can be used to separate (or sift) logging according to a given runtime attribute. For example, SiftingAppender can separate logging events according to user sessions, so that the logs generated by different users go into distinct log files, one log file per user.

AsyncAppender:根据一定规则分派记录请求到不同的输出器

chapter 4

AsyncAppender logs ILoggingEvents asynchronously. It acts solely as an event dispatcher and must therefore reference another appender in order to do anything useful.

LOSSY BY DEFAULT IF 80% FULL AsyncAppender buffers events in a BlockingQueue. A worker thread created by AsyncAppendertakes events from the head of the queue, and dispatches them to the single appender attached to AsyncAppender. Note that by default, AsyncAppender will drop events of level TRACE, DEBUG and INFO if its queue is 80% full. This strategy has an amazingly favorable effect on performance at the cost of event loss.

如何自己写一个输出器

chapter 4

You can easily write your appender by subclassing AppenderBase. It handles support for filters, status messages and other functionality shared by most appenders. The derived class only needs to implement one method, namely append(Object eventObject).

阳光号
129 声望5 粉丝

引用和评论

0 条评论