비동기 Appender는 확실히 빠르지만 부하가 심한 상황에서 WARN 이하 레벨의 로그는 기본적으로 20% 유실 될 수 있고, 비동기 큐에 로그가 쌓인 상태에서 프로세스가 종료되면 해당 로그는 기록되지 않고 종료된다.
groovy 방식 설정은 1.1 이후 버전부터 AsyncAppender 사용가능. appenderRef가 존재하지 않았기 때문.
import ch.qos.logback.classic.AsyncAppender import ch.qos.logback.classic.PatternLayout import ch.qos.logback.core.ConsoleAppender import ch.qos.logback.core.encoder.LayoutWrappingEncoder appender("STDOUT", ConsoleAppender) { encoder(LayoutWrappingEncoder) { layout(PatternLayout) { pattern = "${p} %m%n" // ${p} 잘못된 패턴인듯 } } } appender("STDOUT-ASYNC", AsyncAppender) { appenderRef('STDOUT') } root(DEBUG, ["STDOUT-ASYNC"])
includeCallerData=true
를 통해서 가능하다. 물론 성능저하가 발생할 것이다.queueSize
옵션으로 변경한다. 기본 256
. 적당히 증가시킨다. 4096
?neverBlock=false
큐가 20%정도만 남으면 1차로 ERROR 보다 낮은 레벨의 로그를 버리고, ERROR 이상 레벨의 로그를 찍는데 그것도 꽉차면 blocking 상태가 된다. neverBlock=true
이면 그마저도 blocking 하지 않고 버려버린다.includeCallerData=false
에 따라 메소드 이름, 줄 번호 등이 출력되지 않는다. 대신 성능은 향상된다.<configuration> <!-- The underlying appender will be the standard console one. --> <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> <!-- Wrap calls to the console logger with async dispatching to Disruptor. --> <appender name="async" class="reactor.logback.AsyncAppender"> <!-- Backlog size for logging events. Change size if they are picked up slowly. Default is 1024 * 1024 --> <backlog>65536</backlog> <!-- 2의 거듭제곱이어야 함 --> <!-- Caller data is relatively slow, so per default disabled --> <includeCallerData>false</includeCallerData> <appender-ref ref="stdout"/> </appender> <!-- Direct all logging through the AsyncAppender. --> <root level="info"> <appender-ref ref="async"/> </root> </configuration>