2021. 9. 17. 02:17ㆍ개발공부/SpringBoot
spring Logback
spring-boot-starter-logging
은 간단한 설정으로 편리한 logging을 제공합니다. 설정은 application.properties, XML 두 가지 방식이 있으며
복잡한 커스텀이 필요하다면 XML을 사용해야지만 됩니다.
spring-boot-starter
내에는 logback-classic
, slf4j
의존성이 포함되어 있습니다.
작동원리를 이해하기 좋은 방법은 직접 사용하면서 연습해보는 것 같습니다.
Logger 예제코드를 위해 Service 클래스를 하나 생성해줍니다.
@Service
public class LoggerService {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggerService.class);
public void doStuff(final String value) {
LOGGER.trace("doStuff needed more information - {}", value);
LOGGER.debug("doStuff needed to debug - {}", value);
LOGGER.info("doStuff took input - {}", value);
LOGGER.warn("doStuff needed to warn - {}", value);
LOGGER.error("doStuff encountered an error with value - {}", value);
}
}
그리고 첫 시작으로 간단한 코드를 logback.xml에 작성해주면 Logback 파일이 설정을 위해 찾아 세팅해줄 것입니다.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} $magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
ConsoleAppender
는 System.out.println
처럼 콘솔에 log를 출력해주는 appender 클래스 입니다. 특히 pattern
에 여러 %가 붙어진 표기들이 있는데
생성되는 값으로 대체될 부분이라 보면됩니다.
%d
- 로그 메시지가 발생했을 때 시간을SimpleDateFormat
으로 출력할 수 있도록 해줍니다.%thread
- 로그 메시지가 발생한 스레드명을 출력해줍니다.$-5level
- 로그 메시지의 로깅 레벨을 출력합니다.%logger{36}
- 로그 메시지가 발생한 패키지 + 클래스명을 출력합니다. 괄호 안의 숫자는 글자 수 max length를 표기합니다.%M
- 로그 메시지가 발생한 메서드명을 출력합니다.%msg
- 로그 메시지를 출력합니다.%n
- 라인 변경%magenta()
- 괄호 안의 텍스트 색을 설정합니다(magenta). 다른 색으로도 변경가능합니다.highlight
- 괄호 안의 텍스트를 강조합니다.
설정한 appender는 root logger에 참조됩니다. 상기 코드는 INFO
(대소문자 구분없음)로 설정되어있는 상태입니다.
Logback애서 가능한 로깅레벨은 다음과 같습니다.
- OFF (output no logs)
- ERROR
- WARN
- INFO
- DEBUG
- TRACE
021-09-17 00:19:36.242 [main] INFO com.jpa.shop.logger.LoggerService.doStuff - doStuff took input - 테스트중:INFO
2021-09-17 00:19:36.243 [main] WARN com.jpa.shop.logger.LoggerService.doStuff - doStuff needed to warn - 테스트중:INFO
2021-09-17 00:19:36.243 [main] ERROR com.jpa.shop.logger.LoggerService.doStuff - doStuff encountered an error with value - 테스트중:INFO
테스트 결과 INFO 로깅 레벨 이상의 로그들만 출력되었음을 볼 수 있습니다. DEBUG, TRACE 레벨의 메시지는 출력되지 않았습니다.
properties(yaml)로 설정하고 싶다면 아래와 같이 설정해주면 됩니다. 훨씬 간결한 코드로 XML 설정파일을 대체할 수 있습니다.
logging:
level:
root: info
pattern:
console: %d{yyyy-MM-dd HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n
로그 메시지를 특정 클래스에서 root level이 아닌 고유한 설정으로 로그 레벨을 지정해주고 싶다면 아래 코드와 같이 설정해주면 됩니다.
<logger name="com.jpa.shop.logger.LoggerService" level="debug">
<appender-ref ref="STDOUT"/>
</logger>
//결과값
2021-09-17 00:33:38.815 [main] DEBUG com.jpa.shop.logger.LoggerService.doStuff - doStuff needed to debug - 테스트중:INFO
2021-09-17 00:33:38.815 [main] DEBUG com.jpa.shop.logger.LoggerService.doStuff - doStuff needed to debug - 테스트중:INFO
2021-09-17 00:33:38.816 [main] INFO com.jpa.shop.logger.LoggerService.doStuff - doStuff took input - 테스트중:INFO
2021-09-17 00:33:38.816 [main] INFO com.jpa.shop.logger.LoggerService.doStuff - doStuff took input - 테스트중:INFO
2021-09-17 00:33:38.816 [main] WARN com.jpa.shop.logger.LoggerService.doStuff - doStuff needed to warn - 테스트중:INFO
2021-09-17 00:33:38.816 [main] WARN com.jpa.shop.logger.LoggerService.doStuff - doStuff needed to warn - 테스트중:INFO
2021-09-17 00:33:38.817 [main] ERROR com.jpa.shop.logger.LoggerService.doStuff - doStuff encountered an error with value - 테스트중:INFO
2021-09-17 00:33:38.817 [main] ERROR com.jpa.shop.logger.LoggerService.doStuff - doStuff encountered an error with value - 테스트중:INFO
변경된 설정에 따라 로그 레벨이 DEBUG 이상으로 찍힌 것을 확인할 수 있습니다. 하지만 로그가 중복 출력된 것은 바로 잡아야 합니다. 이를 위해 additivity=false
를
설정해줘야합니다. 또는 출력이 되지 않게끔 appender
를 생략해주면 됩니다.
<logger name="com.jpa.shop.logger.LoggerService" additivity="false" level="debug">
<appender-ref ref="STDOUT"/>
</logger>
///--------
<logger name="com.jpa.shop.logger.LoggerService" level="debug"/>
이또한 properties(yaml) 설정으로 대체가능합니다.
logging:
level:
com:
jpa:
shop:
logger:
LoggerService: debug
물론 클래스 대신 패키지 뎁스로 설정해줄수도 있습니다. 효과적인 예시로는
<logger name="org.springframework.boot" level="debug">
<appender-ref ref="STDOUT" />
</logger>
와
<logger name="org.springframework.boot.SpringApplication" level="debug">
<appender-ref ref="STDOUT" />
</logger>
두 가지 예시가 있습니다. 한 뎁스 차이지만 로그 출력 라인은 약 100개 가량의 차이가 납니다.
물론 이또한 properties(yaml)로 설정이 가능합니다.
Properties는 재사용이 필요한 데이터를 변수화할 수 있는 태그입니다. 출력한 로그를 파일로 만드는 경로에 사용됩니다.
<property name="LOG_PATH" value="logs"/>
//properties(yaml)
logging:
path:logs
LOG_PATH
는 이후 예제에서 사용될 것이며 HOME/logs
디렉토리를 사용할 거란 뜻입니다 HOME
은 제 프로젝트의 root 디렉토리입니다. 이 디렉토리는
저장하기 적합한 곳은 아니지만 연습예제에선 문제없습니다. XML파일 내에서 LOG_PATH
값에 접근하려면 ${LOG_PATH}
형식으로 추가해줘야합니다.
이런 형태로 Spring boot 애플리케이션 내에서 property값을 설정해두고 ${property}
형식으로 사용할 수 있습니다.
출력된 로그를 파일로 저장하려면 FileAppender
를 사용해야합니다. 하지만 이는 단순히 모든 로그를 한 파일에 저장하기 때문에 용량이 커질 위험이 있습니다.
그래서 RollingFileAppender
사용을 권장합니다.
<appender name="SAVE-TO-FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_PATH}/log.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
</Pattern>
</encoder>
</appender>
사실 ConsoleAppender
와 크게 다르지 않습니다. encoder pattern에 글자 색이나 강조 설정만 제거했을 뿐입니다. properties(yaml)을 사용하려면
아래 설정을 추가해줘야 합니다.
logging.pattern.console=
logging.path=logs
logging.file=${logging.path}/log.log
logging.pattern.file=%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
XML 설정과 차이는 LoggerService
만 출력 파일에 담았던 XML과 달리 properteis(yaml)는 root logger까지 모두 포함해 저장하게 됩니다.
RollingFileAppender
는 rolling policy에 따라 로그들을 별도의 파일들로 나뉘어 저장합니다. 예를 들어 파일 사이즈나 기간에 따라 말이죠.
이는 하나의 파일안에서 방대한 히스토리를 들춰보지 않아도 된다는 것을 뜻합니다.
TimeBasedRollingPolicy
는 새로운 파일을 date 기준으로 생성합니다. 아래 코드는 date를 로그파일 이름에 %d
를 사용해 붙여줍니다. %d
표기는
rollover time 기간을 참조하기 때문에 중요하다고 볼 수 있습니다. 아래 코드는 날마다 파일이 업데이트 되도록 설정되었지만 월마다로 설정을 변경하고 싶으면%d{yyyy-MM}
로 바꿔주면 됩니다.
<appender name="SAVE-TO-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/log.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>
${LOG_PATH}/archived/log_%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>10</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
</appender>
추가적으로 TimeBaseRollingPolicy
의 maxHistory
는 archived 로그 파일들이 얼마만큼 보관될지 설정하는 것입니다. totalSizeCap
은
모든 archived된 파일들의 크기를 말합니다. 삭제될 때 우선순위는 maxHistory
가 앞서 가집니다.
이 설정은 properties(yaml)
의 권한범위 밖입니다. 디폴트는 maxHistory:7
에 rolloversize:10MB 입니다.
이전 예시의 경우 rollover 될 때 archive 폴더에 저장됐지만 FixedWindowRollingPolicy
와 트리거 policy SizeBasedTriggeringPolicy
의 경우
용량이 적기 때문에 곧바로 log 디렉토리에 저장했습니다.
minIndex
와 maxIndex
는 %i
의 최소, 최대값을 말합니다. 그래서 log.log 파일이 maxFileSize
를 넘기면 log_2.log
파일이 archived 폴더에
저장되며 새로운 log.log
파일이 생성됩니다. 새로운 파일이 반복해서 maxFileSize
를 초과하면 새로운 log.log
파일이 생기고 기존 파일은 log_3.log
파일로
archived 폴더에 저장되는 과정이 반복해서 일어납니다. 이 과정은 maxIndex
에 이르기 까지 계속되며 기존 파일은 삭제되고 새로운 archived 폴더에
저장되는 파일은 이름이 변경돼 저장됩니다.
말로 설명해 복잡할 수 있으니 단계적으로 나열해보겠습니다.
log.log
가 최대 크기를 초과합니다. ->log.log
가log_2.log
로 이름이 바뀌며 새로운log.log
가 생성됩니다.log_2.log
가 최대 크기를 초과합니다. ->log_2.log
는log_3.log
로 이름이 바뀌며log.log
는log_2.log
로 변경됩니다. 그리고 새로운log.log
가 생성됩니다.log_3.log
가 최대 크기를 초과합니다. ->log_3.log
는 삭제됩니다.log_2.log
는log_3.log
로 이름의 변경되며,log.log
는log_2.log
로 저장되며 새로운log.log
가 생성됩니다.
SizeAndTimeBasedRollingPolicy
는 파일 크기와 기한 두 개의 조건 모두 가지고 있는 policy입니다. 따라서 파일에 %d
와 %i
가 함께 들어갑니다.
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>
${LOG_PATH}/archived/log_%d{yyyy-MM-dd}_%i.log
</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>10</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
아래 코드는 console과 file에 적용되는 multiple appender 입니다. logger에 multipleappender를 추가하면 하나로 묶어 설정해줄 수 있습니다.
<logger name="com.jpa.shop.logger.LoggerService" additivity="false" level="debug">
<appender-ref ref="SAVE-TO-FILE"/>
<appender-ref ref="STDOUT"/>
</logger>
Spring Boot는 환경에 따라 다른 Logback 설정을 적용할 수 있도록 제공합니다. 따라서 개발환경일 때 console과 file 저장을 둘 다 설정하고
서비스 환경일 땐 file 저장만 하고 싶다면 설정을 통해 쉽게 가능합니다.
<springProfile name="dev">
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<logger name="com.jpa.shop.logger.LoggerService" additivity="false" level="debug">
<appender-ref ref="SAVE-TO-FILE"/>
<appender-ref ref="STDOUT"/>
</logger>
</springProfile>
<springProfile name="prod">
<root level="info">
<appender-ref ref="SAVE-TO-FILE"/>
</root>
<logger name="com.jpa.shop.logger.LoggerService" additivity="false" level="debug">
<appender-ref ref="SAVE-TO-FILE"/>
</logger>
</springProfile>
이를 위해선 logback.xml 파일을 logback-spring.xml로 이름변경해줘야 합니다. springProfile
을 사용하기 위해선 말이죠.
'개발공부 > SpringBoot' 카테고리의 다른 글
[SpringBoot] spring boot application.properties/yaml profile 설정 (0) | 2021.09.03 |
---|---|
logger spring xml (0) | 2021.07.01 |
String Boot - Test Driven Development(TDD) (0) | 2020.07.17 |
Spring Boot - Orientation (0) | 2020.07.14 |