LogBack配置

根标签 configuration

属性

<configuration scan="true" scanPeriod="120 seconds" debug="false">  
        <!-- ... -->
</configuration>

scan


当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。

scanPeriod


设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。

debug


当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false

子节点

上下文名称 contextName


默认为default,用于区分不同应用程序的记录,一旦设置,不能修改


使用时可用${contextName}

<configuration scan="true" scanPeriod="120 seconds" debug="false">  
    <contextName>serverName</contextName> 
        <!-- ... -->
</configuration>

变量 property


全局变量,类似于maven的pom.xml中的property,有两个属性:name、value,使用时使用${}占位符

<configuration scan="true" scanPeriod="120 seconds" debug="false">  
    <property name="serverName" value="TestServer"/>
    <contextName>${serverName}</contextName>     
        <!-- ... -->
</configuration>

日志管理 logger

负责写日志 appender

日志管理-logger


可以包含零个或多个

属性
name


用来约束某个包或者某个具体的类
root为全局配置

level


设置日志级别,与大小写无关,默认为DEBUG


日志级别从高到低:OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL

  • ALL 最低等级的,用于打开所有日志记录。
  • TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
  • DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
  • INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
  • WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
  • ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
  • FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
  • OFF 最高等级的,用于关闭所有日志记录。
additivity


是否向上级logger传递打印信息,默认是true,即INFO级别会向DEBUG传递

<configuration>               
    <!-- 指定包中的日志,日志级别为DEBUG,不向上传递,打印至控制台及指定日志文件 -->
    <logger name="test.yong.mapper.dao" additivity="false" level="DEBUG">
        <appender-ref ref="console"/>
        <appender-ref ref="logfile_info"/>
    </logger>
    <!-- 指定类中的日志,日志级别为ERROR -->
    <logger name="org.mybatis.spring.SqlSessionUtils" level="ERROR"/>
    
    <!-- 配置<appender-ref>使用,设置统一日志级别 -->
    <logger name="root" level="INFO">
    
    </logger>
</configuration>

负责写日志-appender

属性

name


appender的名称,全局唯一,appender-ref 关联该name

class


appender的全限定名

ConsoleAppender 日志写到控制台


把日志添加到控制台
<encoder>:对日志进行格式化
<target>:字符串 System.out 或者 System.err ,默认 System.out

<configuration>  
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">  
    <encoder>  
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>  
    </encoder>  
  </appender>  
  
  <root level="DEBUG">  
    <appender-ref ref="console" />  
  </root>  
</configuration>
FileAppender 日志写到文件


把日志添加到文件
<file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。


<append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。


<encoder>:对记录事件进行格式化。


<prudent>:如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。

prudent支持多JVM同时操作同一个日志文件

官方给的说明如下:如果使用prudent模式,FileAppender将安全的写入到指定文件,即使存在运行在不同机器上的、其他JVM中运行的其他FileAppender实例。
Prudent模式更依赖于排他文件锁,经验表明加了文件锁后,写日志的开始是正常的3倍以上。当prudent模式关闭时,每秒logging event的吞吐量为100,000,当prudent模式开启时,大约为每秒33,000

<configuration>  
    <contextName>serverName</contextName>
    <appender name="logfile_info" class="ch.qos.logback.core.FileAppender">  
        <file>${contextName}.log</file>  
    <append>true</append>  
    <encoder>  
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>  
    </encoder>  
    </appender>  
          
    <root level="DEBUG">  
        <appender-ref ref="logfile_info" />  
    </root>  
</configuration>
RollingFileAppender 滚动记录文件


滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件
<file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。


<append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。


<encoder>:对记录事件进行格式化。(具体参数稍后讲解 )


<rollingPolicy>:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。


<triggeringPolicy >: 告知 RollingFileAppender 合适激活滚动。


<prudent>:当为true时,不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有两个限制,1不支持也不允许文件压缩,2不能设置file属性,必须留空。

rollingPolicy 滚动策略
TimeBasedRollingPolicy


最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。


<fileNamePattern>:


必要节点,包含文件名及“%d”转换符, “%d”可以包含一个 java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}


