스프링 logback

오동근·2023년 1월 14일
0

spring

목록 보기
1/1

Logback 으로 쉽고 편리하게 로그 관리를 해볼까요? ⚙️ (techcourse.co.kr)

Spring 로그 설정하기 - Logback (velog.io)

Logback 은 log4j 이후에 출시된 Java 기반 Logging Framework 중 하나로 가장 널리 사용되고 있다. SLF4j 의 구현체이며 Spring Boot 환경이라면 별도의 dependency 추가 없이 기본적으로 포함되어 있다.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;

@RestController
public class LogController {

    private final Logger logger = LoggerFactory.getLogger("LoggerController 의 로그");

    @GetMapping("/log")
    public void log() {
        logger.info("로깅 발생!");
    }
}

간단한 로그를 찍는 과정은 다음과 같다.

[2021-08-07 18:03:03:7491][http-nio-8080-exec-1] INFO LoggerController 의 로그 - 로깅 발생!

다음과 같은 로그가 찍힌다.


로그 레벨은 5가지가 있고, 다음과 같다.

  • ⛔️ Error : 예상하지 못한 심각한 문제가 발생하는 경우, 즉시 조취를 취해야 할 수준의 레벨
  • ⚠ ️Warn : 로직 상 유효성 확인, 예상 가능한 문제로 인한 예외 처리, 당장 서비스 운영에는 영향이 없지만 주의해야 할 부분
  • ✅ Info : 운영에 참고할만한 사항, 중요한 비즈니스 프로세스가 완료됨
  • ⚙️ Debug : 개발 단계에서 사용하며, SQL 로깅을 할 수 있음
  • 📝 Trace : 모든 레벨에 대한 로깅이 추적되므로 개발 단계에서 사용함

