• Logback 专题


    logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <!--
      <pattern>
          %d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n
          Logger: %logger
          Class: %class
          File: %file
          Caller: %caller
          Line: %line
          Message: %m
          Method: %M
          Relative: %relative
          Thread: %thread
          Exception: %ex
          xException: %xEx
          nopException: %nopex
          rException: %rEx
          Marker: %marker
          newline:%n
      </pattern>
      -->
    
        <property name="CUSTOM_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n"/>
        <include resource="org/springframework/boot/logging/logback/base.xml"/>
    
        <appender name="ROLLING-FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logs/todo.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- daily rollover -->
                <fileNamePattern>logs/todo.%d{yyyy-MM-dd}.log</fileNamePattern>
                <!-- keep 30 days' worth of history capped at 1GB total size -->
                <maxHistory>30</maxHistory>
                <totalSizeCap>1GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            </encoder>
        </appender>
    
        <appender name="ROLLING-FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logs/todo-warn.log</file>
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>WARN</level>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- daily rollover -->
                <fileNamePattern>logs/todo-warn.%d{yyyy-MM-dd}.log</fileNamePattern>
                <!-- keep 30 days' worth of history capped at 5GB total size -->
                <maxHistory>30</maxHistory>
                <totalSizeCap>5GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            </encoder>
        </appender>
    
        <logger name="com.tangcheng" level="INFO">
            <appender-ref ref="ROLLING-FILE-WARN"/>
        </logger>
    
        <logger name="org" level="INFO">
            <appender-ref ref="ROLLING-FILE-WARN"/>
        </logger>
    
        <root level="INFO">
            <appender-ref ref="ROLLING-FILE-INFO"/>
        </root>
    
    </configuration>

    In the remainder of this document, we will write "logback" to refer to the logback-classic module.
    Logger, Appenders and Layouts
    Logback is built upon three main classes: Logger, Appender and Layout.
    These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.

    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.

    Example: Additivity flag (logback-examples/src/main/resources/chapters/configuration/additivityFlag.xml)

    <configuration>
    
      <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>foo.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>
    
      <logger name="chapters.configuration.Foo" additivity="false">
        <appender-ref ref="FILE" />
      </logger>
    
      <root level="debug">
        <appender-ref ref="STDOUT" />
      </root>
    </configuration>


    This example, the appender named FILE is attached to the chapters.configuration.Foo logger. Moreover, the chapters.configuration.Foo logger has its additivity flag set to false such that its logging output will be sent to the appender named FILE but not to any appender attached higher in the hierarchy. Other loggers remain oblivious to the additivity setting of the chapters.configuration.Foo logger.
    Running the MyApp3 application with the additivityFlag.xml configuration file will output results on the console from the chapters.configuration.MyApp3 logger.
    However, output from the chapters.configuration.Foo logger will appear in the foo.log file and only in that file.

    https://logback.qos.ch/manual/configuration.html

    File inclusion

    Joran supports including parts of a configuration file from another file. This is done by declaring a <include> element, as shown below:

    Example: File include (logback-examples/src/main/resources/chapters/configuration/containingConfig.xml)

    <configuration>
      <include file="src/main/java/chapters/configuration/includedConfig.xml"/>
    
      <root level="DEBUG">
        <appender-ref ref="includedConsole" />
      </root>
    
    </configuration>

    The target file MUST have its elements nested inside an <included> element. For example, a ConsoleAppender could be declared as:

    Example: File include (logback-examples/src/main/resources/chapters/configuration/includedConfig.xml)

    <included>
      <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
          <pattern>"%d - %m%n"</pattern>
        </encoder>
      </appender>
    </included>

    Again, please note the mandatory <included> element.

    The contents to include can be referenced as a file, as a resource, or as a URL.

      • As a file:
        To include a file use the file attribute. You can use relative paths but note that the current directory is defined by the application and is not necessarily related to the path of the configuration file.
      • As a resource:
        To include a resource, i.e a file found on the class path, use the resource attribute.

    <include resource="includedConfig.xml"/>

    As a URL:
    To include the contents of a URL use the url attribute.

    <include url="http://some.host.com/includedConfig.xml"/>

    If it cannot find the file to be included, logback will complain by printing a status message. In case the included file is optional, you can suppress the warning message by setting optional attribute to true in the <include> element.

    <include optional="true" ..../>

    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 NameAttached AppendersAdditivity FlagOutput TargetsComment
    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.

    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. ThePatternLayout, part of the standard logback distribution, lets the user specify the output format according to conversion patterns similar to the C language printf function.


    The following two lines will yield the exact same output. However, in case of a disabled logging statement, the second variant will outperform the first variant by a factor of at least 30.

    logger.debug("The new entry is "+entry+".");
    logger.debug("The new entry is {}.", entry);

    https://logback.qos.ch/manual/architecture.html

     

     

    Conversion WordEffect
    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
    %logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar
    %logger{0} mainPackage.sub.sample.Bar Bar
    %logger{5} mainPackage.sub.sample.Bar m.s.s.Bar
    %logger{10} mainPackage.sub.sample.Bar m.s.s.Bar
    %logger{15} mainPackage.sub.sample.Bar m.s.sample.Bar
    %logger{16} mainPackage.sub.sample.Bar m.sub.sample.Bar
    %logger{26} mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar

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

     

    Below are various format modifier examples for the logger conversion specifier.

    Format modifierLeft justifyMinimum widthMaximum widthComment
    %20logger false 20 none Left pad with spaces if the logger name is less than 20 characters long.
    %-20logger true 20 none Right pad with spaces if the logger name is less than 20 characters long.
    %.30logger NA none 30 Truncate from the beginning if the logger name is longer than 30 characters.
    %20.30logger false 20 30 Left pad with spaces if the logger name is shorter than 20 characters.
    However, if logger name is longer than 30 characters, then truncate from the beginning.
    %-20.30logger true 20 30 Right pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning.
    %.-30logger NA none 30 Truncate from the end if the logger name is longer than 30 characters.

    The table below list examples for format modifier truncation. Please note that the square brackets, i.e the pair of "[]" characters, are not part of the output. They are used to delimit the width of output.

    Format modifierLogger nameResult
    [%20.20logger] main.Name
    [           main.Name]
    [%-20.20logger] main.Name
    [main.Name           ]
    [%10.10logger] main.foo.foo.bar.Name
    [o.bar.Name]
    [%10.-10logger] main.foo.foo.bar.Name
    [main.foo.f]

     

     

    https://logback.qos.ch/manual/layouts.html

     


    spring boot中使用logback时一个一个配置文件示例:

    简单的:
    logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/base.xml" />
        <logger name="sample.logback" level="DEBUG" />
        <springProfile name="staging">
            <logger name="sample.logback" level="TRACE" />
        </springProfile>
    </configuration>

    include语句利用了spring boot中默认的logback中的一些配置。有些引用,可以不用定义名字为STDOUT和File的appender,不用定义Root节点
    在spring boot中使用logback,可以使用profile的设定。在不同的环境,使用不同的logger定义。
    如果使用maven的Filter插件,也可以在logback-spring.xml中引用相关变量,package后也会替换,因为maven Filter插件会替换classpath下相关文件中与之匹配的 标识位

    小结:就上面的需求,不建议使用spring-logback.xml配置文件,直接在application.yml(或application.properties)文件中定义即可
    示例:

    logging:
      level:
        org.springframework.web: ERROR
        com.demo: DEBUG
      pattern:
        console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
        file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
      file: logs/application.log

    如果要将error日志和info日志分开输出,就需要自定义appender

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <property name="CUSTOM_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n"/>
        <include resource="org/springframework/boot/logging/logback/base.xml"/>
    
        <appender name="ROLLING-FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logs/whatif.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- daily rollover -->
                <fileNamePattern>logs/whatif.%d{yyyy-MM-dd}.log</fileNamePattern>
                <!-- 保留30天的历史日志 -->
                <maxHistory>30</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            </encoder>
        </appender>
    
        <appender name="ROLLING-FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logs/whatif-warn.log</file>
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>WARN</level>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- daily rollover -->
                <fileNamePattern>logs/whatif-warn.%d{yyyy-MM-dd}.log</fileNamePattern>
                <!-- 保留30天的历史日志 -->
                <maxHistory>30</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>${CUSTOM_LOG_PATTERN}</pattern>
            </encoder>
        </appender>
    
        <logger name="com.tang" level="WARN">
            <appender-ref ref="ROLLING-FILE-WARN"/>
        </logger>
    
        <logger name="com.tang" level="INFO">
            <appender-ref ref="ROLLING-FILE-INFO"/>
        </logger>
    
        <root level="INFO">
            <appender-ref ref="ROLLING-FILE-INFO"/>
        </root>
    
    </configuration>

    上面的定义方法,会导致com.tang这个package的info及以上级别的log会在 ROLLING-FILE-INFO appender中打印两遍。即红色加粗的logger配置是不需要的,删除即可
    选定义root,再定义某个package下的log打印,是一种 “先禁止所有,再允许个别”的配置方法,即“除了xxx,其它的都要xxx做

     生成的日志文件:



     

    一:根节点<configuration>包含的属性:
    scan:
    当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
    scanPeriod:
    设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
    debug:
    当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
    例如:
    <configuration scan="true" scanPeriod="60 seconds" debug="false">  
          <!-- 其他配置省略-->  
    </configuration>  
    
    
    2.1设置上下文名称:<contextName>
    每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
    <configuration scan="true" scanPeriod="60 seconds" debug="false">  
          <contextName>myAppName</contextName>  
          <!-- 其他配置省略-->  
    </configuration>  
    
    2.2设置变量: <property>
    
    用来定义变量值的标签,<property> 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过<property>定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。
    
    例如使用<property>定义上下文名称,然后在<contentName>设置logger上下文时使用。
    
    <configuration scan="true" scanPeriod="60 seconds" debug="false">  
          <property name="APP_Name" value="myAppName" />   
          <contextName>${APP_Name}</contextName>  
          <!-- 其他配置省略-->  
    </configuration>   
    
    2.3设置loger:
    <loger>
    用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。
    name:
    用来指定受此loger约束的某一个包或者具体的某一个类。
    level:
    用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
    如果未设置此属性,那么当前loger将会继承上级的级别。
    addtivity:
    是否向上级loger传递打印信息。默认是true。会在Root中打印。如果root也引用了自定义logger中引用过的appender,则Root就会打印两份信息到appender
    <loger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。
    <root>
    也是<loger>元素,但是它是根loger。只有一个level属性,应为已经被命名为"root".
    level:
    用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。
    默认是DEBUG。
    <root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。

    spring boot默认配置的logback中的信息:

    default.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
    Default logback configuration provided for import, equivalent to the programmatic
    initialization performed by Boot
    -->
    
    <included>
        <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
        <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
        <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
        <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
        <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    
        <appender name="DEBUG_LEVEL_REMAPPER" class="org.springframework.boot.logging.logback.LevelRemappingAppender">
            <destinationLogger>org.springframework.boot</destinationLogger>
        </appender>
    
        <logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
        <logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
        <logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
        <logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
        <logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
        <logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
        <logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
        <logger name="org.springframework.boot.actuate.endpoint.jmx" additivity="false">
            <appender-ref ref="DEBUG_LEVEL_REMAPPER"/>
        </logger>
    </included>

    console-appender.xml 会引用default.xmk中定义的属性

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
    Console appender logback configuration provided for import, equivalent to the programmatic
    initialization performed by Boot
    -->
    
    <included>
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>${CONSOLE_LOG_PATTERN}</pattern>
                <charset>utf8</charset>
            </encoder>
        </appender>
    </included>

    file-appender.xml会引用default.xmk中定义的属性

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
    File appender logback configuration provided for import, equivalent to the programmatic
    initialization performed by Boot
    -->
    
    <included>
        <appender name="FILE"
            class="ch.qos.logback.core.rolling.RollingFileAppender">
            <encoder>
                <pattern>${FILE_LOG_PATTERN}</pattern>
            </encoder>
            <file>${LOG_FILE}</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
                <fileNamePattern>${LOG_FILE}.%i</fileNamePattern>
            </rollingPolicy>
            <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
                <MaxFileSize>10MB</MaxFileSize>
            </triggeringPolicy>
        </appender>
    </included>

    base.xml属于集上面于大成者,引用上面的default.xml,file-appender.xml,console-appender.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
    Base logback configuration provided for compatibility with Spring Boot 1.1
    -->
    
    <included>
        <include resource="org/springframework/boot/logging/logback/defaults.xml" />
        <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
        <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
        <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE" />
        </root>
    </included>

    因为spring boot 中已经定义,所以在logback-spring.xml中可以不用定义

    =====================================================finish=====================================================

    报错:

    java.lang.IllegalStateException: Logback configuration error detected: 
    ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [logs/log.%d{yyyy-MM-dd}_%i.log] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it.
    ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [logs/log-warn.%d{yyyy-MM-dd}_%i.log] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it.
    	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:152)
    	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:72)
    	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:50)
    	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:106)

    解决办法:
    将日志文件格式中的"%i"去掉。因为TimeBasedRollingPolicy是按日期分隔文件的,不需要这个%i,这个按文件大小分隔文件时才会使用。

    如果使用ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"策略时,就需要这个%i了

    eg:

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

    http://mcs.une.edu.au/doc/logback/manual/appenders.html

    Declaring project dependencies for logging

    Given Maven's transitive dependency rules, for "regular" projects (not libraries or frameworks) declaring logging dependencies can be accomplished with a single dependency declaration.

    LOGBACK-CLASSIC(需要slf4j-api和logback-classic)
    If you wish to use logback-classic as the underlying logging framework, all you need to do is to declare "ch.qos.logback:logback-classic" as a dependency in your pom.xml file as shown below. In addition to logback-classic-1.0.13.jar, this will pull slf4j-api-1.7.25.jar as well as logback-core-1.0.13.jar into your project. Note that explicitly declaring a dependency on logback-core-1.0.13 or slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifacts by virtue of Maven's "nearest definition" dependency mediation rule.

            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.0.13</version>
            </dependency>

    LOG4J(需要slf4j-log4j12这个jar)
    If you wish to use log4j as the underlying logging framework, all you need to do is to declare "org.slf4j:slf4j-log4j12" as a dependency in your pom.xml file as shown below. In addition to slf4j-log4j12-1.7.25.jar, this will pull slf4j-api-1.7.25.jar as well as log4j-1.2.17.jar into your project. Note that explicitly declaring a dependency on log4j-1.2.17.jar or slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifacts by virtue of Maven's "nearest definition" dependency mediation rule.

            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.25</version>
            </dependency>

    JAVA.UTIL.LOGGING(需要slf4j-jdk14这个jar)  
    If you wish to use java.util.logging as the underlying logging framework, all you need to do is to declare "org.slf4j:slf4j-jdk14" as a dependency in your pom.xml file as shown below. In addition to slf4j-jdk14-1.7.25.jar, this will pull slf4j-api-1.7.25.jar into your project. Note that explicitly declaring a dependency on slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifact by virtue of Maven's "nearest definition" dependency mediation rule.

            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-jdk14</artifactId>
                <version>1.7.25</version>
            </dependency>

    Binary com

    https://www.slf4j.org/manual.html 

    例如:%-4relative 表示,将输出从程序启动到创建日志记录的时间 进行左对齐 且最小宽度为4
    格式修饰符,与转换符共同使用:
    可选的格式修饰符位于“%”和转换符之间。
    第一个可选修饰符是左对齐 标志,符号是减号“-”;
    接着是可选的最小宽度 修饰符,用十进制数表示。如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格。如果字符大于最小宽度,字符永远不会被截断。最大宽度 修饰符,符号是点号"."后面加十进制数。如果字符大于最大宽度,则从前面截断。点符号“.”后面加减号“-”在加数字,表示从尾部截断。

    2016-07-04 07:37:29.801 [restartedMain] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$97204b4c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2016-07-04 07:37:30.482 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application startup failed
    java.lang.IllegalStateException: Logback configuration error detected: 
    ERROR in ch.qos.logback.core.rolling.RollingFileAppender[FILE] - Appender [FILE] failed to append. java.lang.NullPointerException
    ERROR in c.q.l.c.recovery.ResilientFileOutputStream@403418161 - IO failure while writing to file [demo.log] java.io.IOException: Stream Closed
    	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:151)
    	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:71)
    	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:49)
    	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:106)
    	at org.springframework.boot.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:301)
    	at org.springframework.boot.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:253)
    	at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:225)
    	at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:201)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:119)
    	at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111)
    	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:65)
    	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
    	at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:330)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180)
    	at com.DemoApplication.main(DemoApplication.java:17)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
    2016-07-04 07:37:30.486 [restartedMain] INFO  o.s.b.logging.ClasspathLoggingApplicationListener - Application failed to start with classpath: [file:/D:/workspace/demo/target/classes/, file:/D:/workspace/common/target/classes/]
    2016-07-04 07:51:03.820 [restartedMain] INFO  o.s.c.a.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1237898e: startup date [Mon Jul 04 07:51:03 CST 2016]; root of context hierarchy
    2016-07-04 07:51:04.568 [restartedMain] INFO  o.s.b.f.a.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    2016-07-04 07:51:04.623 [restartedMain] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$67d72258] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2016-07-04 07:51:05.312 [restartedMain] INFO  com.DemoApplication - No active profile set, falling back to default profiles: default

    出现上面报错时,很有可能是因为maxFileSize设置有不合理(一般是太小),文件rename太快,导致异常发生。
    如果想了解详解信息,可以查看logback的日志打印,可以把logback的debug打开:(1)

    <configuration debug="true"> 
    (2)
    <configuration>
      <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  

      ... the rest of the configuration file  
    </configuration>


    http://logback.qos.ch/manual/configuration.html

    http://jira.qos.ch/browse/LOGBACK-1054

    http://logback.qos.ch/dist/

    https://codeload.github.com/qos-ch/logback/zip/v_1.1.5 

    logback-sizeAndTime.xml(按照如下配置,经测试是可用的。idea中可能出现问题,但重启idea应用程序(是exit,不是close project)即可恢复正常)

    <configuration>
    
        <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
    
        <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>mylog.txt</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- rollover daily -->
                <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <!-- or whenever the file size reaches 100MB -->
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%msg%n</pattern>
            </encoder>
        </appender>
    
    
        <root level="debug">
            <appender-ref ref="ROLLING"/>
        </root>
    
    </configuration>

     logback.xml

    <configuration>
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n</Pattern>
            </encoder>
        </appender>
    
        <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>mylog.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- rollover daily -->
                <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <!-- or whenever the file size reaches 100MB -->
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n</pattern>
            </encoder>
        </appender>
    
    
        <root level="debug">
            <appender-ref ref="ROLLING"/>
            <appender-ref ref="STDOUT"/>
        </root>
    
    </configuration>

    Appenders accumulate

    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.

    Example: Duplicate appender (logback-examples/src/main/resources/chapters/configuration/duplicate.xml)

    View as .groovy

    <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. The appender named STDOUT is attached to two loggers, to root and tochapters.configuration. Since the root logger is the ancestor of all loggers and chapters.configuration is the parent of both chapters.configuration.MyApp3 and chapters.configuration.Foo, each logging request made with these two loggers will be output twice, once because STDOUT is attached to chapters.configuration and once because it is attached to root.

    Appender additivity is not intended as a trap for new users. It is quite a convenient logback feature. For instance, you can configure logging such that log messages appear on the console (for all loggers in the system) while messages only from some specific set of loggers flow into a specific appender.

    Example: Multiple appender (logback-examples/src/main/resources/chapters/configuration/restricted.xml)

    View as .groovy

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

      <logger name="chapters.configuration">
        <appender-ref ref="FILE" />
      </logger>

      <root level="debug">
        <appender-ref ref="STDOUT" />
      </root>
    </configuration>

    In this example, the console appender will log all the messages (for all loggers in the system) whereas only logging requests originating from the chapters.configuration logger and its children will go into the myApp.logfile.

    http://logback.qos.ch/manual/configuration.html

    or the shorter equivalent (DEPRECATED)

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
      <file>testFile.log</file>
      ...
      <!-- layout are assigned the type ch.qos.logback.classic.PatternLayout by default -->
      <layout>
        <pattern>%msg%n</pattern>
      </layout>
    </appender>  

    to (GOOD)

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
      <file>testFile.log</file>
      ...
      <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%msg%n</pattern>
      </encoder>
    </appender>  

    or the shorter equivalent (GOOD)

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
      <file>testFile.log</file>
      ...
      <!-- encoders are assigned the type
           ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
      <encoder>
        <pattern>%msg%n</pattern>
      </encoder>
    </appender>  

    http://logback.qos.ch/codes.html

    效果图:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- debug:打印logback内部日志信息,实时查看logback的运行状态,默认为false -->
    <!-- scan:配置文件如果发生改变,是否被重新加载,默认为true。 -->
    <!-- scanPeriod:设置检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒,默认的时间间隔为1分钟,默认为true。 -->
    <configuration debug="true" scan="true" scanPeriod="30 seconds">
        <contextName>SpringBoot Demo</contextName>
        <!-- 时间戳定义,timeReference:使用日志产生日期为时间基准 -->
        <timestamp key="byDay" datePattern="yyyy-MM-dd" timeReference="contextBirth"/>
    
        <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径,可以使用系统变量 -->
        <!-- <property name="LOG_HOME" value="${app.home}/log" /> -->
        <property name="LOG_HOME" value="log"/>
    
        <!-- appender很重要,一个配置文件会有多个appender -->
        <!-- ConsoleApperder意思是从console中打印出来 -->
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <!-- On Windows machines setting withJansi to true enables ANSI
             color code interpretation by the Jansi library. This requires
             org.fusesource.jansi:jansi:1.8 on the class path.  Note that
             Unix-based operating systems such as Linux and Mac OS X
             support ANSI color codes by default. 
    http://blog.csdn.net/u013613428/article/details/51499552
    -->
            <withJansi>true</withJansi>
            <!-- 过滤器,一个appender可以有多个 -->
            <!-- 阈值过滤,就是log行为级别过滤,debug及debug以上的信息会被打印出来 -->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>debug</level>
            </filter>
            <!-- encoders are assigned the type
                 ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
            <!-- encoder编码规则 -->
            <encoder>
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
                <!--<pattern>%d %contextName %msg%n</pattern>-->
                <!-- pattern模式 %d时间 %thread 线程名 %level行为级别 %logger logger名称 %method 方法名称 %message 调用方法的入参消息 -->
                <pattern>%-4d [%green(%thread)] %highlight(%-5level) %cyan(%logger).%-10method - %message%n</pattern>
            </encoder>
     <!-- 常用的Pattern变量,大家可打开该pattern进行输出观察 -->
            <!-- 
              <pattern>
                  %d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n
                  Logger: %logger
                  Class: %class
                  File: %file
                  Caller: %caller
                  Line: %line
                  Message: %m
                  Method: %M
                  Relative: %relative
                  Thread: %thread
                  Exception: %ex
                  xException: %xEx
                  nopException: %nopex
                  rException: %rEx
                  Marker: %marker
                  %n
                  
              </pattern>
               -->
        </appender>
    
        <!-- 按照每天生成日志文件 -->
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 日志输出文件 -->
            <file>${LOG_HOME}/LoggingBack.log</file>
            <!-- 追加日志到原文件结尾 -->
            <append>true</append>
            <!-- timebasedrollingpolicy:演示时间和大小为基础的日志文件归档 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定。 -->
                <!--可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。 -->
                <!--而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
                <!-- 文件滚动日期格式:每天:.YYYY-MM-dd(默认);每星期:.YYYY-ww;每月:.YYYY-MM -->
                <!-- 每隔半天:.YYYY-MM-dd-a;每小时:.YYYY-MM-dd-HH;每分钟:.YYYY-MM-dd-HH-mm -->
                <fileNamePattern>${LOG_HOME}/log-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <!-- 控制归档文件的最大数量的保存,删除旧的文件,默认单位天数 -->
                <maxHistory>7</maxHistory>
                <!-- 设置当前日志的文件的大小,决定日志翻滚 -->
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>

    <!-- encoders 作用是将logger事件转换成字节数组,并将字节数组写入到输出流-->

            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 这里添加一个过滤器 -->
            <file>${LOG_HOME}/LoggingBack-info.log</file>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_HOME}/LOG-INFO-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <maxHistory>7</maxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 这里添加一个过滤器 -->
            <file>${LOG_HOME}/LoggingBack-error.log</file>
            <!--<filter>标签。
            过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。
            返回DENY,日志将立即被抛弃不再经过其他过滤器;
            返回NEUTRAL,有序列表里的下个过滤器过接着处理日志;
            返回ACCEPT,日志会被立即处理,不再经过剩余过滤器。
            过滤器被添加到<Appender> 中,为<Appender> 添加一个或多个过滤器后,可以用任意条件对日志进行过滤。<Appender> 有多个过滤器时,按照配置顺序执行。
           -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_HOME}/LOG-ERROR-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <maxHistory>7</maxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <!-- 可以写多个日志文件appender,然后区分多个模块的日志 -->
        <appender name="BACKUP" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_HOME}/LoggingBack2.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_HOME}/LOG-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <maxHistory>7</maxHistory>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <!-- 为单独的包配置日志级别,若root的级别大于此级别, 此处级别也会输出
           应用场景:生产环境一般不会将日志级别设置为trace或debug,但是为详细的记录SQL语句的情况,
           可将hibernate的级别设置为debug,如此一来,日志文件中就会出现hibernate的debug级别日志,
           而其它包则会按root的级别输出日志
       -->
        <logger name="org.hibernate.SQL" level="DEBUG"/>
        <logger name="org.hibernate.jdbc" level="DEBUG"/>
        <logger name="org.springframework" level="DEBUG"/>
    
        <!-- 指定一个包,name必填,additivity选填:控制是否继承父类appender,默认true -->
        <!-- level选填,如果木有指定从最近的父类继承,顶级为root的级别 -->
        <logger name="com.wisely.ch7_7" additivity="true">
            <appender-ref ref="FILE"/>
            <appender-ref ref="FILE-INFO"/>
            <appender-ref ref="FILE-ERROR"/>
            <appender-ref ref="BACKUP"/>
        </logger>
        <!-- root, 只有在level及以上级别的日志会被输出 -->
        <!-- 例如: 当root level设置为INFO时, appender DEBUG中无法获取到DEBUG级别的日志事件, 则DEBUG日志信息也不会写入debug.log中. -->
        <root level="DEBUG">
            <appender-ref ref="STDOUT"/>
        </root>
    </configuration>  

    运用滚动策略与触发策略

    RollingFileAppender 继承 FileAppender,能够滚动记录文件。例如,RollingFileAppender能先记录到文件"log.txt",然后当符合某个条件时,变成记录到其他文件。 RollingFileAppender 有两个与之互动的重要子组件。第一个是RollingPolicy,负责滚动。第二个是 TriggeringPolicy,决定是否以及何时进行滚动。所以,RollingPolicy 负责"什么", TriggeringPolicy 负责"何时"。

    要想 RollingFileAppender 起作用,必须同时设置 RollingPolicy 和 TriggeringPolicy。不过,如果 RollingPolicy 也实现了 TriggeringPolicy 接口,那么只需要设置 RollingPolicy。

    FixedWindowRollingPolicy当发生滚动时,FixedWindowRollingPolicy 根据如下固定窗口(window)算法重命名文件。 选项"fileNamePattern"代表归档(滚动)记录文件的文件名模式。该选项是必需的,且必需在模式的某处包含标志"%i"。如示例3中的MyApp3-RollingFixedWindow.xml 。

    TimeBasedRollingPolicy 或许是最受流行的滚动策略。它根据时间来制定滚动策略,例如根据日或月。TimeBasedRollingPolicy 既负责滚动也负责触发滚动。实际上,TimeBasedRollingPolicy 同时实现了 RollingPolicy 接口和 TriggeringPolicy 接口。和 FixedWindowRollingPolicy一样,TimeBasedRollingPolicy 也支持自动压缩文件。如果"fileNamePattern"选项以".gz"或".zip"结尾,就表示需要压缩。如示例3中的MyApp3-RollingTimeBased.xml 。

    SizeAndTimeBasedFNATP按照日期进行归档的同时限制每个记录文件的大小,特别是当后处理工具对记录文件大小有限制时。Logback 为此提供了 SizeAndTimeBasedFNATP,它是TimeBasedRollingPolicy 的子组件,FNATP 代表"FNATP stands for File Naming And Triggering Policy"。 下面的例子MyApp3-sizeAndTime.xml演示了基于大小和时间的记录文件归档。

    layout格式修饰符

    如给定的一个格式:%-5p [%t]: %m%n中,并没有明确的分隔转换字符和普通文本的字符存在。PatternLayout能自己区分普通文本和转换字符。其中%-5p是日志的调用级别。事件是左对齐的,5个字符宽度。

    格式修饰符,放在%和转换符之间。 第一个可选的格式修饰符是左对齐(-);第二个可选的格式修饰符是字段最小宽度。一个整数。表示输出的最小字符数。如果数据未达到指定最小大小,那么它将以左填充(默认)或者右填充方式(左对齐情况下只能使用右填充了)。用空格填充,直到达到最小宽度。如果大于指定最小宽度,不会被截断 。当然可以指定最大字符数,使用.符号加数字表示最大字符数。如果大于指定长度,多余的字符会被删除。它是从前面删除,而不是从后面删除的。如最大字符是8个,数据有10个字符,那么前面两个字符会被删除。 

    %20c 右对齐,最少20字符,没有左边用空格填充 

    %-20c 左对齐,最少20字符,没有右边用空格填充 

    %.30c 右对齐,最多30字符,超过左边的截取掉 

    %20.30c 右对齐,最少20字符,最多30字符,填充或截取规则略

    %-20.30c 左对齐,最少20字符,最多30字符,填充或截取规则略 

    Appender累积

    默认情况下,appender 是可累积的:logger 会把记录输出到它自身的 appender 和它所有祖先的 appender。因此,把同一 appender 关联到多个 logger 会导致重复输出,如下面的配置文件会导致重复的输出:

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

    输出结果如下:

    20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Entering application.

    20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Entering application.

    20:53:29.328 [main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!

    20:53:29.328 [main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!

    20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.

    20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.

    覆盖默认的累积行为

    如果你觉得默认的累积行为不合适,可以设置叠加性标识为 false 以关闭它。 这样的话,logger 树里的某个分支可以输出到与其他 logger 不同的 appender。

    示例:叠加性标识

    <configuration>

        …………

        <logger name="com.ttpod.chapters.configuration.Foo" additivity="false">

            <appender-ref ref="FILE" />

        </logger>

        <root level="debug">

            <appender-ref ref="STDOUT" />

        </root>

    </configuration>

    输出结果:

    Entering application.

    Exiting application.

    此例中,logger"chapters.configuration.Foo"关联 appender"FILE",它的叠加性标记为false,这样它的记录输出仅会被发送到 appender"FILE",不会被发送到更高logger 等级关联的 appender。其他 logger 不受此影响。 用 additivityFlag.xml 配置 MyApp3 , 运 行 后 , 控 制 台 上 由 输 出由"chapters.configuration.MyApp3"产生的记录。而 logger" chapters.configuration.Foo"将且仅仅将输出到文件 foo.log。

    http://www.cnblogs.com/luowei010101/archive/2012/01/04/2312438.html

    When you specify the MaxFileSize to be used by the SizeBasedRollingPolicy, logback expects a rather precise format:

    • The number has to be an integer
    • You can add 'KB', 'MB' or 'GB' after the number.

    Here are some correct values: 500KB, 15MB, 2GB.

    No TriggeringPolicy was set for the RollingFileAppender.

    The RollingFileAppender must be set up with a TriggeringPolicy. It permits the Appender to know when the rollover must be activated.

    To find more information about TriggeringPolicy objects, please read the following javadocs:

    Please note that the TimeBasedRollingPolicy is a TriggeringPolicy and and RollingPolicy at the same time.

    Missing integer token, that is %i, in FileNamePattern [...].

    The %i conversion token is mandatory for size and time based archiving. In case the %i token is missing,SizeAndTimeBasedFNATP attached to RollingFileAppender will detect the omission and will not start.

    http://logback.qos.ch/codes.html

    SizeBasedTriggeringPolicy

    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 KBMB and respectively GB. For example, 50000005000KB5MB and 2GB are all valid values, with the first three being equivalent.

    Here is a sample configuration with a RollingFileAppender in conjunction with SizeBasedTriggeringPolicy triggering rollover when the log file reaches 5MB in size.

    Example: Sample configuration of a RollingFileAppender using a SizeBasedTriggeringPolicy (logback-examples/src/main/resources/chapters/appenders/conf/logback-RollingSizeBased.xml)

    <configuration>
      <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>test.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
          <fileNamePattern>test.%i.log.zip</fileNamePattern>
          <minIndex>1</minIndex>
          <maxIndex>3</maxIndex>
        </rollingPolicy>
    
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
          <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
          <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
      </appender>
            
      <root level="DEBUG">
        <appender-ref ref="FILE" />
      </root>
    </configuration>

    file:///D:/jar/logback-1.1.7/docs/manual/appenders.html#TimeBasedRollingPolicy

    https://yq.aliyun.com/articles/25530


    26.2 Console output

    The default log configuration will echo messages to the console as they are written. By default ERRORWARN and INFO level messages are logged. You can also enable a “debug” mode by starting your application with a --debug flag.

    $ java -jar myapp.jar --debug
    [Note]

    you can also specify debug=true in your application.properties.

    When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate and Spring) are configured to output more information. Enabling the debug mode does not configure your application log all messages with DEBUG level.

    26.2.1 Color-coded output

    If your terminal supports ANSI, color output will be used to aid readability. You can set spring.output.ansi.enabled to a supported value to override the auto detection.

    Color coding is configured using the %clr conversion word. In its simplest form the converter will color the output according to the log level, for example:

    %clr(%5p)

    The mapping of log level to a color is as follows:

    LevelColor

    FATAL

    Red

    ERROR

    Red

    WARN

    Yellow

    INFO

    Green

    DEBUG

    Green

    TRACE

    Green

    Alternatively, you can specify the color or style that should be used by providing it as an option to the conversion. For example, to make the text yellow:

    %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

    The following colors and styles are supported:

    • blue
    • cyan
    • faint
    • green
    • magenta
    • red
    • yellow

    26.5 Custom log configuration

    The various logging systems can be activated by including the appropriate libraries on the classpath, and further customized by providing a suitable configuration file in the root of the classpath, or in a location specified by the Spring Environment property logging.config.

    [Note]

    Since logging is initialized before the ApplicationContext is created, it isn’t possible to control logging from @PropertySources in Spring@Configuration files. System properties and the conventional Spring Boot external configuration files work just fine.)

    Depending on your logging system, the following files will be loaded:

    Logging SystemCustomization

    Logback

    logback-spring.xmllogback-spring.groovylogback.xml or logback.groovy

    Log4j

    log4j-spring.propertieslog4j-spring.xmllog4j.properties or log4j.xml

    Log4j2

    log4j2-spring.xml or log4j2.xml

    JDK (Java Util Logging)

    logging.properties

    [Note]

    When possible we recommend that you use the -spring variants for your logging configuration (for example logback-spring.xml rather thanlogback.xml). If you use standard configuration locations, Spring cannot completely control log initialization.

    [Warning]

    There are known classloading issues with Java Util Logging that cause problems when running from an ‘executable jar’. We recommend that you avoid it if at all possible.

    To help with the customization some other properties are transferred from the Spring Environment to System properties:

    Spring EnvironmentSystem PropertyComments

    logging.exception-conversion-word

    LOG_EXCEPTION_CONVERSION_WORD

    The conversion word that’s used when logging exceptions.

    logging.file

    LOG_FILE

    Used in default log configuration if defined.

    logging.path

    LOG_PATH

    Used in default log configuration if defined.

    logging.pattern.console

    CONSOLE_LOG_PATTERN

    The log pattern to use on the console (stdout). (Not supported with JDK logger.)

    logging.pattern.file

    FILE_LOG_PATTERN

    The log pattern to use in a file (if LOG_FILE enabled). (Not supported with JDK logger.)

    logging.pattern.level

    LOG_LEVEL_PATTERN

    The format to use to render the log level (default %5p). (Thelogging.pattern.level form is only supported by Logback.)

    PID

    PID

    The current process ID (discovered if possible and when not already defined as an OS environment variable).

    All the logging systems supported can consult System properties when parsing their configuration files. See the default configurations in spring-boot.jar for examples.

    [Tip]

    If you want to use a placeholder in a logging property, you should use Spring Boot’s syntax and not the syntax of the underlying framework. Notably, if you’re using Logback, you should use : as the delimiter between a property name and its default value and not :-.

    http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html


    默认情况下,Spring Boot的日志是输出到控制台的,不写入任何日志文件。
    要让Spring Boot输出日志文件,最简单的方式是在application.properties配置文件中配置logging.path键值,如下:(日志文件为spring.log)
    logging.path=/var/log
    第二种方法是在application.properties配置文件中配置logging.file键值,如下:
    logging.file=/var/log/myapp.log
    这两种配置方法适用于开发阶段,对于部署则存在一定的问题。比如部署到不同的环境,可能就存在需要修改application.properties文件的情况,这就意味着需要重新打包,再次部署,显得不便捷。
    有鉴于此,Spring Boot提供了一种覆写application.properties配置文件中键值的方法,在命令行通过指定参数来实现覆写——在运行时把命令行参数当作标准的系统属性,如下:
    java -jar -Dlogging.path=/tmp myapp.jar
    最后,还可以在命令行调用Spring Boot的Maven插件时覆写这个值。但是,直接使用系统属性对于插件方式是无效的。需要使用run.jvmArguments参数来指定系统属性,设置想要的值:
    mvn spring-boot:run -Drun.jvmArguments="-Dlogging.path=/tmp"
    一切都变得很完美了!

    http://m.blog.csdn.net/article/details?id=50737925



    <appender>:
    <appender>是<configuration>的子节点,是负责写日志的组件。
    <appender>有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。

    1.ConsoleAppender:
    把日志添加到控制台,有以下子节点:
    <encoder>:对日志进行格式化。(具体参数稍后讲解 )
    <target>:字符串 System.out 或者 System.err ,默认 System.out ;

    rollingPolicy:

    TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:

    <fileNamePattern>:

    必要节点,包含文件名及“%d”转换符, “%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}。如果直接使用 %d,默认格式是 yyyy-MM-dd。RollingFileAppender 的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变;如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“”会被当做目录分隔符。

    http://blog.csdn.net/haidage/article/details/6794529  good

    logback-spring.xml

    Logback的核心对象:Logger、Appender、Layout

    Logback主要建立于Logger、Appender 和 Layout 这三个类之上。

    Logger:日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。Logger对象一般多定义为静态常量

    Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 PostreSQL、Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。

    Layout:负责把事件转换成字符串,格式化的日志信息的输出。具体的Layout通配符,可以直接查看帮助文档。

    3、Level 有效级别

    Logger可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN和ERROR,定义于ch.qos.logback.classic.Level类。程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。如果设置级别为INFO,则优先级高于等于INFO级别(如:INFO、 WARN、ERROR)的日志信息将可以被输出,小于该级别的如DEBUG将不会被输出。为确保所有logger都能够最终继承一个级别,根logger总是有级别,默认情况下,这个级别是DEBUG


    4、 三值逻辑
    Logback的过滤器基于三值逻辑(ternary logic),允许把它们组装或成链,从而组成任意的复合过滤策略。过滤器很大程度上受到Linux的iptables启发。这里的所谓三值逻辑是说,过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。
    如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;
    如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;
    如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。

    5、Filter 过滤器
    Logback-classic提供两种类型的过滤器:常规过滤器和TuroboFilter过滤器。Logback整体流程:Logger 产生日志信息;Layout修饰这条msg的显示格式;Filter过滤显示的内容;Appender具体的显示,即保存这日志信息的地方。

    Java项目中一般都会应用比如struts、spring、hibernate等开源框架,而这些框架很多是应用log4j记录日志的,所以我们考虑用log4j + slf4j + logback 。这样我们需要导入log4j-over-slf4j-1.6.4.jar 、logback-classic-1.0.1.jar 、logback-core-1.0.1.jar 、slf4j-api-1.6.4.jar ,如果你要用到EvaluatorFilter过滤器来过滤日志Msg中的特殊字符需要导入其依赖包 janino-2.3.2.jar

    http://www.cnblogs.com/yongze103/archive/2012/05/05/2484753.html

    Coloring

    Grouping by parentheses as explained above allows coloring of sub-patterns. As of version 1.0.5, PatternLayout recognizes "%black", "%red", "%green","%yellow","%blue", "%magenta","%cyan", "%white", "%gray", "%boldRed","%boldGreen", "%boldYellow", "%boldBlue", "%boldMagenta""%boldCyan", "%boldWhite" and "%highlight" as conversion words. These conversion words are intended to contain a sub-pattern. Any sub-pattern enclosed by a coloring word will be output in the specified color.

    Below is a configuration file illustrating coloring. Note the %cyan conversion specifier enclosing "%logger{15}". This will output the logger name abbreviated to 15 characters in cyan. The %highlight conversion specifier prints its sub-pattern in bold-red for events of level ERROR, in red for WARN, in BLUE for INFO, and in the default color for other levels.

    Example: Highlighting levels (logback-examples/src/main/resources/chapters/layouts/highlighted.xml) View as .groovy
    <configuration debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- On Windows machines setting withJansi to true enables ANSI
    color code interpretation by the Jansi library. This requires
    org.fusesource.jansi:jansi:1.8 on the class path. Note that
    Unix-based operating systems such as Linux and Mac OS X
    support ANSI color codes by default. -->
    <withJansi>true</withJansi>
    <encoder>
    <pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
    </encoder>
    </appender>
    <root level="DEBUG">
    <appender-ref ref="STDOUT" />
    </root>
    </configuration>
    Here is the corresponding output:

    It takes very few lines of code to create a coloring conversion word. The section entitled creating a custom conversion specifier discusses the steps necessary for registering a conversion word in your configuration file.

    http://logback.qos.ch/manual/layouts.html

    SizeBasedTriggeringPolicy

    sizebasedtriggeringpolicy 监控当前使用的日志文件的大小。当文件大于指定的大小时,将会通过rollingfileappender触发滚动事件。它只接受一个属性,maxfilesize。默认值是10MB。maxfilesize属性可以以KB,MB,GB作为单位,如5000000.5000KB,5MB ,5GB,前面三个值是相等的。举例如下,文件大小设置为5MB。
    <configuration>
      <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>test.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
          <fileNamePattern>test.%i.log.zip</fileNamePattern>
          <minIndex>1</minIndex>
          <maxIndex>3</maxIndex>
        </rollingPolicy>
    
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
          <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
          <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
      </appender>
            
      <root level="DEBUG">
        <appender-ref ref="FILE" />
      </root>
    </configuration>

    http://blog.csdn.net/huozhonbin/article/details/12560617

    下载对于的JAR 包:
    http://logback.qos.ch/
    logback-access-1.1.2.jar
    logback-classic-1.1.2.jar
    logback-core-1.1.2.jar

    http://www.slf4j.org/
    slf4j-api-1.7.10.jar
    mvaven , 配置如下:

    <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.3</version>
    </dependency><dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>1.1.3</version>
    </dependency><dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.1.3</version>
    </dependency><dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.12</version>
    </dependency>


    将logback.xml 放置到web工程的classes目路下,运行项目
    http://www.cnblogs.com/dragonflyyi/p/4245250.html

    LogBack可以通过编程式或以XML、Groovy格式配置,原来使用log4j的用户可以通过属性转换器将log4j.properties转换成logback.xml文件。我在使用这个转换器的时候,能转换成功,但是在Web-App中日志输出的有点小问题,后来就自己写logback.xml文件,LogBack读取配置或属性文件的步骤:
    1. LogBack在类路径下尝试查找logback.groovy的文件。
    2. 如果logback.groovy没有找到,就在类路径下查找logback-test.xml文件。
    3. 若logback-test.xml文件没有找到,就会在类路径下查找logback.xml文件(自己使用的就是这种方式,将logback.xml配置文件放到类路径下)。
    4. 如果都找不到,LogBack就会使用BasicConfigurator启动默认配置,该配置会将日志输出到控制上。

    http://blog.csdn.net/wangdongsong1229/article/details/17463113

    Code:

    package com.wisely.ch7_7;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    
    @RestController
    @SpringBootApplication
    public class Ch77Application {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(Ch77Application.class);
    
        @RequestMapping(value = "/search", produces = {MediaType.APPLICATION_JSON_VALUE})
        public Person search(String personName) {
            LOGGER.info("info level");
            LOGGER.error("error level");
            LOGGER.warn("warn level");
            LOGGER.debug("debug level");
            LOGGER.info("info level");
            return new Person(personName, 32, "shanghai");
        }
    
        public static void main(String[] args) {
            SpringApplication.run(Ch77Application.class, args);
        }
    }
    package com.wisely.ch7_7;
    
    public class Person {
        private String name;
        private Integer age;
        private String address;
        
        
        public Person() {
            super();
        }
        public Person(String name, Integer age, String address) {
            super();
            this.name = name;
            this.age = age;
            this.address = address;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
    }
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.wisely</groupId>
        <artifactId>ch7_7</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>ch7_7</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.3.0.M1</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
        
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
        
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </pluginRepository>
            <pluginRepository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    
    
    </project>

    一、logback的介绍

    Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。 Logback是要与SLF4J结合起来用两个组件的官方网站如下:

    logback的官方网站: http://logback.qos.ch

    SLF4J的官方网站:http://www.slf4j.org

    本文章用到的组件如下:请自行到官方网站下载!

    logback-access-1.0.0.jar

    logback-classic-1.0.0.jar

    logback-core-1.0.0.jar

    slf4j-api-1.6.0.jar

    maven配置

    <dependency>  
           <groupId>ch.qos.logback</groupId>  
           <artifactId>logback-classic</artifactId>  
        <version>1.0.11</version>  
    </dependency>  

    这样依赖包全部自动下载了!

    二、logback取代 log4j的理由:

    Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点:

    1、更快的实现 Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。

    2、非常充分的测试 Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。在作者的观点,这是简单重要的原因选择logback而不是log4j。

    3、Logback-classic非常自然实现了SLF4j Logback-classic实现了 SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了SLF4J, 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。

    4、非常充分的文档 官方网站有两百多页的文档。

    5、自动重新加载配置文件 当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。

    6、Lilith Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。

    7、谨慎的模式和非常友好的恢复 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。

    8、配置文件可以处理不同的情况 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。

    9、Filters(过滤器) 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需 加4行XML配置。可以参考MDCFIlter 。

    10、SiftingAppender(一个非常多功能的Appender) 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。

    11、自动压缩已经打出来的log RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。

    12、堆栈树带有包版本 Logback在打出堆栈树日志时,会带上包的数据。

    13、自动去除旧的日志文件 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory 12,那那些log文件超过12个月的都会被自动移除。

    总之,logback比log4j太优秀了,让我们的应用全部建立logback上吧 !

    、Logback的配置介绍

    1、Logger、appender及layout

    Logger作为日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。

    Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 PostreSQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。

    Layout 负责把事件转换成字符串,格式化的日志信息的输出。

    2、logger context

    各个logger 都被关联到一个 LoggerContext,LoggerContext负责制造logger,也负责以树结构排列各 logger。其他所有logger也通过org.slf4j.LoggerFactory 类的静态方法getLogger取得。 getLogger方法以 logger 名称为参数。用同一名字调用LoggerFactory.getLogger 方法所得到的永远都是同一个logger对象的引用。

    3、有效级别及级别的继承

    Logger 可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定义于 ch.qos.logback.classic.Level类。如果 logger没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。

    4、打印方法与基本的选择规则

    打印方法决定记录请求的级别。例如,如果 L 是一个 logger 实例,那么,语句 L.info("..")是一条级别为 INFO 的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger的有效级别为 q,只有则当 p>=q时,该请求才会被执行。

    该规则是 logback 的核心。级别排序为: TRACE < DEBUG < INFO < WARN < ERROR。 

    http://www.cnblogs.com/yuanermen/archive/2012/02/13/2348942.html

    LogBack入门实践
    一、简介

    LogBack是一个日志框架,它是Log4j作者Ceki的又一个日志组件。

    LogBack,Slf4j,Log4j之间的关系

        slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog...);

        LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。

        LogBack官方建议配合Slf4j使用,这样可以灵活地替换底层日志框架。

    LogBack的结构

    LogBack分为3个组件,logback-core, logback-classic 和 logback-access。

    其中logback-core提供了LogBack的核心功能,是另外两个组件的基础。

    logback-classic则实现了Slf4j的API,所以当想配合Slf4j使用时,则需要引入这个包。

    logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口。

    Log的行为级别

    OFF、

    FATAL、

    ERROR、

    WARN、

    INFO、

    DEBUG、

    ALL

    从下向上,当选择了其中一个级别,则该级别向下的行为是不会被打印出来。

    举个例子,当选择了INFO级别,则INFO以下的行为则不会被打印出来。

    二、slf4j与logback结合使用原理

    我们从java代码最简单的获取logger开始

    Logger logger = LoggerFactory.getLogger(xxx.class.getName());

    LoggerFactory是slf4j的日志工厂,获取logger方法就来自这里。

    public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }

    这个方法里面有分为两个过程。

    第一个过程是获取ILoggerFactory,就是真正的日志工厂。

    第二个过程就是从真正的日志工厂中获取logger。

    第一个过程又分为三个部分。

    第一个部分加载org/slf4j/impl/StaticLoggerBinder.class文件

    paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);//STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"
    第二部分随机选取一个StaticLoggerBinder.class来创建一个单例

    当项目中存在多个StaticLoggerBinder.class文件时,运行项目会出现以下日志:

    SLF4J: Class path contains multiple SLF4J bindings.
    SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
    SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
    SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
    SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

    最后会随机选择一个StaticLoggerBinder.class来创建一个单例

    StaticLoggerBinder.getSingleton()

    第三部分返回一个ILoggerFactory实例

    StaticLoggerBinder.getSingleton().getLoggerFactory();

    所以slf4j与其他实际的日志框架的集成jar包中,都会含有这样的一个org/slf4j/impl/StaticLoggerBinder.class类文件,并且提供一个ILoggerFactory的实现。

    第二个过程就是每一个和slf4j集成的日志框架中实现ILoggerFactory方法getLogger()的实例所做的事了。

    三、slf4j与logback结合使用实践

    第一步引入jar包

    slf4j-api

    logback-core

    logback-classic(含有对slf4j的集成包)

    <!-- slf4j-api -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>
    <!-- logback -->
    <dependency> 
        <groupId>ch.qos.logback</groupId> 
        <artifactId>logback-core</artifactId> 
        <version>1.1.3</version> 
    </dependency> 
    <dependency> 
        <groupId>ch.qos.logback</groupId> 
        <artifactId>logback-classic</artifactId> 
        <version>1.1.3</version> 
    </dependency>

    第二步编写简单的logback配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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>
      <root level="DEBUG">          
        <appender-ref ref="STDOUT" />
      </root>  
    </configuration>

    文件位置位于src/main/resources下,名字默认为logback.xml

    当然,logback也支持groovy格式的配置文件,如果你会用那更好。

    接下来,自己随便写一个类调用一下logger

    package log.test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    /**
     * @author jiangmitiao
     * @date 2016/3/24
     * @description TODO
     */
    public class Foo {
        public static void doIt(){
            Logger logger = LoggerFactory.getLogger(Foo.class.getName());
            logger.debug("let`s do it");
        }
    }
    package log.test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class MyApp1 {
        public static void main(String[] args) {
            Logger logger = LoggerFactory.getLogger(MyApp1.class.getName());
            logger.info("before");
            Foo.doIt();
            logger.info("after");
            try {
                int i = 10 / 0;
            } catch (Exception e) {
                logger.error("errorTest",e);
            }
        }
    }

    最后的结果是:

    16:22:13.459 [main] INFO  log.test.MyApp1 - before
    16:22:13.463 [main] DEBUG log.test.Foo - let`s do it
    16:22:13.463 [main] INFO  log.test.MyApp1 - after
    16:22:13.466 [main] ERROR log.test.MyApp1 - errorTest
    java.lang.ArithmeticException: / by zero
    at log.test.MyApp1.main(MyApp1.java:19) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na]

    配置规则简述

    上边这么简单的配置当然是没有用的,下面这个就能够说明logback配置文件的编写规则了。

    <!-- scan的意思是是否扫描  seconds是说多长时间扫描一次 -->
    <configuration scan="true" scanPeriod="30 seconds" debug="false" packagingData="true">
        <!-- 项目名称 -->
        <contextName>myApp1 contextName</contextName>
        <!-- 属性 -->
        <property name="USER_HOME" value="./log"/>
        <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
           the key "bySecond" into the logger context. This value will be
           available to all subsequent configuration elements. -->
        <timestamp key="bySecond" datePattern="yyyyMMdd" timeReference="contextBirth"/>
        <!-- appender很重要,一个配置文件会有多个appender -->
        <!-- ConsoleApperder意思是从console中打印出来 -->
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <!-- 过滤器,一个appender可以有多个 -->
            <!-- 阈值过滤,就是log行为级别过滤,debug及debug以上的信息会被打印出来 -->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>debug</level>
            </filter>
            <!-- encoders are assigned the type
                 ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
            <!-- encoder编码规则 -->
            <encoder>
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
                <!--<pattern>%d %contextName %msg%n</pattern>-->
                <!-- pattern模式 %d时间 %thread 线程名 %level行为级别 %logger logger名称 %method 方法名称 %message 调用方法的入参消息 -->
                <pattern>%-4d [%thread] %highlight%-5level %cyan%logger.%-10method - %message%n</pattern>
            </encoder>
        </appender>
        <!-- FileAppender 输出到文件 -->
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <!-- 文件存放位置 %{xxx} 就是之前定义的属性xxx -->
            <file>${USER_HOME}/myApp1log-${bySecond}.log</file>
            <encoder>
                <!-- %date和%d是一个意思 %file是所在文件 %line是所在行 -->
                <pattern>%date %level [%thread] %logger{30} [%file:%line] %msg%n</pattern>
            </encoder>
        </appender>
        <!-- 输出到HTML格式的文件 -->
        <appender name="HTMLFILE" class="ch.qos.logback.core.FileAppender">
            <!-- 过滤器,这个过滤器是行为过滤器,直接过滤掉了除debug外所有的行为信息 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>debug</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <!-- HTML输出格式 可以和上边差不多 -->
                <layout class="ch.qos.logback.classic.html.HTMLLayout">
                    <pattern>%relative%thread%mdc%level%logger%msg</pattern>
                </layout>
            </encoder>
            <file>${USER_HOME}/test.html</file>
        </appender>
        <!-- 滚动日志文件,这个比较常用 -->
        <appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 当project等于true的时候file就不会起效果-->
            <prudent>true</prudent>
            <!--<file>${USER_HOME}/logFile.log</file>-->
            <!-- 按天新建log日志 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- daily rollover -->
                <fileNamePattern>${USER_HOME}/logFile.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
                <!-- 保留30天的历史日志 -->
                <maxHistory>30</maxHistory>
                <!-- 基于大小和时间,这个可以有,可以没有 -->
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <!-- or whenever the file size reaches 100MB -->
                    <!-- 当一个日志大小大于10KB,则换一个新的日志。日志名的%i从0开始,自动递增 -->
                    <maxFileSize>10KB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <encoder>
            <!-- %ex就是指抛出的异常,full是显示全部,如果在{}中写入数字,则表示展示多少行 -->
                <pattern>%-4date [%thread] %-5level %logger{35} - %msg%n%ex{full, DISPLAY_EX_EVAL}</pattern>
            </encoder>
        </appender>
        <!-- 重点来了,上边都是appender输出源。这里开始就是looger了 -->
        <!-- name意思是这个logger管的哪一片,像下面这个管的就是log/test包下的所有文件 level是只展示什么行为信息级别以上的,类似阈值过滤器 additivity表示是否再抛出事件,就是说如果有一个logger的name是log,如果这个属性是true,另一个logger就会在这个logger处理完后接着继续处理 -->
        <logger name="log.test" level="INFO" additivity="false">
            <!-- 连接输出源,也就是上边那几个输出源,你可以随便选几个appender -->
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ROLLINGFILE"/>
            <appender-ref ref="HTMLFILE"/>
        </logger>
        <!-- 这个logger详细到了类 -->
        <logger name="log.test.Foo" level="debug" additivity="false">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ROLLINGFILE"/>
            <appender-ref ref="HTMLFILE"/>
        </logger>
        <!-- Strictly speaking, the level attribute is not necessary since -->
        <!-- the level of the root level is set to DEBUG by default.       -->
        <!-- 这就是上边logger没有管到的情况下 root默认接管所有logger -->
        <root level="debug">
            <appender-ref ref="STDOUT"/>
        </root>
    </configuration>

    四、过滤器的一些疑问

    Logback的过滤器基于三值逻辑(ternary logic),允许把它们组装或成链,从而组成任意的复合过滤策略。过滤器很大程度上受到Linux的iptables启发。这里的所谓三值逻辑是说,过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。

    如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;

    如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;

    如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。

    写一个简单的过滤器大家就明白了。

    package log.test;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import ch.qos.logback.core.filter.Filter;
    import ch.qos.logback.core.spi.FilterReply;
    public class SampleFilter extends Filter<ILoggingEvent> {
      @Override
      public FilterReply decide(ILoggingEvent event) {    
        if (event.getMessage().contains("let")) {
          return FilterReply.ACCEPT;
        } else {
          return FilterReply.DENY;
        }
      }
    }

    可以选择任意几个输出源加入这个filter

    <filter class="log.test.SampleFilter" />

    最后的结果是,加入该filter的输出源只能输出Foo.doIt()中的日志了。

    五、总结

    logback配置比较简单,官网手册也是比较容易看懂的。除上边几种输出源之外,logback还支持输出到远程套接字服务器、 MySQL、 PostreSQL、Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等等。

    第一次学习log方面的知识,如有错误,请不吝赐教。

    相关资源:

    http://logback.qos.ch/manual/index.html

    http://www.cnblogs.com/mailingfeng/p/3499436.html

    http://yuri-liuyu.iteye.com/blog/954038

    http://www.cnblogs.com/yongze103/archive/2012/05/05/2484753.html

    http://blog.csdn.net/haidage/article/details/6794509

    http://my.oschina.net/jiangmitiao/blog/647902

    Spring Boot Logback应用日志

    SLF4J与Logback简介

    SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。Java日志框架众多——常用的有java.util.logginglog4jlogbackcommons-logging, Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的——它提供了各类日志框架的binding。

    Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。

    Spring Boot Logging

    Spring Boot实现了一套日志系统——它能够根据类路径上的内容来决定使用哪一种日志框架,logback是最优先的选择。配置了logback.xml可以利用Spring Boot提供的默认日志配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/base.xml"/>
        <logger name="org.springframework.web" level="DEBUG"/>
    </configuration>

    这样就定义了一个<logger>捕获org.springframework.web的日志,日志级别是DEBUGbase.xml内容如下:

    <included>
        <include resource="org/springframework/boot/logging/logback/defaults.xml" />
        <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
        <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
        <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE" />
        </root>
    </included>

    Spring Boot的日志系统预先定义了一些系统变量:

    • ${PID},当前进程ID
    • ${LOG_FILE},Spring Boot配置文件中logging.file的值
    • ${LOG_PATH}, Spring Boot配置文件中logging.path的值

    同时默认情况下包含另个appender——一个是控制台,一个是文件,分别定义在console-appender.xmlfile-appender.xml中。同时对于应用的日志级别也可以通过application.properties进行定义:

    logging.level.org.springframework.web=DEBUG
    logging.level.org.hibernate=ERROR

    这等价于在logback.xml配置appender的日志级别。

    ConsoleAppender

    Logback使用appender来定义日志输出,在开发过程中最常用的是将日志输出到控制台:

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
        <Pattern>.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n</Pattern>
      </encoder>
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>TRACE</level>
      </filter>
    </appender>

    <encoder>表示对日志进行编码:

    • %d{HH:mm:ss.SSS}——日志输出时间
    • %thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
    • %-5level——日志级别,并且使用5个字符靠左对齐
    • %logger{36}——日志输出者的名字
    • %msg——日志消息
    • %n——平台的换行符

    在这种格式下一条日志的输出结果如下:

    0:12:51.012 [qtp231719230-45] DEBUG o.c.d.r.util.LoggingResponseFilter

    RollingFileAppender

    另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender用于切分文件日志:

    <appender name="dailyRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <File>/data/log/app.log</File>
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- daily rollover -->
        <FileNamePattern>rest-demo.%d{yyyy-MM-dd}.log</FileNamePattern>
        <!-- keep 30 days' worth of history -->
        <maxHistory>30</maxHistory>         
      </rollingPolicy>
      <encoder>
        <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n</Pattern>
      </encoder>        
    </appender>

    其中重要的是rollingPolicy的定义,上例中<FileNamePattern>rest-demo.%d{yyyy-MM-dd}.log</FileNamePattern>定义了日志的切分方式——把每一天的日志归档到一个文件中,<maxHistory>30</maxHistory>表示只保留最近30天的日志,以防止日志填满整个磁盘空间。同理,可以使用%d{yyyy-MM-dd_HH-mm}来定义精确到分的日志切分方式。

    Sentry

    Sentry是一个统一的日志跟踪平台,在传统的日志管理中,都是在服务器上通过tailvim等工具查看日志,并且不同的日志位置也个不相同,而Sentry则是将这些日志(主要是错误日志)通过统一的接口收集起来,并且提供跟踪、管理的功能,使得应用程序的错误、Bug能够即时被解决。

    Sentry提供了Java库——Raven Java,Java应用程序能够在捕获异常后将其发送到Sentry服务器中,另一方面它包含了各类日志框架的支持,以Logbakc为例:

    <dependency>
        <groupId>net.kencochrane.raven</groupId>
        <artifactId>raven-logback</artifactId>
        <version>6.0.0</version>
    </dependency>

    logback.xml中定义appender

    <configuration>
        <appender name="Sentry" class="net.kencochrane.raven.logback.SentryAppender">
            <dsn>https://publicKey:secretKey@host:port/1?options</dsn>
            <tags>tag1:value1,tag2:value2</tags>
            <!-- Optional, allows to select the ravenFactory -->
            <!--<ravenFactory>net.kencochrane.raven.DefaultRavenFactory</ravenFactory>-->
        </appender>
        <root level="warn">
            <appender-ref ref="Sentry"/>
        </root>
    </configuration>

    我们推荐在这个<appender>中加入<filter>用于过滤ERROR级别的日志。

    http://blog.csdn.net/xiaoyu411502/article/details/48295973

    72. Logging

    Spring Boot has no mandatory logging dependency, except for the commons-logging API, of which there are many implementations to choose from. To use Logback you need to include it, and some bindings for commons-logging on the classpath. The simplest way to do that is through the starter poms which all depend onspring-boot-starter-logging. For a web application you only need spring-boot-starter-web since it depends transitively on the logging starter. For example, using Maven:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    Spring Boot has a LoggingSystem abstraction that attempts to configure logging based on the content of the classpath. If Logback is available it is the first choice.

    If the only change you need to make to logging is to set the levels of various loggers then you can do that in application.properties using the "logging.level" prefix, e.g.

    logging.level.org.springframework.web=DEBUG
    logging.level.org.hibernate=ERROR

    You can also set the location of a file to log to (in addition to the console) using "logging.file".

    To configure the more fine-grained settings of a logging system you need to use the native configuration format supported by the LoggingSystem in question. By default Spring Boot picks up the native configuration from its default location for the system (e.g. classpath:logback.xml for Logback), but you can set the location of the config file using the "logging.config" property.

    72.1 Configure Logback for logging

    If you put a logback.xml in the root of your classpath it will be picked up from there (or logback-spring.xml to take advantage of the templating features provided by Boot). Spring Boot provides a default base configuration that you can include if you just want to set levels, e.g.

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/base.xml"/>
        <logger name="org.springframework.web" level="DEBUG"/>
    </configuration>

    If you look at that base.xml in the spring-boot jar, you will see that it uses some useful System properties which the LoggingSystem takes care of creating for you. These are:

    • ${PID} the current process ID.
    • ${LOG_FILE} if logging.file was set in Boot’s external configuration.
    • ${LOG_PATH} if logging.path was set (representing a directory for log files to live in).
    • ${LOG_EXCEPTION_CONVERSION_WORD} if logging.exception-conversion-word was set in Boot’s external configuration.

    Spring Boot also provides some nice ANSI colour terminal output on a console (but not in a log file) using a custom Logback converter. See the default base.xmlconfiguration for details.

    If Groovy is on the classpath you should be able to configure Logback with logback.groovy as well (it will be given preference if present).

    72.1.1 Configure logback for file only output

    If you want to disable console logging and write output only to a file you need a custom logback-spring.xml that imports file-appender.xml but notconsole-appender.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/defaults.xml" />
        <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
        <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
        <root level="INFO">
            <appender-ref ref="FILE" />
        </root>
    </configuration>

    You also need to add logging.file to your application.properties:

    logging.file=myapplication.log

    http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html

     
    下面是几个常用的过滤器:

    1,LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。
    有以下子节点:
    <level>:设置过滤级别
    <onMatch>:用于配置符合过滤条件的操作
    <onMismatch>:用于配置不符合过滤条件的操作
    例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。前面我已经举过例子了,这里就不做赘述了。

    2,ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

    3,EvaluatorFilter: 求值过滤器,评估、鉴别日志是否符合指定条件。有一下子节点:
    <evaluator>:鉴别器,常用的鉴别器是JaninoEventEvaluato,也是默认的鉴别器,它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件。
    evaluator有个子标签<expression>,用于配置求值条件
    <onMatch>,用于配置符合过滤条件的操作
    <onMismatch>,用于配置不符合过滤条件的操作

    http://blog.csdn.net/u011794238/article/details/50770557

    一个著名的日志系统是怎么设计出来的?


    1前言
    Java帝国在诞生之初就提供了集合、线程、IO、网络等常用功能,从C和C++领地那里吸引了大量程序员过来加盟,但是却有意无意地忽略了一个重要的功能: 输出日志。

    对于这一点,IO大臣其实非常清楚, 日志是个很重要的东西, 因为程序运行起来以后, 基本上就是一个黑盒子,如果程序的行为和预料的不一致,那就是出现Bug了,如何去定位这个Bug 呢?

    臣民们能用的工具有两个,第一个就是单步调试,一步步地跟踪,查看代码中变量的值, 这种办法费时费力, 并且只能在程序员的机器上才能用。

    第二种就是在特定的地方打印日志, 通过日志的输出,帮助快速定位。尤其是当代码在生产环境上跑起来以后, 日志信息更是必不可少,要不然出了状况两眼一抹黑,上哪儿找问题去? 总不能让臣民们把自己变成一个线程进入系统来执行吧?

    但是IO大臣也有自己的小算盘: 日志嘛, 用我的System.out.println(.....) 不就可以了?! 我还提供了System.err.println不是?

    在IO大臣的阻挠下, 从帝国的第一代国王到第三代国王, 都没有在JDK中提供日志相关的工具包, 臣民们只好忍受着去使用System.out.println去输出日志,把所有的信息都输出到控制台, 让那里变成一堆垃圾。

    2张家村
    张家村的电子商务系统也不能幸免,自然也遇到了日志的问题。经验丰富的老村长已经烦透了System.out.println所输出的大量难于理解的无用信息,看着村民民整天苦逼地和这些System.out做斗争,他找来了小张,命令他设计一个通用的处理日志的系统。

    小张在消息队列和JMS的设计上花了不少功夫, 积累了丰富的经验,从那以后一直都是实现业务代码,一直都是CRUD, 张二妮整天笑话自己是HTML填空人员,这一回一定要让她看看自己的设计功力!

    (传送门:《Java帝国之消息队列》,《Java帝国之JMS的诞生》)

    老村长给小张下达的需求是这样的:

    1. 日志消息除了能打印到控制台, 还可以输出到文件,甚至可以通过邮件发送出去(例如生成环境出错的消息)

    2. 日志内容应该可以做格式化, 例如变成纯文本,XML, HTML格式等等

    3. 对于不同的Java class,不同的 package , 还有不同级别的日志,应该可以灵活地输出到不同的文件中。

    例如对于com.foo 这个package,所有的日志都输出到 foo.log 文件中

    对于com.bar 这个package ,所有文件都输出到bar. log文件中

    对于所有的ERROR级别的日志,都输出到 errors.log文件中

    4. 能对日志进行分级, 有些日志纯属debug , 在本机或者测试环境使用, 方便程序员的调试, 生产环境完全不需要。有些日志是描述错误(error)的, 在生产环境下出错的话必须要记录下来,帮助后续的分析。

    小张仔细看了看,拍着胸脯对老村长说:“没问题, 明天一定让您老看到结果。”

    3小张的设计
    老村长走了以后,小张开始分析需求, 祭出“面向对象设计大法”,试图从村长的需求中抽象出一点概念。

    首先要记录日志,肯定需要一个类来表达日志的概念,这个类至少应该有两个属性,一个是时间戳,一个是消息本身,把它叫做LoggingEvent吧,记录日志就像记录一个事件嘛。

    其次是日志可以输出到不同的地方,控制台、文件、邮件等等, 这个可以抽象一下,不就是写到不同的目的地吗? 可以叫做LogDestination?

    嗯, 还是简单一点,叫做Appender吧, 暗含了可以不断追加日志的意思。

    至于第二条的日志内容可以格式化,完全可以比葫芦画瓢, 定义一个Formatter接口去格式化消息。

    对了, Appender 应该引用Formatter ,这样以来就可以对LoggingEvent记录格式化以后再发送。

    第三条需求把小张给难住了,不同的class, package 输出的目的地不同? “目的地”这个概念是由Appender来表达的, 难道让不同的class, package 和Appender关联? 不不, 不能这样 !

    还需要一个新的概念 , 这个概念是什么?

    从用户角度想一下, 村民们要想获取日志,必须得先获取个什么东西,这个东西是不是可以称为Logger啊? 灵感的火花就闪了那么一下就被小张抓住了: 获取Logger的时候要传入类名或者包名!

    这样一来,不同的class, package就区分开了, 然后让Logger 和Appender关联,灵活地设置日志的目的地, 并且一个Logger可以拥有多个Appender,同一条日志消息可以输出到多个地方, 完美!

     

    小张迅速地画出了核心类的类图:

     

    还算漂亮,小张陶醉着自我欣赏了一下。

    再接再厉, 把第四条需求也设计一下,日志要分级,这个简单, 定义一个Priority的类,里边定义5个常量DEBUG, INFO, WARN, ERROR, FATAL, 表示5个不同的级别就OK了。当然这我5个级别有高低之分, DEBUG级别最低, FATAL级别最高。

    还可以给Logger增加一些辅助编程的方法,如Logger.debug(....) , Logger.info(...) , Logger.warn(...) 等等, 这样村民们将来就可以轻松地输出各种级别的日志了。

    等一下, 老村长还说过“对于所有的ERROR级别的日志,都输出到 errors.log文件中” 类似这样的需求, 好像给忽略了。

    这也好办嘛, 只要在Appender上增加一个属性,就叫做Priority, 如果用户要输出的日志是DEBUG级别, 但是有个FileAppender的Priority是 ERROR级别,那这个日志就不用在这个FileAppender中输出了 ,因为ERROR级别比DEBUG级别高嘛。

    同理, 在Logger类上也可以增加一个Priority的属性,用户可以去设置, 如果一个Logger的Priority是ERROR, 而用户调用了这个Logger的debug方法, 那这个debug 的消息也不会输出。

    小张全心全意地投入到设计当中,一看时间, 都快半夜了, 赶紧休息, 明天向村长汇报去。

    4正交性
    第二天, 小张给老村长展示了自己设计的LoggerEvent, Logger , Appender, Formatter, Priority 等类和接口, 老村长捻着胡子满意地点点头:“不错不错,与上一次相比有巨大的进步。你知不知道我在需求中其实给了你引导?”

    “引导? 什么引导? ”

    “就是让你朝着正交的方向去努力啊”

    “正交? ”

    ‘“如果你把Logger, Appender, Formatter看成坐标系中的X轴,Y轴,Z轴, 你看看,这三者是不是可以独立变化而不互相影响啊?”

     

    “我赛,果然如此,我可以任意扩展Appender接口而影响不到Logger和Formatter, 无论有多少个Logger 都影响不了Appender和Formatter , 这就是正交了?”

    “是啊,当你从系统中提取出正交的概念的时候,那就威力无比了,因为变化被封装在了一个维度上,你可以把这些概念任意组合,而不会变成意大利面条似的代码。 ”

    听到村长做了理论的升华, 小张兴奋得直搓手。

    “好吧,你把这个设计实现了吧,对了,你打算叫什么名字? ” 村长问道

    “我打算把他叫做Log4j , 意思是Log for Java”

    “不错,就这么定了吧”

    5Log4j
    小张又花了两个月的时间把Log4j 开发了出来, 由于Log4j有着良好的设计,优异的性能, 不仅仅是张家村的人在用, Java帝国的很多村镇、部落都爱上了它。

    后来张家村把Log4j 在Apache部落开源了, 这下子吸引了无数的人无偿帮助测试它,扩展它,改进它, 很快就成了帝国最流行的日志工具。

    张家村建议帝国把Log4j 纳入到JDK 中, 帝国那效率低下的官僚机构竟然拒绝了。 消息传到了IO大臣的耳朵里,他不由的扼腕叹息: 唉,失去了一次极好的招安机会啊。 现在唯一的办法就是赶紧上奏皇上,在官方也提供一套,争取让臣民们使用官方版本。

    到了第四代国王(JDK1.4),臣民们终于看到了帝国提供的java.util.logging包,也是用来记录日志的,并且其中的核心概念Logger, Formatter, Handler 和 Log4j非常相似,只是为时已晚, Log4j早已深入人心了, 不可撼动了。

    6尾声
    Log4j 在Apache开源以后, 小张也逐渐地有点落寞,他闲不住又写了一个工具,叫做logback, 有了之前的经验,这logback 比log4j 还要快。

    如今的日志世界有了很多的选择 ,除了java.util.logging, log4j 之外,还有logback,tinylog 等其他工具。

    小张想了想, 这么多日志工具,用户如果想切换了怎么办?不想用log4j了,能换到logback吗?

    我还是提供一个抽象层吧, 用户用这个抽象层的API来写日志, 底层具体用什么日志工具不用关心,这样就可以移植了。

    小张把这抽象层就叫做Simple Logging Facade for Java,简称SLF4J。

    对于Log4j , JDK logging, tinylog 等工具, 需要一个适配层, 把SLF4J 的API转化成具体工具的调用接口。

    由于Logback这个工具也是出自小张之手, 直接实现了SLF4J的API,所以连适配层都不需要了, 用起来速度飞快,效率最高,SLFJ4+Logback 成为了很多人的最爱, 大有超越Apache Common Logging + Log4j 之势。

    后记: 本文主要想讲一下日志工具的历史和现状, 尤其是Log4j核心的设计理念。

    文中的小张其实就是Ceki Gülcü,他开发了Log4j , logback,以及slfj4, 为Java的日志事业做出了卓越的贡献。

    (完)
    https://mp.weixin.qq.com/s/XiCky-Z8-n4vqItJVHjDIg


  • 相关阅读:
    python sendmail
    linux find命令
    10块钱去买酒,2块一瓶,2空瓶换一瓶,4盖换一瓶,问能喝到什么时候
    【转】通过经纬度坐标计算距离的方法(经纬度距离计算)
    Android应用开发相关下载资源(2015/3/20更新)
    使用Entity Framework访问MySQL数据库
    VS2013+EF6.1+Mysql配置心路历程
    SQL-LINQ-Lambda语法对照实例
    百度统计今晚更新了,统计的数据报表格式都大变样了,少不了我的功劳吧!跟类似yoyooho.com的小伙伴说再见啦
    跟踪那些像www.yoyooho.com非友链带来的百度统计数据解析【第三篇】
  • 原文地址:https://www.cnblogs.com/softidea/p/5642174.html
Copyright © 2020-2023  润新知