logback에 대한 자세한 설명은 다른사이트를 참조하세요.
logback을 사용하려면 maven을 사용할경우 아래와 같이 추가하시면
기본적인 기능들은 사용하실 수 있습니다.
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency>
logback은 자체적으로 설정 파일을 reloading 할 수 있는 기능을 제공한다.
<configuration scan="true" scanPeriod="30 seconds" >
logback 테스트
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BasicLog { private static Logger logger = LoggerFactory.getLogger(BasicLog.class); public static void main(String[] args) { logger.trace("BasicLog."); logger.debug("BasicLog."); logger.info("BasicLog."); logger.warn("BasicLog."); logger.error("BasicLog."); } }
logback.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="30 seconds" > <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <encoder> <Pattern> <!-- %d{yyyy-MM-dd HH:mm:ss} : 년월일 시분초 %thread : thread name %-5level : log level , -5는 출력 고정폭 값 %logger{length} :Logger name의 이름, {length}는 자리수 %msg : log message %message은 alias %n : 줄바꿈 org.fusesource.jansi:jansi:1.8 가 필요함. Linux ,Mac OS X 기본적으로 지원함 <withJansi>true</withJansi>설정후 사용해야함 %highlight : log level 별로 color가 다르게 나옴 --> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </Pattern> </encoder> </layout> </appender> <root level="debug" > <appender-ref ref="STDOUT" /> </root> </configuration>
위와 같이 생성한후 실행을 하시면 아래와 같이 콘솔을 이용한 출력을 볼수 있습니다.
2016-02-04 15:21:50 [main] DEBUG com.hello.logback.basic.BasicLog - BasicLog. 2016-02-04 15:21:50 [main] INFO com.hello.logback.basic.BasicLog - BasicLog. 2016-02-04 15:21:50 [main] WARN com.hello.logback.basic.BasicLog - BasicLog. 2016-02-04 15:21:50 [main] ERROR com.hello.logback.basic.BasicLog - BasicLog.
좀더 다양한 로그를 이용하기 위해서는 다른종류의 appender를 이용하시면됩니다.
1.mdc를 이용한 logging
아래와 같이 MDC.put 을 logging에 필요한 다양한것들을 추가할수 있습니다.
MDC.put("userid", "scott"); logger.info("start application."); logger.info("end application."); MDC.remove("userid");
logback.xml파일에 아래와 같은 pattern을 추가하시면 로그에 출력되는것을 확인할수 있습니다.
%X{userid} : userid의 값 %mdc : all mdc key=value (host=127.0.0.1, userid=dec)
2016-02-04 15:28:01 [userid=scott] [scott] [main] INFO com.hello.logback.mdc.MdcLog - start application. 2016-02-04 15:28:01 [userid=scott] [scott] [main] INFO com.hello.logback.mdc.MdcLog - end application.
web application을 개발할 경우 filter를 이용하여
public class MDCServletFilter implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; MDC.put(REMOTE_HOST, httpRequest.getRemoteHost()); HttpSession session = httpRequest.getSession(); if (session != null && session.getAttribute(USER_ID_MDC_KEY) != null){ MDC.put(USER_ID, (String)session.getAttribute(USER_ID)); } try{ chain.doFilter(request, response); }finally{ MDC.clear(); } } }
MDC.put 을 추가하여 원하는 값을 logging 할수 있습니다.
2.파일로그
ch.qos.logback.core.rolling.RollingFileAppender을 이용하면 일자별 로그를 생성할수 있습니다.
maxFileSize값을 설정할경우 maxFileSize값을 넘어갈경우 아래와 같이 생성된다.
maxHistory값은 월을 뜻하며 설정한 월값을 지난 로그파일은 자동으로 삭제해준다.
<property name="LOG_HOME" value="d:\\log\\" /> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/log.txt</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${LOG_HOME}/log-%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> <!-- maximum number of archive files to keep, deleting older files. For example, if you specify monthly rollover, and set maxHistory to 6, then 6 months worth of archives files will be kept with files older than 6 months deleted. --> <maxHistory>6</maxHistory> </rollingPolicy> <encoder> <pattern> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender>
3.sift를 이용한 파일별 logging
아래와 같이 파일을 분리해서 logging하고자 하는 값을 설정한다.
MDC.put("userid", "scott"); logger.info("scott start application."); logger.info("scott end application."); MDC.put("userid", "tiget"); logger.info("tiget start application."); logger.info("tiget end application."); MDC.clear();
SifingAppender를 이용하여 key에 분리하고자 하는값을 설정한다.
<property name="LOG_HOME" value="d:\\log\\" /> <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender"> <discriminator> <key>userid</key> <defaultValue>unknown</defaultValue> </discriminator> <sift> <appender name="FILE-${userid}" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/${userid}.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %mdc [%thread] %-5level %logger{36} - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <FileNamePattern>${LOG_HOME}/${userid}.%i.log.zip</FileNamePattern> <MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> </sift> </appender>
아래와 같이 userid별로 생성된 log file을 볼수 있다.
4.AsyncAppender를 이용한 logging
비동기 logging의 경우 Method name, Line Number 등이 출력되지 않는다.
TRACE, DEBUG and INFO 레벨의 로그는 기본적으로 20% 유실 될 수 있다
비동기 큐에 로그가 쌓인 상태에서 프로세스가 종료되면 해당 로그는 기록되지 않고 종료된다.
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </Pattern> </layout> </appender> <appender name="async" class="ch.qos.logback.classic.AsyncAppender"> <!-- Queue의 크기중에 비어있는 부분이 discardingThreshold 비율 이하인 경우 INFO 레벨 이하의 로그는 저장하지 않는다. 모든 로그 이벤트를 처리하기 위해서는 0으로 discardingThreshold을 설정합니다 --> <discardingThreshold>0</discardingThreshold> <!-- 큐의 최대 용량. 기본적으로 QUEUESIZE는 256으로 설정됩니다. --> <queueSize>10000</queueSize> <!-- 해당 로그 이벤트 정보를 Queue에 추가하는 시점에 로그를 호출한 정보 (callerData)를 추출할지 여부를 결정하는 속성 <includeCallerData>boolean</includeCallerData> --> <!-- (밀리 초) 큐의 최대 flush timeout 시간을 지정합니다.처리 할 수없는 이벤트가 삭제됩니다. <maxFlushTime>int</maxFlushTime> --> <appender-ref ref="STDOUT" /> </appender>
테스트 소스 다운로드 : https://github.com/liyobi/logback-appender-case
조으디!! ㅋㅋㅋ
DB랑 소켓도 추가해 주삼~
trace, debug, info 20% 유실될 수 도있는건 정확하지않은것 같습니다.
default 로 queue의 용량이 80% 찾을때 queue에서 trace, debug, info레벨의 event를 삭제합니다.
하지만 discardingThreshold의 속성을 0으로(default 20) 하면 로그 유실을 막을 수 있습니다.
discardingThreshold default 가 20인 이유는 성능이나 큐 안전성을 고려해서 trace, info, debug를 버리는것이 기회비용이 작기 때문에 그런거겠죠?(정확하지 않음)