콘솔 로그의 수준을 변경하는 방법은 application.yml 과 logback-spring.xml 에서 설정하는 방법이 있다. 세부적인 설정을 위해서는 logback-spring.xml 로 관리하는 편이 더 좋다. 설정법을 알아보자.

  • 설정 코드
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration><!-- 이 곳에 추가할 기능을 넣는다. -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    //appender + 어디에 추가할지
       <layout class="ch.qos.logback.classic.PatternLayout">
         <Pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{36} - %msg%n</Pattern>
    //출력 형식을 지정한다.
       </layout>
     </appender>
    </configuration>
    다양한 설정들…
    <appendername="INFO_LOG"class="ch.qos.logback.core.rolling.RollingFileAppender"><file>./logs/info.log</file> 
    <!-- 파일을 저장할 경로를 정한다 -->
       <filterclass="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch> 
    <!-- 해당 레벨만 기록한다. -->
         <onMismatch>DENY</onMismatch> 
    <!-- 다른 수준의 레벨은 기록하지 않는다.(상위 레벨도 기록 안함), 상위 수준의 레벨에 대한 기록을 원하면 ACCEPT 로 하면 기록된다. -->
       </filter> 
    <!-- 레벨별 필터링이 필요없을 경우 filter class 관련된 부분을 삭제하면 됨-->
       <encoder><pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern> 
    <!-- 해당 패턴 네이밍으로 현재 로그가 기록됨 -->
       </encoder><rollingPolicyclass="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>./was-logs/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> 
    <!-- 해당 패턴 네이밍으로 이전 파일이 기록됨 -->
         <timeBasedFileNamingAndTriggeringPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize> <!-- 한 파일의 최대 용량 -->
         </timeBasedFileNamingAndTriggeringPolicy><maxHistory>180</maxHistory> 
    <!-- 한 파일의 최대 저장 기한 -->
       </rollingPolicy></appender>
  • 설정되어 있는 코드 설명
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <property name="LOGS_PATH" value="./logs"/>
        <property name="PAST_LOGS_PATH" value="./was-logs"/>
        <!-- <property name="LOGS_PATH" value="/home/ubuntu/logs" />
        <property name="PAST_LOGS_PATH" value="/home/ubuntu/was-logs"/> -->
    
    // LOGS/PATH 지정해서 밑에서 바인딩해준다.
    
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{36} - %msg%n</Pattern>
            </layout>
        </appender>
    //기본 STDOUT (콘솔에 출력하는 코드)
    
        <appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${ LOGS_PATH }/info.log</file>
            <encoder>
                <pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${PAST_LOGS_PATH}/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <maxHistory>10</maxHistory>
            </rollingPolicy>
        </appender>
    //info.log 전체 다출력하는 로그 
    
        <appender name="ERROR_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${ LOGS_PATH }/error.log</file>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>     //에러 레벨
                <onMatch>ACCEPT</onMatch>    // 에러 레벨 허용
                <onMismatch>DENY</onMismatch>  //에러 레벨이 아니면 거부
            </filter>
            <encoder>  //문자 패턴 밑에 더 서술함
                <pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    //File Name 경로 (일자 별로 백업 저장)
                <fileNamePattern>${PAST_LOGS_PATH}/ERROR.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MB</maxFileSize>   //FILE 최대 사이즈는 10메가
                </timeBasedFileNamingAndTriggeringPolicy>
                <maxHistory>10</maxHistory>   //10일동안 저장
            </rollingPolicy>
        </appender>
    //error.log 전체에서 에러만 출력하는 로그 
        <include resource="amazon-appender.xml"/>
        <include resource="ali-appender.xml"/>
        <include resource="ebay-appender.xml"/>
    //include로 다른 파일에서 가져옴 (너무 길어서 나눠놓음)
    
        <logger name="AmazonLogger" level="debug" additivity="false">
            <appender-ref ref="AmazonReader" />   //AmazonReader appender는 파일로 받아옴
            <appender-ref ref="STDOUT" />     //STDOUT은 그냥 콘솔에 출력 
        </logger>
    //기본 level이 debug (개발 단계에서 trace 빼고 다 가져오기 위함 
        <logger name="AliLogger" level="debug" additivity="false">
            <appender-ref ref="AliReader" />
            <appender-ref ref="STDOUT" />
        </logger>
        <logger name="eBayLogger" level="debug" additivity="false">
            <appender-ref ref="eBayReader" />
            <appender-ref ref="STDOUT" />
        </logger>
    
        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="INFO_LOG" />
            <appender-ref ref="ERROR_LOG" />
        </root>
    // root에서는 전체를 다룸 (STDOUT, INFO_LOG, ERROR_LOG가 기본으로 설정되어있음)
    </configuration>
%m : 로그내용이 출력
 %p : trace > debug > info > warn > error 등의 priority 출력
 %r : 어플리케이션이 시작되어 로깅이벤트가 발생하는 시점까지의 경과시간을 밀리세컨드로 출력
 %c : 예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
 %n :  플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다
 %d : 로깅이벤트가 일어나 날짜 출력 ( 프로그램의 실행속도를 느리게 한다.)
     예) %d{HH:mm:ss} 또는 %d{dd MMMM yyyy HH:mm:ss}
 %C : 호출자의 클래스명 출력
    예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
 %M : 로깅이 발생한 method 이름을 나타냅니다.
 %F : 로깅이 발생한 프로그램 파일명을 나타냅니다.
 %l : 로깅이 발생한 caller의 정보를 나타냅니다
 %L : 로깅이 발생한 caller의 라인수를 나타냅니다
 %x : 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다.
 %X : 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다.
 %% : % 표시를 출력하기 위해 사용한다.
 %t : 로그이벤트가 발생된 쓰레드의 이름을 출력합니다

localhost:8080/api/log로 들어가면

다음과 같이 시간별로 로그가 찍힌다.

warn.log의 메모리 제한이 걸렸거나 일자가 넘어가면

waslog에 기록된다.

  • slf4j 와 LoggerFactory
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// LoggerFactory 사용 시
private static final Logger LOG = LoggerFactory.getLogger(class명.class);

// lombok 사용 시
@Slf4j
public class 클래스명 {
	public void 메소드명() {
    	log.info("...");
    }
}
profile
꾸준히 열심히

0개의 댓글