RollingFileAppender的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),
活动文件的名字不会改变;如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。


<maxHistory>:


可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。


假设设置每个月滚动,且 <maxHistory>是6,则只保存最近6个月的文件,删除之前的旧文件。


删除旧文件时,那些为了归档而创建的目录也会被删除。

FixedWindowRollingPolicy


根据固定窗口算法重命名文件的滚动策略


<minIndex>:窗口索引最小值


<maxIndex>:窗口索引最大值,当用户指定的窗口过大时,会自动将窗口设置为12。


<fileNamePattern >:
必须包含“%i”例如,假设最小值和最大值分别为1和2,命名模式为 mylog%i.log,会产生归档文件mylog1.log和mylog2.log。还可以指定文件压缩选项,例如,mylog%i.log.gz或者log%i.log.zip

SizeAndTimeBasedRollingPolicy


按时间滚动,按大小归档





必要节点,%d和%i 必须有


<maxFileSize>


最大文件大小,超过大小进行归档


<maxHistory>


可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。


<totalSizeCap>


总日志文件最大大小,当总日志文件最大大小超过最大值时,删除旧文件,优先级大于maxHistory

<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <FileNamePattern>
        /app/log/${CONTEXT_NAME}/info/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd}.ysData.%i.log
    </FileNamePattern>
    <maxFileSize>100MB</maxFileSize>
    <maxHistory>30</maxHistory>
    <totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
triggeringPolicy 日志触发器策略


SizeBasedTriggeringPolicy: 查看当前活动文件的大小,如果超过指定大小会告知 RollingFileAppender 触发当前活动文件滚动。只有一个节点:


<maxFileSize>:这是活动文件的大小,默认值是10MB。


例:

<!-- 每天生成一个日志文件,保存30天的日志文件 -->
<configuration>   
  <appender name="loggerFile_info" class="ch.qos.logback.core.rolling.RollingFileAppender">   
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">   
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>   
      <maxHistory>30</maxHistory>    
    </rollingPolicy>   
    <encoder>   
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>   
    </encoder>   
  </appender>    
  <root level="DEBUG">   
    <appender-ref ref="loggerFile_info" />   
  </root>   
</configuration>
<!-- 按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。 -->
<configuration>   
  <appender name="loggerFile_info" 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>20MB</maxFileSize>   
    </triggeringPolicy>   
    <encoder>   
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>   
    </encoder>   
  </appender>   
  <root level="DEBUG">   
    <appender-ref ref="loggerFile_info" />   
  </root>   
</configuration>
DBAppender 日志入库


DBAppender将日志存入三张表中,这三张表分别为:logging_event, logging_event_propertylogging_event_exception。在使用 DBAppender 之前,它们必须存在。


logback 自带 SQL 脚本来创建表。这些脚本在 logback-classic/src/main/java/ch/qos/logback/classic/db/script 文件夹下。每一种最流行的数据库都有一个对应的脚本。


目前 logback 支持的数据库方言有 H2, HSQL, MS SQL Server, MySQL, Oracle, PostgreSQL, SQLLite and Sybase。


下面的表格总结了数据库类型,以及它们是否支持 getGeneratedKeys() 方法:

RDBMS测试版本JDBC 驱动的测试版本是否支持 getGeneratedKeys()logback 是否提供对应的方言
DB2untesteduntestedunknownNO
H21.2.132-unknownYES
HSQL1.8.0.7-NOYES
Microsoft SQL Server20052.0.1008.2 (sqljdbc.jar)YESYES
MySQL5.0.225.0.8 (mysql-connector.jar)YESYES
PostgreSQL8.x8.4-701.jdbc4NOYES
Oracle10g10.2.0.1 (ojdbc14.jar)YESYES
SQLLite3.7.4-unknownYES
Sybase SQLAnywhere10.0.1-unknownYES


logging_event 表包含了以下字段:

