slf4j と logback の関係

サンプルアプリ

pom.xml

<?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.mycompany</groupId>
    <artifactId>SLF4JExam</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!-- SLF4J and Logback-class and Logback-core -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- DB Appender needs JDBC Driver -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.3-1101-jdbc41</version>
        </dependency>
        <!-- SMTP Appender needs JavaMail and Activation -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- GEventEvaluator Filter needs Groovy -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.0.7</version>
        </dependency>
        <!-- JaninoEventEvaluator Filter needs Janino and Commons-Compiler -->
        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
            <version>2.6.1</version>
        </dependency>       
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
</project>
pom.png

com.mycompany.logbackexam.App.java

package com.mycompany.logbackexam;

import com.mycompany.logbackexam.app.buggy.BuggyClass;
import com.mycompany.logbackexam.app.gentle.GentleClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {

    private static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        // slf4j には fatal は無い
        //logger.fatal("本当にやばいログ  ");
        logger.error("普通にやばいログ  ");
        logger.warn("ちょっとやばいログ ");
        logger.info("運用時に必要なログ ");
        logger.debug("開発時に必要なログ ");
        logger.trace("デスマ時に必要なログ");
        
        BuggyClass buggy = new BuggyClass();
        GentleClass gentle = new GentleClass();
        
        buggy.doSomething();
        gentle.doSomething();
    }
}

com.mycompany.logbackexam.app.buggy.BunngClass?.java

package com.mycompany.logbackexam.app.buggy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BuggyClass {
    
    private static Logger logger = LoggerFactory.getLogger(BuggyClass.class);

    public void doSomething() {
        // slf4j には fatal は無い
        //logger.fatal("本当にやばいログ  ");
        logger.error("普通にやばいログ  ");
        logger.warn("ちょっとやばいログ ");
        logger.info("運用時に必要なログ ");
        logger.debug("開発時に必要なログ ");
        logger.trace("デスマ時に必要なログ");
    } 
}

com.mycompany.logbackexam.app.gentle.GentleClass?.java

package com.mycompany.logbackexam.app.gentle;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GentleClass {
    private static Logger logger = LoggerFactory.getLogger(GentleClass.class);

    public void doSomething() {
        // slf4j には fatal は無い
        //logger.fatal("本当にやばいログ  ");
        logger.error("普通にやばいログ  ");
        logger.warn("ちょっとやばいログ ");
        logger.info("運用時に必要なログ ");
        logger.debug("開発時に必要なログ ");
        logger.trace("デスマ時に必要なログ");
    }
}

logback.xml

<configuration>
    <!--
    #####################
    # pattern structure #
    #####################
    
    http://logback.qos.ch/manual/layouts.html
    
    * %logger{length}
        log source. this is the argument of LoggerFactory.getLogger(class). 
        %logger{0} prints class name.
    
    * %date{pattern}, %date{pattern, timezone}
        %date => 2006-10-20 14:06:49,812 (It's ISO8601)
        %date{dd MMM yyy;HH:mm:ss.SSS} => 20 oct. 2006;14:05:49.812
    * %relative          milliseconds elapsed from application start.
    * %level             level
    * %message, %msg     message
    * %n                 \n or \r\n
    
    * %thread            thread
    * %mdc{key:-default} MDC
    
    * %class{length}     log source. this came from stacktrace. very slow.
    * %file              java source file name. very slow.
    * %caller{depth}     show stack trace. very slow
    * %method            method. very slow
    * %line              line number. very slow
    
    * right padding      msg = 12345 => %-10msg = "12345     "
    * highlight          %highlight(%-5level) %cyan(%logger{0})
                         Jansi lib and <withJansi>true</withJansi>
                         is needed if run on win.
    -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <withJansi>true</withJansi>
        <encoder>
            <pattern>%date [%thread] %highlight(%-5level) %cyan(%-20logger{20}) %msg %n</pattern>
        </encoder>
    </appender>

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

出力結果

output.png

logback の設定内容をログに出力する

package com.mycompany.slf4jexam;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {

    private static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        // slf4j には fatal は無い
        //logger.fatal("本当にやばいログ");
        logger.error("普通にやばいログ");
        logger.warn("ちょっとやばいログ");
        logger.info("運用時に必要なログ");
        logger.debug("開発時に必要なログ");
        logger.trace("デスマ時に必要なログ");
        
        // print internal state
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        StatusPrinter.print(lc);
    }
}
 
