반응형
Logback 이란?
- 자바 오픈소스 로깅 프레임워크, SLF4J의 구현체
- log4j, log4j2 등과 성능을 비교했을 때에도 logback이 더 훌륭한 성능 (괸련 링크)
- spring-boot-starter-web 안에 spring-boot-starter-logging에 구현체 존재
- Spring Boot의 경우 logback-spring.xml 파일을 resources 디렉토리에 만들어서 참조
Logback의 참고 순서
- classpath(resources디렉토리 밑)에 logback-spring.xml파일이 있으면 설정파일을 읽음
- logback-spring.xml파일이 없다면 .yml(.properties)파일의 설정을 읽음
- logback-spring.xml파일과 .yml(.properties)파일이 동시에 있으면 .yml(.properties) 설정파일을 적용 후 xml파일이 적용된다.
Spring Boot의 기본 설정
base.xml
<included>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</included>
- <include resource=".../defaults.xml">
- defaults.xml에서 추가로 설정을 읽어옴
- Console Log Pattern과 File Log Pattern의 기본값이 정의되어 있음
- 그 외의 tomcat이나 hibernate 등의 모듈의 log level 설정이 되어 있음
- <property name="LOG_FILE" ...>
- ${LOG_FILE}이 없으면 ${LOG_PATH}를 호출
- ${LOG_PATH}가 없으면 ${LOG_TEMP}를 호출
- 이러한 형식으로 application.yml의 property를 불러오고 있음
- <include resource=".../console-appender.xml">
- Console Appender 설정을 읽음
- <include resource=".../file-appender.xml">
- File Appender 설정을 읽음
logback-spring.xml
- appender와 logger 크게 두개로 구분됨
- scanPeriod 설정을 통해 해당 기간마다 로그 파일(logback-spring.xml)이 바뀌었는지 검사하고 바뀌면 갱신
appender
- log의 형태를 설정, 로그 메시지가 출력될 대상을 결정하는 요소
- 콘솔, 파일 등
- appender의 종류는 여길 참고
appender-ref
- ref에 선언된 name의 appender를 찾아 추가한다.
root, logger
- 설정한 appender를 참조하여 package와 level을 설정
- root : 전역 설정, 지역적으로 선언된 logger 설정이 있다면 해당 logger 설정이 default로 적용
- logger : 지역 설정, additivity 값은 root 설정 상속 유무 설정
property
- 설정파일에서 사용될 변수값 선언
Logback 사용법
log 객제 정의
로깅을 하고 싶은 클래스에 다음과 같이 Logger를 받아온다.
private final Logger log = LoggerFactory.getLogger(ControllerAdvice.class);
@Slf4j 어노테이션 사용
Lombok을 사용하여 어노테이션 하나만 붙이면 간단하게 log 변수로 Logger 객체를 사용할 수 있다.
Loging Level
TRACE < DEBUG < INFO < WARN < ERROR
- ERROR : 요청을 처리하는 중 오류가 발생한 경우
- WARN : 처리 가능한 문제, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄
- INFO : 상태변경과 같은 정보성 로그 표시
- DEBUG : 프로그램을 디버깅하기 위한 정보를 표시
- TRACE : Debug보다 훨씬 상세한 정보를 나타냄
위의 순서대로 높은 레벨을 가지며, 출력 레벨의 설정에 따라 설정 레벨 이상의 로그를 출력 한다.
놀토의 Logging 전략
현재 놀토 프로젝트의 logback-spring.xml을 좀 정리해서 올렸다.
완벽한 로깅 전략이 아닌, 우리의 기준으로 세운 로깅 전략이니 참고하시길!
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty name="SLACK_WEBHOOK_URI" source="logging.slack.webhook-uri"/>
<appender name="LOCAL_CONSOLE_POLICY" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} %highlight([%-5level]) [%thread] %cyan([%logger{36}]) - %m%n
</Pattern>
</layout>
</appender>
<appender name="SQL_FILE_POLICY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/logs/nolto-sql.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/logs/dateLog/%d{yyyy_MM_dd}_%i.nolto-sql.log
</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>14</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<charset>utf8</charset>
<Pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger{36}] - %m%n</Pattern>
</encoder>
</appender>
<appender name="INFO_FILE_POLICY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<file>${LOG_PATH}/logs/nolto-info.log</file>
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger{36}] - %m%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/logs/dateLog/%d{yyyy_MM_dd}_%i.nolto-info.log
</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>14</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="ERROR_FILE_POLICY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<file>${LOG_PATH}/logs/nolto-error.log</file>
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger{36}] - %m%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/logs/dateLog/%d{yyyy_MM_dd}_%i.nolto-error.log
</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>14</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="SLACK" class="com.github.maricn.logback.SlackAppender">
<webhookUri>${SLACK_WEBHOOK_URI}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[DEV] %-4relative [%thread] %-5level %class - %msg%n</pattern>
</layout>
<colorCoding>true</colorCoding>
</appender>
<appender name="ASYNC_SLACK" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="SLACK"/>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<appender name="PROD-SLACK" class="com.github.maricn.logback.SlackAppender">
<webhookUri>${SLACK_WEBHOOK_URI}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[PROD] %-4relative [%thread] %-5level %class - %msg%n</pattern>
</layout>
<colorCoding>true</colorCoding>
</appender>
<appender name="PROD_ASYNC_SLACK" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="PROD-SLACK"/>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<root level="INFO">
<springProfile name="local">
<appender-ref ref="LOCAL_CONSOLE_POLICY"/>
</springProfile>
<springProfile name="dev">
<appender-ref ref="ERROR_FILE_POLICY"/>
<appender-ref ref="INFO_FILE_POLICY"/>
<appender-ref ref="ASYNC_SLACK"/>
</springProfile>
<springProfile name="prod">
<appender-ref ref="ERROR_FILE_POLICY"/>
<appender-ref ref="INFO_FILE_POLICY"/>
<appender-ref ref="PROD_ASYNC_SLACK"/>
</springProfile>
<springProfile name="file-sql-logging">
<logger name="org.hibernate.SQL" level="TRACE">
<appender-ref ref="SQL_FILE_POLICY"/>
</logger>
<logger name="org.hibernate.type.descriptor" level="TRACE">
<appender-ref ref="SQL_FILE_POLICY"/>
</logger>
</springProfile>
</root>
</configuration>
- LOG_PATH: 해당 변수의 값은 dev와 prod 환경 설정 yml에서 가지고 있음
- SLACK_WEBHOOK_URI: 외부에 노출되면 계속해서 URL이 변하기에 각 환경의 yml에 해당 정보를 숨김
여러 전략의 appender를 만들어 두고 profile 설정별로 이를 조합하여 사용하도록 하였다.
- local: info 레벨의 console 로깅
- dev: info 레벨의 file 로깅, error 레벨의 file, slack 로깅, trace 레벨의 sql 쿼리를 file 로깅
- prod: info 레벨의 file 로깅, error 레벨의 file, slack 로깅
➕ Slack으로 알림받기
참고 자료
반응형
'스프링 부트' 카테고리의 다른 글
S3를 사용하는 환경에서 LocalStack을 통한 통합 테스트 (2) | 2021.08.21 |
---|---|
@PostConstruct와 @PreDestroy (0) | 2021.08.17 |
[ERROR] Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 (0) | 2021.08.14 |
ApplicationEventPublisher 적용과 그 안에서의 삽질 (1) | 2021.08.14 |
스프링 부트 Profile별로 다른 환경 구성 (0) | 2021.08.06 |