FieldTypeDescription
timestampbig int日志事件的创建时间
formatted_messagetext经过 org.slf4j.impl.MessageFormatter
格式化后的消息
logger_namevarchar发出日志的 logger 名
level_stringvarchar日志事件的级别
reference_flagsmallint用来表示是否是异常或者与 MDC 属性相关联。它的值通过 ch.qos.logback.classic.db.DBHelper
计算得到。日志时间包含 MDC
或者 Context
时,它的值为 1。包含异常时,它的值为 2。包含两者,则值为 3
caller_filenamevarchar发出日志请求的文件名
caller_classvarchar发出日志请求的类
caller_methodvarchar发出日志请求的方法
caller_linechar发出日志请求所在的行
event_idint日志事件在数据库的 id


logging_event_property 表用于存储 MDC 或者 Context 中的 key 与 value。它包含如下字段:

FieldTypeDescription
event_idint日志事件的数据库 id
mapped_keyvarcharMDC
属性的 key
mapped_valuetextMDC
属性的 value


logging_event_exception 表包含如下字段:

FieldTypeDescription
event_idint日志事件的数据库 id
ismallint堆栈所在的行
trace_linevarchar相对应的堆栈信息
ConnectionSource


ConnectionSource 接口提供了一种可插拔式的方式为需要使用 java.sql.Connection 的 logback 类获取 JDBC 连接。


目前有三种实现,分别为:DataSourceConnectionSource,DriverManagerConnectionSource 与 JNDIConnectionSource

DriverManagerConnectionSource


DriverManagerConnectionSource 实现了 ConnectionSource 接口,通过基于 URL 的传统 JDBC 方式来获取连接。


这个类为每一个调用 getConnection() 的方法都新建一个 Connection 连接。推荐你使用本地支持的连接池的 JDBC 驱动,或者创建你自己实现的 ConnectionSource,基于你已经使用的任何连接池机制

<!-- DriverManagerConnectionSource示例 -->
<configuration>
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
      <driverClass>com.mysql.jdbc.Driver</driverClass>
      <url>jdbc:mysql://host_name:3306/datebase_name</url>
      <user>username</user>
      <password>password</password>
    </connectionSource>
  </appender>
  <root level="DEBUG" >
    <appender-ref ref="DB" />
  </root>
</configuration>
JNDIConnectionSource


JNDIConnectionSource是 logback 自带的,ConnectionSource的另一种实现。从名字可以看出来,它通过 JNDI 获取 javax.sql.DataSource,然后再获取 java.sql.Connection 实例。JNDIConnectionSource主要设计用在 J2EE 应用服务器以及应用服务器客户端中,这里假设应用服务器支持远程获取 javax.sql.DataSource。因为可以利用连接池或者其它应用服务器所提供的好处。更加重要的是,你的应用不需要做重复的工作,因为不需要在 logback.xml 中定义一个 DataSource。

<!-- tomcat中配置jndl -->
<Context docBase="/path/to/app.war" path="/myapp">
  ...
  <Resource name="jdbc/logging"
               auth="Container"
               type="javax.sql.DataSource"
               username="..."
               password="..."
               driverClassName="org.postgresql.Driver"
               url="jdbc:postgresql://localhost/..."
               maxActive="8"
               maxIdle="4"/>
  ...
</Context>
<!-- JNDIConnectionSource示例 -->
<configuration debug="true">
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
      <!-- please note the "java:comp/env/" prefix -->
      <jndiLocation>java:comp/env/jdbc/logging</jndiLocation>
    </connectionSource>
  </appender>
  <root level="INFO">
    <appender-ref ref="DB" />
  </root>  
</configuration>


这个类通过无参构造函数获取一个 javax.naming.InitialContext。在 J2EE 环境通常可以行得通。但是在 J2EE 环境之外,你需要根据 JNDI 提供者的文档提供一个 jndi.properties 属性文件

DataSourceConnectionSource
<configuration  debug="true">
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
     <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">

       <dataSource class="${dataSourceClass}">
         <!-- Joran 不能替换不是属性的变量。因此我们不能像其它变量一样声明接下来的变量
         -->
         <param name="${url-key:-url}" value="${url_value}"/>
         <serverName>${serverName}</serverName>
         <databaseName>${databaseName}</databaseName>
       </dataSource>
       <user>${user}</user>
       <password>${password}</password>
     </connectionSource>
  </appender>
  <root level="INFO">
    <appender-ref ref="DB" />
  </root>  