2014-03-30 16:37:53,748 [main] ERROR c.m.slf4jexam.App    普通にやばいログ 
2014-03-30 16:37:53,751 [main] WARN  c.m.slf4jexam.App    ちょっとやばいログ 
2014-03-30 16:37:53,751 [main] INFO  c.m.slf4jexam.App    運用時に必要なログ 
2014-03-30 16:37:53,751 [main] DEBUG c.m.slf4jexam.App    開発時に必要なログ 
|- Could NOT find resource [logback.groovy]
|- Could NOT find resource [logback-test.xml]
|- Found resource [logback.xml] at [file:/Users/atsushi/NetBeansProjects/SLF4JExam/target/classes/logback.xml]
|- debug attribute not set
|- About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
|- Naming appender as [STDOUT]
|- Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
|- Setting level of ROOT logger to DEBUG
|- Attaching appender named [STDOUT] to Logger[ROOT]
|- End of configuration.
|- Registering current configuration as safe fallback point

logback の設定ファイルを指定する

loglevel

level

level ::= TRACE | DEBUG | INFO | WARN | ERROR | OFF

パッケージごとに level を変更する

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="com.mycompany.logbackexam.app.buggy" level="DEBUG"/>
    <logger name="com.mycompany.logbackexam.app.gentle" level="WARN"/>
 
    <root level="OFF">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER1* c.m.l.a.b.BuggyClass 普通にやばいログ  
*LOGGER1* c.m.l.a.b.BuggyClass ちょっとやばいログ 
*LOGGER1* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.b.BuggyClass 開発時に必要なログ 
*LOGGER1* c.m.l.a.g.GentleClass 普通にやばいログ  
*LOGGER1* c.m.l.a.g.GentleClass ちょっとやばいログ

素直に継承される

指定した level出力 level
rootOFF-
App-なし
BuggyDEBUGDEBUG, INFO, WARN, ERROR
GentleWARNWARN, ERROR

logger に appender を貼り付ける

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER2* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="STDOUT3" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER3* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="com.mycompany.logbackexam.app.buggy" level="DEBUG">
        <appender-ref ref="STDOUT2" />
    </logger>
    <logger name="com.mycompany.logbackexam.app.gentle" level="WARN">
        <appender-ref ref="STDOUT3" />
    </logger>
    <root level="OFF">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER2* c.m.l.a.b.BuggyClass 普通にやばいログ  
*LOGGER1* c.m.l.a.b.BuggyClass 普通にやばいログ  
*LOGGER2* c.m.l.a.b.BuggyClass ちょっとやばいログ 
*LOGGER1* c.m.l.a.b.BuggyClass ちょっとやばいログ 
*LOGGER2* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER2* c.m.l.a.b.BuggyClass 開発時に必要なログ 
*LOGGER1* c.m.l.a.b.BuggyClass 開発時に必要なログ 
*LOGGER3* c.m.l.a.g.GentleClass 普通にやばいログ  
*LOGGER1* c.m.l.a.g.GentleClass 普通にやばいログ  
*LOGGER3* c.m.l.a.g.GentleClass ちょっとやばいログ 
*LOGGER1* c.m.l.a.g.GentleClass ちょっとやばいログ 
指定した level出力 level
rootOFFSTDOUT1--
App--なしなし
BuggyDEBUGSTDOUT2DEBUG, INFO, WARN, ERRORSTDOUT1, STDOUT2
GentleWARNSTDOUT3WARN, ERRORSTDOUT1, STDOUT3

level と appender が root から継承されている

logger に appender を貼り付けるけど root 設定を継承したくない

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER2* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="STDOUT3" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER3* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="com.mycompany.logbackexam.app.buggy" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT2" />
    </logger>
    <logger name="com.mycompany.logbackexam.app.gentle" level="WARN" additivity="false">
        <appender-ref ref="STDOUT3" />
    </logger>
    <root level="OFF">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER2* c.m.l.a.b.BuggyClass 普通にやばいログ  
