본문 바로가기

Backend/spring

[spring, logback] 비동기식 로깅 - AsyncAppender - 2

728x90

 

코드의 자세한 설명을 하겠다.

 

- application.properties

spring.profiles.active 설정을 변경해서 앱이 개발 상태인지 배포 상태인지에 따라서

logback의 설정을 지정할 수 있다.

spring.profiles.active=local
logging.config=classpath:logback-${spring.profiles.active}.xml

 

- logback-local.xml

logback 설정 파일이다.

어떻게 로그를 남길지에 대한 logback의 설정 값을 지정할 수 있다.

scanPeriod를 지정하여 로그 설정파일을 주기적으로 다시 읽도록 하여 앱이 배포 중인 상태에서도 로그 설정을 변경할 수 있다.

STDOUT의 appender처럼 이용하면 로그를 동기식으로 남길 수 있다.

ROLLING_FILE, ASYNC_FILE appender를 이용하면 로그를 비동기식으로 남길 수 있다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<property name="LOG_PATH" value="./tmp"/>
<property name="LOG_FILE" value="${LOG_PATH}/mylog.log" />
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS,Asia/Tokyo} %-5level [%thread,%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}] %logger{36} [%file:%line] - %msg ##%n" />
<!-- async logging on file-->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>5</maxHistory>
</rollingPolicy>
</appender>
<!-- ROLLING_FILE appender를 AsyncAppender가 참조하도록 한다 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="ROLLING_FILE" />
<queueSize>256</queueSize>
<discardingThreshold>20</discardingThreshold>
<includeCallerData>true</includeCallerData>
<maxFlushTime>10</maxFlushTime>
<neverBlock>true</neverBlock>
</appender>
<!-- sync logging on console -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- debug level로 콘솔에 로그를 출력하도록 한다. -->
<!-- debug level로 ASYNC_FILE appender로 로그를 출력하도록 한다. -->
<root level="debug">
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>

 

- TestController.java, TestService.java

먼저 controller와 service를 생성하여 logger를 가져와서 log를 남긴다.

logback은 slf4j에 포함되기 때문에 내부적으로는 logback 설정 파일을 자동으로 읽어서 logback을 사용한다.

package com.example.logging.controller;
import com.example.logging.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestContoller {
// slf4j를 이용하여 logger 세부구현에 상관없이 이용할 수 있다.
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final TestService testService;
@Autowired
public TestContoller(TestService testService) {
this.testService = testService;
}
@RequestMapping(value = "/test")
public ResponseEntity<Void> test() {
logger.trace("start");
logger.debug("start");
logger.info("start");
logger.warn("start");
logger.error("start");
testService.testLog();
logger.trace("end");
logger.debug("end");
logger.info("end");
logger.warn("end");
logger.error("end");
return new ResponseEntity<>(HttpStatus.OK);
}
}
package com.example.logging.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class TestService {
// slf4j를 이용하여 logger 세부구현에 상관없이 이용할 수 있다.
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public void testLog() {
logger.trace("logging");
logger.debug("logging");
logger.info("logging");
logger.warn("logging");
logger.error("logging");
}
}

 

- mylog.log

실제로 파일에 남겨진 로그를 첨부한다.

debug level에서는 아주 많은 로그가 남지만 controller와 service와 관련된 로그만 발췌했다.

2021-07-08 12:19:46.775 DEBUG [http-nio-8080-exec-1,,,] o.s.w.s.m.m.a.RequestMappingHandlerMapping [AbstractHandlerMapping.java:522] - Mapped to com.example.logging.controller.TestContoller#test() ##
2021-07-08 12:19:46.782 DEBUG [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:27] - start ##
2021-07-08 12:19:46.782 INFO [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:28] - start ##
2021-07-08 12:19:46.782 WARN [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:29] - start ##
2021-07-08 12:19:46.782 ERROR [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:30] - start ##
2021-07-08 12:19:46.782 DEBUG [http-nio-8080-exec-1,,,] c.e.logging.service.TestService [TestService.java:13] - logging ##
2021-07-08 12:19:46.782 INFO [http-nio-8080-exec-1,,,] c.e.logging.service.TestService [TestService.java:14] - logging ##
2021-07-08 12:19:46.783 WARN [http-nio-8080-exec-1,,,] c.e.logging.service.TestService [TestService.java:15] - logging ##
2021-07-08 12:19:46.783 ERROR [http-nio-8080-exec-1,,,] c.e.logging.service.TestService [TestService.java:16] - logging ##
2021-07-08 12:19:46.783 DEBUG [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:33] - end ##
2021-07-08 12:19:46.783 INFO [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:34] - end ##
2021-07-08 12:19:46.783 WARN [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:35] - end ##
2021-07-08 12:19:46.783 ERROR [http-nio-8080-exec-1,,,] c.e.logging.controller.TestContoller [TestContoller.java:36] - end ##
view raw mylog.log hosted with ❤ by GitHub

 

 

전체 소스코드는 여기서 확인이 가능하다. 여기