<피드백 언제나 환영합니다! 댓글 감사합니다>
Apache Tomcat 운영중 stdout, stderr 같은 log의 경우 날짜별로 쌓이는게 아닌 한 log 파일에 쌓이게 된다.
이런부분 때문에 apache tomcat의 log를 막고 logback 이용하여 log를 관리할 예정이다.
들어가기전...
들어가기전 Profile.active 를 이용 다른 application.properties or application.yml 을 먼저 설정 해야 한다.
→ 무조건 필요한게 아니지만 logback 시작때 다시한번 언급 할 예정입니다. 아래 링크를 확인하여 설정을 할 수 있습니다.
application.proerteis 또는 .yml 파일에서도 설정을 할 수 있지만 세부적인 설정까지는 어렵습니다. 그래서
logback.properteis, logbakc-spring.xml 로 나누어 설정을과 예제를 보여드릴 예정 입니다.
Log를 왜 쓸까요??
너무 간단한 이야기 입니다. Log를 통해 우리는 개발과정 혹은 운영 과정에서 예상치 못한 어플리케이션의 문제를 진단 및 사용자 로그를 이용 분석하여 조금더 사용자에게 친화적인 환경을 구성할수 있습니다. 하지만 로깅을 하는 단계에서 로그 기준을 잡지 못하면 방대한양의 로그파일이 쌓여 의미있는 로그가 쌓이지 않습니다.
결국 효율적으로 로깅하는 방법이 중요합니다 → 실무마다 적용이 달라 우리는 사용하는 방법 위주로 공부 할 예정입니다.!!
스프링에서는 어떻게 사용 할까요??
Log4j와 LogBack으로 스프링 부트의 로그구현체를 사용 합니다. Logback 은 log4j 이후에 출시된 Java 기반 Logging Framework 중 하나로 가장 널리 사용되고 있습니다. SLF4j 의 구현체이며 Spring Boot 환경이라면 별도의 dependency 추가 없이 기본적으로 포함되어 있습니다. logback.properteis, logbakc-spring.xml 을 이용 log를 이용하여 관리할 예정입니다.
즉, logback은 Java / Spring 에 조금 친화적이며 후 Log4J를 이용 Log 관리를 알아보도록 하겠습니다.
- Log4J 보안 이슈
간단한 Log 표시 사용법
1. LoggerFactory 를 이용한 생성
package com.log.findlog.log1; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class log1Controller { private static final Logger log = LoggerFactory.getLogger(log1Controller.class); @GetMapping("/log1") public String log1() { log.info("hello log1"); return "ok"; } }
2. lombok @Slf4j 을 이용한 방법
package com.log.findlog.log2; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController public class log2Controller { @GetMapping("/log2") public String log1() { log.info("hello log2"); return "ok"; } }
로그 레벨 관련
Logback 은 5단계의 로그 레벨을 가진다.심각도 수준은 Error > Warn > Info > Debug > Trace 이다.
- ⛔️ Error : 예상하지 못한 심각한 문제가 발생하는 경우, 즉시 조취를 취해야 할 수준의 레벨
- ⚠ ️Warn : 로직 상 유효성 확인, 예상 가능한 문제로 인한 예외 처리, 당장 서비스 운영에는 영향이 없지만 주의해야 할 부분
- ✅ Info : 운영에 참고할만한 사항, 중요한 비즈니스 프로세스가 완료됨
- ⚙️ Debug : 개발 단계에서 사용하며, SQL 로깅을 할 수 있음
- 📝 Trace : 모든 레벨에 대한 로깅이 추적되므로 개발 단계에서 사용함
✨로그파일 작성하기
먼저 로그 관련하여 전반적인 코드를 먼저 작성하고 하나하나 뜯어보면서 하겠습니다.
- resources 폴더에 저장하면 됩니다.
application.properties
spring.profiles.active=dev
application-dev.properties
server.port=9090
logback-dev.properties
log.config.path=D:\\logs log.config.normal.filename=normal log.config.error.filename=error
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- springProfile --> <springProfile name="dev"> <property resource="logback-dev.properties" /> </springProfile> <!-- log file path --> <property name="LOG_PATH" value="${log.config.path}" /> <!-- log file name --> <property name="NOR_LOG_FILE_NAME" value="${log.config.normal.filename}" /> <!-- err log file name --> <property name="ERR_LOG_FILE_NAME" value="${log.config.error.filename}" /> <!-- pattern --> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <property name="LOG_PATTERN" value="%clr(%d{yy-MM-dd E HH:mm:ss.SSS}){magenta} %clr(%-5p) %clr(${PID}){yellow} %clr(---){faint} %clr([%15.15t]){cyan} %clr(%-45.45c){faint} %clr(::){red} %clr(%m){green}%n" /> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <!-- Console Appender --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${LOG_PATTERN}</pattern> </encoder> </appender> <!-- Nomal File Appender --> <appender name="NORMAL" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 파일경로 설정 --> <file>${LOG_PATH}/${NOR_LOG_FILE_NAME}.log</file> <!-- 출력패턴 설정 --> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <!-- Rolling 정책 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --> <fileNamePattern>${LOG_PATH}/${NOR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.zip</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- 파일당 최고 용량 kb, mb, gb --> <maxFileSize>5KB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --> <maxHistory>30</maxHistory> </rollingPolicy> </appender> <!-- Error File Appender --> <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>error</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <!-- Rolling 정책 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --> <fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- 파일당 최고 용량 kb, mb, gb --> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --> <maxHistory>30</maxHistory> </rollingPolicy> </appender> <!-- root레벨 설정 --> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="NORMAL" /> <appender-ref ref="ERROR" /> </root> <!-- 특정패키지 로깅레벨 설정 --> <logger name="com.log.findlog.log2" level="DEBUG" additivity="false"> <appender-ref ref="CONSOLE" /> <appender-ref ref="NORMAL" /> <appender-ref ref="ERROR" /> </logger> </configuration>
1. configuration 설정
configuration
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- springProfile --> <springProfile name="dev"> <property resource="logback-dev.properties" /> </springProfile> .... .... <configuration>
설정 정보들을 넣을 수 있다. 예로들어 application.properteis 에서 사용하는 profile 설정, properties resource를 사용하여 log 를 메시지화 하여 관리 할 수 있다.
2. path 설정 및 fileName 설정
path 설정 및 fileName
<!-- log file path --> <property name="LOG_PATH" value="${log.config.path}" /> <!-- log file name --> <property name="NOR_LOG_FILE_NAME" value="${log.config.normal.filename}" /> <!-- err log file name --> <property name="ERR_LOG_FILE_NAME" value="${log.config.error.filename}" />
logback-dev.properties 에서 설정한 메시지 들을 xml내에 사용가능한 proerty화(메시지화)되어 재사용이 가능하다.
3. pattern
pattern
<!-- pattern --> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <property name="LOG_PATTERN" value="%clr(%d{yy-MM-dd E HH:mm:ss.SSS}){magenta} %clr(%-5p) %clr(${PID}){yellow} %clr(---){faint} %clr([%15.15t]){cyan} %clr(%-45.45c){faint} %clr(::){red} %clr(%m){green}%n" /> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
로그를 적을시 패턴을 적어서 사용하기위해 이용 된다. 주로 콘솔의 log와 파일의 log 패턴을 분류해서 사용한다.
- clr : console에 색을 입혀 잘 보기 위해
4. console appender
console appender
<!-- Console Appender --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${LOG_PATTERN}</pattern> </encoder> </appender>
idea 에서 작업시 로그를 출력하기 위한 appender 이며 pattern에서 정의한 LOG_PATTERN의 정보를 사용한다.
5. normal fileAppender 출력 패턴 설정, rolling 설정
fileAppender 출력 패턴 설정
<appender name="NORMAL" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 파일경로 설정 --> <file>${LOG_PATH}/${NOR_LOG_FILE_NAME}.log</file> <!-- 출력패턴 설정 --> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <!-- Rolling 정책 --> .... </appender>
file appender 는 파일의 경로 출력패턴 rolling 설정들을 하는 곳입니다. 저같은 경우 normal과 error 파일들을 분류하여 설정 하였습니다. 파일의 경로와 log 파일에 찍히는 패턴을 설정 합니다. (2.path 설정, 3.pattern 에서 정의한 내요을 사용 합니다.)
rolling 설정
<!-- Rolling 정책 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 --> <fileNamePattern>${LOG_PATH}/${NOR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- 파일당 최고 용량 kb, mb, gb --> <maxFileSize>5KB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 --> <maxHistory>30</maxHistory> </rollingPolicy>
rolling 정책은 로그파일의 용량과 일정 용량을 넘어갈시 log파일의 이름을 새로 만들어저장 최대 보한 기한을 설정 하빈다.
fileNamePattern
: logfile의 지정 size 를 넘길시 새로운 이름을 부여해 저장합니다.
(zip, gz 로 만들경우 log 파일을 압축하여 저장 합니다. → .log 로 남는게 아닌 name에 부여되 이름의 log 파일을 압축합니다)
maxFileSize
: logfile의 size를 지정 할 수있으며 size가 오버되면 fileNamePattern
에 의해 이름이 정의 된다
maxHistory
: 로그파일의 최대 보관 주기(일) 로 되며 해당 설정일 이상이된 파일은 자동으로 제거 됩니다.
6. error fileAppender
error 와 관련된게 따로 분류한 이유는 error와 관련된 부분만 저장하기 위해서이다. normalfileAppdender 와 별 다를점이 없다 그래서 다른 점 만 확인하겠습니다.
error fileAppdender
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>error</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> .... </appender>
log level 중 error 만을 사용하기위해 입니다. level을 설정한후 onMatch onMismatch 설정으로 leve단위로 설정할 수 있습니다.
7. append-ref 설정
append-ref 설정
<!-- root레벨 설정 --> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="NORMAL" /> <appender-ref ref="ERROR" /> </root> <!-- 특정패키지 로깅레벨 설정 --> <logger name="com.log.findlog.log2" level="DEBUG" additivity="false"> <appender-ref ref="CONSOLE" /> <appender-ref ref="NORMAL" /> <appender-ref ref="ERROR" /> </logger> </configuration>
append-ref 에 들어갈 값은 append name들의 이름 입니다.
root
설정은 spring 의 전박적인 package의 log 설정과 level 설정 후 실행합니다.
logger
설정은 특정 pacakge에 관한 log 설정과 level 설정후 실행합니다.
console 또는 logfile 의 내용들을 실행하며 이전에 설정해놓은 appender 들을 실행하는 곳입니다.
마치며..
기본적인 사용법과 설정을 알아 보았습니다. 이걸로 apache에서 제공하는 log 보다는 이부분을 사용하여 log파일을 따로
관리하는게 이점이 크다고 생각 합니다. 여러 블로그들을 확인하여 본 결과 로그파일의 크기는 100MB 정도로 하고 180일을 주기로
log파일들을 관리를 한다고 합니다 (물론 이점이 무조건 맞다는 아닙니다) 다음 번에는 properties에서 설정 하는 법을 확인해보도록 하겠습니다.
감사합니다!!
참조
https://tecoble.techcourse.co.kr/post/2021-08-07-logback-tutorial/
[10분 테코톡] ☂️ 검프의 Logging(로깅) #1 - YouTube
[10분 테코톡] ☂️ 검프의 Logging(로깅) #2 - YouTube
Uploaded by Notion2Tistory v1.1.0