*LOGGER2* c.m.l.a.b.BuggyClass ちょっとやばいログ 
*LOGGER2* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER2* c.m.l.a.b.BuggyClass 開発時に必要なログ 
*LOGGER3* c.m.l.a.g.GentleClass 普通にやばいログ  
*LOGGER3* c.m.l.a.g.GentleClass ちょっとやばいログ

ログ設定のパラメータ化

logback.xml 内

<configuration>

  <property name="USER_HOME" value="/home/sebastien" />

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${USER_HOME}/myApp.log</file>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

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

起動パラメータ

java -DUSER_HOME="/home/sebastien" MyApp2
<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${USER_HOME}/myApp.log</file>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

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

properties

<configuration>

  <property file="src/main/java/chapters/configuration/variables1.properties" />

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <file>${USER_HOME}/myApp.log</file>
     <encoder>
       <pattern>%msg%n</pattern>
     </encoder>
   </appender>

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

properties ファイルの中で変数を使うことも可能

USER_HOME=/home/sebastien
fileName=myApp.log
destination=${USER_HOME}/${fileName}

環境変数

USER_HOME=/home/sebastien
<configuration>

  <property resource="resource1.properties" />

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <file>${USER_HOME}/myApp.log</file>
     <encoder>
       <pattern>%msg%n</pattern>
     </encoder>
   </appender>

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

JNDI

<configuration>
  <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
  <contextName>${appName}</contextName>

  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d ${CONTEXT_NAME} %level %msg %logger{50}%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>
</configuration>

file include

<configuration>
  <include file="src/main/java/chapters/configuration/includedConfig.xml"/>

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

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

Appender

Console

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- colorize -->
    <withJansi>true</withJansi>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

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

File

<configuration>
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

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

File Rotate

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- Support multiple-JVM writing to the same log file -->
    <prudent>true</prudent>

    <!-- (1) daily rolling -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory> 
    </rollingPolicy>

    <!-- (2) size rolling -->
    <!--
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>logFile.%i.log</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    -->

    <!-- (3) daily and size rolling -->
    <!--
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>    
    -->

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

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

Mail

<configuration>   
  <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
    <smtpHost>ADDRESS-OF-YOUR-SMTP-HOST</smtpHost>
    <to>EMAIL-DESTINATION</to>
    <to>ANOTHER_EMAIL_DESTINATION</to> <!-- additional destinations are possible -->
    <from>SENDER-EMAIL</from>
    <subject>TESTING: %logger{20} - %m</subject>
    <layout class="ch.qos.logback.classic.PatternLayout">
      <pattern>%date %-5level %logger{35} - %message%n</pattern>
    </layout>       
  </appender>

  <root level="DEBUG">
    <appender-ref ref="EMAIL" />
  </root>  
</configuration>

DB

DDL文 : https://github.com/qos-ch/logback/tree/master/logback-classic/src/main/java/ch/qos/logback/classic/db/script

<configuration>
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
      <driverClass>org.postgresql.Driver</driverClass>
      <url>jdbc:postgresql://localhost:5432/demo</url>
      <user>atsushi</user>
      <password>**********</password>
    </connectionSource>
  </appender>
  
    <root level="DEBUG">
        <appender-ref ref="DB" />
    </root>
</configuration>
db.png

JNDI 経由で Connection Pool を使うこともできる

<configuration debug="true">
  <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.JNDIConnectionSource">
      <!-- please note the "java:comp/env/" prefix -->
      <jndiLocation>java:comp/env/jdbc/logging</jndiLocation>
    </connectionSource>
  </appender>
  <root level="INFO">
    <appender-ref ref="DB" />
  </root>  
</configuration>

SYSLOG