</configuration>


在这个例子中,我们大量使用了变量替换。当需要把一些连接的细节集中在一个配置文件中,并且通过 logback 与其它框架共享时非常方便。

连接池


日志事件可以很快的被创建。为了让日志事件都能被插入到数据库,推荐DBAppender使用连接池配置。


经过实验发现,使用连接池,可以让 DBAppender 有大幅的性能提升。下面的配置文件,将日志事件发送给 MySQL,没有使用连接池。

<configuration>
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
      <dataSource class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <serverName>${serverName}</serverName>
        <port>${port$</port>
        <databaseName>${dbName}</databaseName>
        <user>${user}</user>
        <password>${pass}</password>
      </dataSource>
    </connectionSource>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="DB" />
  </root>
</configuration>


在这个配置文件中,发送 500 个日志事件到 MySQL 数据库,需要高达 5 秒的时间,相当每条请求需要 10 毫秒。在大型的应用中,这个数字是不能够被接受的。


DBAppender` 连接池需要使用一个专业的外部库。下一个例子中使用 c3p0。为了使用 c2p0,你需要下载并将 c3p0-VERSION.jar 放在类路径下。

<configuration>
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource
      class="ch.qos.logback.core.db.DataSourceConnectionSource">
      <dataSource
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <driverClass>com.mysql.jdbc.Driver</driverClass>
        <jdbcUrl>jdbc:mysql://${serverName}:${port}/${dbName}</jdbcUrl>
        <user>${user}</user>
        <password>${password}</password>
      </dataSource>
    </connectionSource>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="DB" />
  </root>
</configuration>


使用这个新的配置,发送 500 条日志事件到 MySQL 数据库大约需要 0.5 秒,大约 1 毫秒一条请求,性能提升了十倍。

SiftingAppender 分离或者过滤日志


SiftingAppender 根据给定的运行时属性分离或者过滤日志。例如,SiftingAppender 可以根据用户的 session 分离日志,因此不同的用户的日志会有不同的日志文件,一个用户一个日志文件。

属性名类型描述
timeoutDuration一个内置的 appender 如果在指定 timeout
时间内没有被访问,则被认为是过时的。一个过时的 appender 会被关闭,并且不会被 SiftingAppende
所引用。默认值为 30 分钟
maxAppenderCountintegerSiftingAppender
可以创建并且跟踪内置 appender 的最大数量。默认值为 Integer.MAX_VALUE


通过动态创建来实现这个。SiftingAppender 通过配置文件中指定的模板 (通过闭合的 <sift> 元素,见下面的例子) 来创建内置的 appender。SiftingAppender 负责管理子 appender 的生命周期。例如,SiftingAppender 会自动关闭并移除任何过时的 appender。在指定的 timeout 时间内没有被访问过的内置 appender,被认为是过时的。


在处理一个日志事件时,SiftingAppender会委托一个子 appender 去进行处理。选择的标准是通过 discriminator 在运行时计算。用户也可以通过 Discriminator 来指定一个选择标准。

示例


应用通过打印日志来表明应用已经启动。通过 MDC 设置键 “userid” 对应的值为 “Alice”,并打印了一条日志信息。

logger.debug("Application started");
MDC.put("userid", "Alice");
logger.debug("Alice says hello");
<configuration>
    <property name="FILE_NAME" value="FILE" />
    <appender name="SIFT"
        class="ch.qos.logback.classic.sift.SiftingAppender">
        <!-- 在缺少 class 属性的情况下,默认的 discriminator 类型为                                          ch.qos.logback.classic.sift.MDCBasedDiscriminator -->
        <discriminator>
            <key>userid</key>
            <defaultValue>unknown</defaultValue>
        </discriminator>
        <sift>
            <appender name="FILE-${userid}"
                class="ch.qos.logback.core.FileAppender">
                <file>${userid}_${FILE_NAME}.log</file>
                <append>false</append>
                <layout class="ch.qos.logback.classic.PatternLayout">
                    <pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
                </layout>
            </appender>
        </sift>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="SIFT" />
    </root>
</configuration>


在没有 class 属性的情况下,默认的 discriminator 类型为 MDCBasedDiscriminator。discriminator 的的值为 MDC 的 key 所对应的值。但是,如果 MDC 的值为 null,那么 defaultValue 的将为 discriminator 的值。


SiftingAppender 的独特之处在于它有能力去引用以及配置子 appender。在上面的例子中,SiftingAppender 会创建多个 FileAppender 实例。每个 FileAppender 实例通过 MDC 的 key 所对应的值来标识。每当 MDC 的 key “userid” 被分配一个新值时,一个新的 FileAppender 将会被构建。SiftingAppender 可以追踪它所创建的 appender。appender 在 30 分钟之内没有被使用将会被自动关闭并丢弃。


导出变量 有不同 appender 实例是不够的。每一个实例都必须输出到一个唯一的资源中。为了做到这种区分,在 appender 模板中,key 被传递给 discriminator。在上面的例子中是 “userid”,它将被导出并变成一个变量。因此,该变量可以通过给定的子 appender 来区分具体的资源。


在上面的示例中,使用 “byUserid.xml” 来运行 SiftExample,将会创建两个不同的日志文件,“unknown.log” 与 “Alice.log”。


本地变量 在版本 1.0.12 中,配置文件中局部变量的属性也可以应用到内置的 appender 中。而且,你可以在  元素中定义变量以及动态定义属性。或者在  元素之外定义变量,在里面使用也是支持的。

获取正确的 timeout


对于特定类型的应用,正确的获取 timeout 参数非常困难。如果 timeout 过小,一个新的内置 appender 在创建几秒钟之后就被移除了。这种现象被称为 “制造垃圾”。如果 timeout 的值过大,那么 appender 会快速接连的被创建,可能会耗尽资源。同理,设置 maxAppenderCount 的值太低会产生垃圾。


在大多数情况下,在代码中显示的指出不需要再创建内置的 appender。需要在代码中标记日志事件为 FINALIZE_SESSION。无论什么时候 SiftingAppender 看到日志事件标记为 FINALIZE_SESSION,它将会终结相关的子 appender。在生命周期快结束时,内置的 appender 将会留存几秒钟来处理之后到来的日志事件,然后再关闭。

import org.slf4j.Logger;
import static ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER;

  void job(String jobId) {
    MDC.put("jobId", jobId);
    logger.info("Starting job.");
    ... do whather the job needs to do
    // 将导致内置 appender 结束生命周期。但是会留存几秒钟
    logger.info(FINALIZE_SESSION_MARKER, "About to end the job");
    try {
      .. perform clean up
    } catch(Exception e);  
      // 被留存的 appender 处理,但是不会再创建新的 appender
      logger.error("unexpected error while cleaning up", e);
    }
  }
其余appender


SocketAppender、SMTPAppender、SyslogAppender、SiftingAppender

<encoder>


负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。


目前PatternLayoutEncoder 是唯一有用的且默认的encoder ,有一个<pattern>节点,用来设置日志的输入格式。使用“%”加“转换符”方式,如果要输出“%”,则必须用“\”对“%”进行转义


例:

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


转换符 作用

c {length } lo {length } logger {length }输出日志的logger名,可有一个整形参数,功能是缩短logger名,设置为0表示只输入logger最右边点符号之后的字符串。 Conversion specifier Logger name Result%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.Bar
C {length } class {length }输出执行记录请求的调用者的全限定名。参数与上面的一样。尽量避免使用,除非执行速度不造成任何问题。
contextName cn输出上下文名称。
d {pattern } date {pattern }输出日志的打印日志,模式语法与java.text.SimpleDateFormat
兼容。 Conversion Pattern Result%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.812
F / file输出执行记录请求的java源文件名。尽量避免使用,除非执行速度不造成任何问题。
caller{depth} caller{depth, evaluator-1, … evaluator-n}输出生成日志的调用者的位置信息,整数选项表示输出信息深度。例如, %caller{2}  输出为:0 [main] DEBUG - logging statement Caller+0 at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22) Caller+1 at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
例如, %caller{3}  输出为:16 [main] DEBUG - logging statement Caller+0 at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22) Caller+1 at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17) Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)
L / line输出执行日志请求的行号。尽量避免使用,除非执行速度不造成任何问题。
m / msg / message输出应用程序提供的信息。
M / method输出执行日志请求的方法名。尽量避免使用,除非执行速度不造成任何问题。
n输出平台先关的分行符“\n”或者“\r\n”。
p / le / level输出日志级别。
r / relative输出从程序启动到创建日志记录的时间,单位是毫秒
t / thread输出产生日志的线程名。
replace(p ){r, t}p 为日志内容,r 是正则表达式,将p 中符合r 的内容替换为t 。例如, “%replace(%msg){‘\s’, ‘’}”


格式修饰符,与转换符共同使用:


可选的格式修饰符位于“%”和转换符之间。


第一个可选修饰符是左对齐 标志,符号是减号“-”;接着是可选的最小宽度 修饰符,用十进制数表示。


如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格。


如果字符大于最小宽度,字符永远不会被截断。最大宽度 修饰符,符号是点号"."后面加十进制数。


如果字符大于最大宽度,则从前面截断。点符号“.”后面加减号“-”在加数字,表示从尾部截断。


例如:%-4relative 表示,将输出从程序启动到创建日志记录的时间 进行左对齐 且最小宽度为

<encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}| %-4relative [%thread][%-5level][%logger:%L]%n %msg%n</pattern>
    <charset>GBK</charset>
</encoder>

<filter>


过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。

  • DENY,日志将立即被抛弃不再经过其他过滤器;
  • NEUTRAL,有序列表里的下个过滤器过接着处理日志;
  • ACCEPT,日志会被立即处理,不再经过剩余过滤器。


过滤器被添加到<Appender>中,为<Appender>添加一个或多个过滤器后,可以用任意条件对日志进行过滤。<Appender> 有多个过滤器时,按照配置顺序执行。

LevelFilter


级别过滤器,根据日志级别进行过滤


如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志


<level>:设置过滤级别


<onMatch>:用于配置符合过滤条件的操作


<onMismatch>:用于配置不符合过滤条件的操作

<!-- 将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉 -->
<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


临界值过滤器,过滤掉低于指定临界值的日志


当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝

<!-- 过滤掉所有低于INFO级别的日志 -->
<configuration>   
  <appender name="CONSOLE"   
    class="ch.qos.logback.core.ConsoleAppender">   
    <!-- 过滤掉 TRACE 和 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>
EvaluatorFilter


求值过滤器,评估、鉴别日志是否符合指定条件


需要额外的两个JAR包,commons-compiler.jar和janino.jar


<evaluator>


鉴别器,常用的鉴别器是JaninoEventEvaluato,也是默认的鉴别器,它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件。evaluator有个子标签<expression>,用于配置求值条件


求值表达式作用于当前日志,logback向求值表达式暴露日志的各种字段:

NameTypeDescription
eventLoggingEvent与记录请求相关联的原始记录事件,下面所有变量都来自event,例如,event.getMessage()返回下面"message"相同的字符串
messageString日志的原始消息,例如,设有logger mylogger,“name"的值是"AUB”,对于 mylogger.info(“Hello {}”,name); "Hello {}"就是原始消息。
formatedMessageString日志被各式话的消息,例如,设有logger mylogger,“name"的值是"AUB”,对于 mylogger.info(“Hello {}”,name); "Hello Aub"就是格式化后的消息。
loggerStringlogger 名。
loggerContext[LoggerContextVO](https://www.iteye.com/admin/blogs/xref/ch/qos/logback/classic/spi/LoggerContextVO.html)日志所属的logger上下文。
levelint级别对应的整数值,所以 level > INFO 是正确的表达式。
timeStamplong创建日志的时间戳。
markerMarker与日志请求相关联的Marker对象,注意“Marker”有可能为null,所以你要确保它不能是null。
mdcMap包含创建日志期间的MDC所有值得map。访问方法是: mdc.get(“myKey”) 。mdc.get()返回的是Object不是String,要想调用String的方法就要强转,例如,((String) mdc.get("k")).contains("val")
.MDC可能为null,调用时注意。
throwablejava.lang.Throwable如果没有异常与日志关联"throwable" 变量为 null. 不幸的是, “throwable” 不能被序列化。在远程系统上永远为null,对于与位置无关的表达式请使用下面的变量throwableProxy
throwableProxy[IThrowableProxy](https://www.iteye.com/admin/blogs/xref/ch/qos/logback/classic/spi/IThrowableProxy.html)与日志事件关联的异常代理。如果没有异常与日志事件关联,则变量"throwableProxy" 为 null. 当异常被关联到日志事件时,“throwableProxy” 在远程系统上不会为null


<onMatch>:用于配置符合过滤条件的操作


<onMismatch>:用于配置不符合过滤条件的操作

<!-- 过滤掉所有日志消息中不包含“billing”字符串的日志 -->
<configuration>   
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">   
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">         
      <evaluator> <!-- 默认为 ch.qos.logback.classic.boolex.JaninoEventEvaluator -->   
        <expression>return message.contains("billing");</expression>   
      </evaluator>   
      <OnMatch>ACCEPT </OnMatch>  
      <OnMismatch>DENY</OnMismatch>  
    </filter>   
    <encoder>   
      <pattern>   
        %-4relative [%thread] %-5level %logger - %msg%n   
      </pattern>   
    </encoder>   
  </appender>   
   
  <root level="INFO">   
    <appender-ref ref="console" />   
  </root>   
</configuration>

<matcher>


匹配器


尽管可以使用String类的matches()方法进行模式匹配,但会导致每次调用过滤器时都会创建一个新的Pattern对象,为了消除这种开销,可以预定义一个或多个matcher对象,定以后就可以在求值表达式中重复引用。


<matcher>是<evaluator>的子标签。


<matcher>中包含两个子标签,一个是<name>,用于定义matcher的名字,求值表达式中使用这个名字来引用matcher;另一个是<regex>,用于配置匹配条件

<configuration debug="true">   
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">   
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">   
      <evaluator>           
        <matcher>   
          <Name>odd</Name>   
          <!-- filter out odd numbered statements -->   
          <regex>statement [13579]</regex>   
        </matcher>     
        <expression>odd.matches(formattedMessage)</expression>   
      </evaluator>   
      <OnMismatch>NEUTRAL</OnMismatch>   
      <OnMatch>DENY</OnMatch>   
    </filter>   
    <encoder>   
      <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>   
    </encoder>   
  </appender>   
  <root level="DEBUG">   
    <appender-ref ref="console" />   
  </root>   
</configuration>

MDC使用


logback.xml中配置:


使用%X{xxx} 进行占位,可配置多个,名称不能重复

<!-- %X{logToken}为MDC的占位符 -->
<encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}|%X{logToken}|%X{IP}|%X{HOSTNAME}| %-4relative [%thread][%-5level][%logger:%L]%n %msg%n</pattern>
    <charset>GBK</charset>
</encoder>


在java代码中赋值,可put多个与占位符名称相同的属性,无顺序要求

MDC.put("logToken", "xxxxxx");
MDC.put("IP",getServerIpAddress());
MDC.put("HOSTNAME",getHostName());


MDC线程安全,使用结束后应及时清除MDC

// 清空全部
MDC.clear();
// 移除指定key
MDC.remove(key);

导入其他logback文件

<!-- logback.xml -->
<configuration>
    <contextName>xxxx</contextName>
    <!-- <include resource="org/springframework/boot/logging/logback/base.xml"/> -->
    <include resource="logback-common.xml"/>
</configuration>
<?xml version="1.0" encoding="GBK"?>
<!-- logback-common.xml -->
<included>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][track: %X{trackToken}] %-5level %logger:%L%n
                %msg%n
            </pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>
    <appender name="logfile_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <Prudent>true</Prudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>
                /app/log/${CONTEXT_NAME}/error/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd-HH}.error.log
            </FileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][%X{trackToken}][%-5level][%logger:%L]%n %msg%n
            </pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>

    <appender name="logfile_debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <!--<onMatch>ACCEPT</onMatch>-->
            <!--<onMismatch>DENY</onMismatch>-->
        </filter>
        <Prudent>true</Prudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>
                /app/log/${CONTEXT_NAME}/debug/${HOSTNAME}.${CONTEXT_NAME}.%d{yyyy-MM-dd-HH}.debug.log
            </FileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread][%X{trackToken}][%-5level][%logger:%L]%n %msg%n
            </pattern>
            <charset>GBK</charset>
        </encoder>
    </appender>
    <logger name="root" level="DEBUG">
        <appender-ref ref="logfile_debug"/>
        <appender-ref ref="logfile_error"/>
    </logger>
    <logger name="xxxx" level="DEBUG"/>
    <logger name="org.hibernate" level="WARN"/>
    <logger name="org.hibernate.SQL" level="DEBUG"/>
    <logger name="org.apache.camel" level="ERROR"/>
    <logger name="org.apache.activemq.transport" level="WARN"/>
    <logger name="java.sql" level="DEBUG"/>
    <logger name="com.mchange" level="WARN"/>
    <logger name="org.springframework" level="WARN"/>
    <logger name="org.apache.commons" level="WARN"/>
    <logger name="org.apache.http.wire" level="OFF"/>
    <logger name="org.apache.http.headers" level="OFF"/>
    <logger name="org.springframework.data.mongodb.core" level="DEBUG"/>
    <logger name="org.mongodb.driver.cluster" level="WARN"/>
    <logger name="org.mongodb.driver.protocol.command" level="WARN"/>
    <logger name="com.netflix" level="INFO"/>
    <logger name="org.apache.http.impl.conn" level="INFO"/>
    <logger name="org.apache.http.client.protocol" level="INFO"/>
</included>

与SpringBoot结合


官方推荐使用logback-spring.xml作为配置文件命名

<springProfile>


<springProfile> 标签允许我们更加灵活配置文件,可选地包含或排除配置部分。


元素中的任何位置均支持轮廓部分。使用该name属性指定哪个配置文件接受配置。可以使用逗号分隔列表指定多个配置文件。

<springProfile name="dev">
    <!-- 开发环境时激活 -->
</springProfile>

<springProfile name="dev,test">
    <!-- 开发,测试的时候激活-->
</springProfile>

<springProfile name="!prod">
    <!-- 当 "生产" 环境时,该配置不激活-->
</springProfile>
<!-- 开发环境日志级别为DEBUG -->
<springProfile name="dev">
    <root level="DEBUG">
        <appender-ref ref="FILE"/>
        <appender-ref ref="STDOUT"/>
    </root>
</springProfile>

<!-- 测试环境日志级别为INFO -->
<springProfile name="test">
    <root level="INFO">
        <appender-ref ref="FILE"/>
        <appender-ref ref="STDOUT"/>
    </root>
</springProfile>

<springProperty>


1.该 <springProperty> 标签允许我们从Spring中显示属性,Environment 以便在Logback中使用。如果你想将 application.properties在回读配置中访问文件中的值,这将非常有用


2.标签的工作方式与Logback的标准 <property> 标签类似,但不是直接value 指定source属性(从Environment)指定。


scope 如果需要将属性存储在local范围之外的其他位置,则可以使用该属性。如果您需要一个后备值,以防该属性未设置,则Environment可以使用该defaultValue属性。

<!-- 读取spring.application.name中的属性来生成日志文件名 -->
<!-- 如果无法获取,在springProperty前添加property标签 -->
<springProperty scope="context" name="logName" source="spring.application.name" defaultValue="localhost.log"/>

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/${logName}.log</file>    <!-- 使用方法 -->
    <append>true</append>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>logs/${logName}-%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
        <maxFileSize>100MB</maxFileSize>
        <maxHistory>7</maxHistory>
        <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line] %mdc{client} %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>DEBUG</level>
    </filter>
</appender>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值