<configuration>

  <appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
    <syslogHost>remote_home</syslogHost>
    <!-- default is 514
    <port>514</port>
    -->
    
    <!-- KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, CRON,
         AUTHPRIV, FTP, NTP, AUDIT, ALERT, CLOCK, 
         LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7 -->
    <facility>AUTH</facility>
    <suffixPattern>[%thread] %logger %msg</suffixPattern>

    <!--
    Out put the stackTracePattern string before each lines of the stack trace.
    default is \t.
    <stackTracePattern>\t</stackTracePattern>
    -->

    <!--
    Don't send stacktraces to syslog doemon.
    default is false, ie. send stacktraces to syslog doemon.
    <throwableExcluded>false</throwableExcluded>
    -->

  </appender>

  <root level="DEBUG">
    <appender-ref ref="SYSLOG" />
  </root>
</configuration>

Filter

LevelFilter?

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER1* c.m.logbackexam.App  運用時に必要なログ
*LOGGER1* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.g.GentleClass 運用時に必要なログ

ThresholdFilter?

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER1* c.m.logbackexam.App  普通にやばいログ
*LOGGER1* c.m.logbackexam.App  ちょっとやばいログ
*LOGGER1* c.m.logbackexam.App  運用時に必要なログ
*LOGGER1* c.m.l.a.b.BuggyClass 普通にやばいログ  
*LOGGER1* c.m.l.a.b.BuggyClass ちょっとやばいログ 
*LOGGER1* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.g.GentleClass 普通にやばいログ  
*LOGGER1* c.m.l.a.g.GentleClass ちょっとやばいログ 
*LOGGER1* c.m.l.a.g.GentleClass 運用時に必要なログ

EvaluatorFilter?

<configuration>
    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
            <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
                <expression>return message.contains("必要");</expression>
            </evaluator>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>ACCEPT</OnMatch>
        </filter>
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
*LOGGER1* c.m.logbackexam.App  運用時に必要なログ
*LOGGER1* c.m.logbackexam.App  開発時に必要なログ
*LOGGER1* c.m.l.a.b.BuggyClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.b.BuggyClass 開発時に必要なログ 
*LOGGER1* c.m.l.a.g.GentleClass 運用時に必要なログ 
*LOGGER1* c.m.l.a.g.GentleClass 開発時に必要なログ

GEventEvaluator?

TurboFilter?

<configuration>
    <turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter">
        <!-- Default AllowedRepetitions is 5. 
        <AllowedRepetitions>2</AllowedRepetitions>
        -->
        <!-- Default CacheSize is 100.
        <CacheSize>100</CacheSize>
        -->
    </turboFilter>

    <appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>*LOGGER1* %-20logger{20} %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="STDOUT1" />
    </root>
</configuration>
        logger.info("{} sheep.", 1);
        logger.info("{} sheep.", 2);
        logger.info("{} sheep.", 3);
        logger.info("{} sheep.", 4);
        logger.info("{} sheep.", 5);
        logger.info("{} sheep.", 6);
        logger.info("{} sheep.", 7);
        logger.info("{} sheep.", 8);
        logger.info("{} sheep.", 9);
        logger.info("Yawn.");
        logger.info("{} sheep.", 1);
        logger.info("{} sheep.", 2);
        logger.info("{} sheep.", 3);
        logger.info("{} sheep.", 4);
        logger.info("{} sheep.", 5);
        logger.info("{} sheep.", 6);
        logger.info("{} sheep.", 7);
        logger.info("{} sheep.", 8);
        logger.info("{} sheep.", 9);
--- exec-maven-plugin:1.2.1:exec (default-cli) @ SLF4JExam ---
*LOGGER1* c.m.logbackexam.App  1 sheep.
*LOGGER1* c.m.logbackexam.App  2 sheep.
*LOGGER1* c.m.logbackexam.App  3 sheep.
*LOGGER1* c.m.logbackexam.App  4 sheep.
*LOGGER1* c.m.logbackexam.App  5 sheep.
*LOGGER1* c.m.logbackexam.App  6 sheep.
*LOGGER1* c.m.logbackexam.App  Yawn.
------------------------------------------------------------------------

参考文献


Java#Jakarta


添付ファイル: filepom.png 376件 [詳細] filedb.png 404件 [詳細] fileoutput.png 506件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   sitemap
Last-modified: 2014-04-06 (日) 21:38:54 (979d)
ISBN10
ISBN13
9784061426061