ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Springboot Logging 적용 - logback
    우아한 테크코스/이것저것 2020. 7. 29. 13:10
    반응형

    Springboot에서의 Logging

     Springboot에서는 Logging 설정을 자동적으로 지원

     slf4j 로깅 Facade를 통해 logback을 기본적으로 지원하고 있음

    slf4j란?

    더보기

    Simple Logging Facade for Java (SLF4J) LINK

     SLF4J는 다양한 로깅 프레임워크(java.util.logging / logback / log4j 등)에 대한 간단한 Facade* 또는 추상화 역할을 하여 사용자가 설정(deployment)하는 경우 원하는 로깅 프레임워크를 플러그인할 수 있도록 함

     로깅 API를 분리하면 애플리케이션과 특정 로깅 프레임워크간의 관계가 느슨해지고, 이를 통해 기존 또는 다른 코드와 쉽게 통합하거나 이미 다른 로깅을 사용한 프로젝트에 코드를 제공할 수 있음

    Facade 패턴
     - 어떤 서브시스템의 일련의 인터페이스에 대해 통합된 인터페이스를 제공
     - Facade에서 고수준 인터페이스를 정의하기 때문에 서브 시스템을 더 쉽게 사용할 수 있음

    기본 logging 해보기

    // BoardApplication
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.WebApplicationType;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class BoardApplication {
    
        public static void main(String[] args) {
            SpringApplication application = new SpringApplication(BoardApplication.class);
            // WepApplication 사용 안함 설정 - NONE
            application.setWebApplicationType(WebApplicationType.NONE);
            application.run(args);
        }
    }
    
    // AppRunner
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    import org.springframework.stereotype.Component;
    
    @Component
    // ApplicationRunner - 애플리케이션 실행 후 추가로 실행하고 싶은 것 구현할 때 사용
    public class AppRunner implements ApplicationRunner {
    
        // Logger 생성 - LoggerFactory.getLogger(클래스명)
        // lombok을 이용한다면, 클래스 위에 @Slf4j 애너테이션을 다는 것으로 대체할 수 있음
        // - @Slf4j 사용시 log라는 필드가 생겨서, log.info("") 이런 식으로 사용
        private Logger logger = LoggerFactory.getLogger(AppRunner.class);
    
        @Override
        public void run(ApplicationArguments args) {
            /* logging - 레벨별로 설정 가능
            logger.trace("A TRACE Message");
            logger.debug("A DEBUG Message");
            logger.info("An INFO Message");
            logger.warn("A WARN Message");
            logger.error("An ERROR Message");
            */
            logger.info("=======================");
            logger.info("Jamie's Spring Boot App");
            logger.info("=======================");
        }
    }
    

    결과 - Application 실행시, 로깅한 내용 확인됨

    Logging 설정하기 - application.properties

    # 콘솔 창에 출력되는 로깅 메세지를 색으로 구분해서 출력
    spring.output.ansi.enabled=always
    # 로그 메세지가 저장되는 디렉터리 (절대경로/상대경로 모두 가능)
    # 이렇게 설정하면, logs/spring.log로 LOG_FILE이 잡히고, LOG_PATH로는 
    logging.file.path=logs
    # 로그 레벨 - logging.level.{패키지 경로}를 통해 설정
    logging.level.com.github.jamie9504.board=DEBUG

     

    Logging Extentions(확장)

    Springboot에서는 기본적으로 logback 모듈을 제공, logback 모듈의 설정 정보를 logback-spring.xml 파일로 따로 관리할 수 있음

    Logback 확장이 가능한 이유

     Web Application 시작하면 classpath 내에서 환경 파일(logback.xml)을 검색해서 logback을 초기화시킴
    => Spring 구동 전의 시점
     Springboot의 경우 logback-spring.xml을 사용해 Spring이 logback을 구동할 수 있도록 지원해줌
    => profile이나 application.properties에 설정된 properties들을 읽어올 수 있음

    application.properties

    logging.level info를 전체에 적용

    profile 설정을 다중으로 할 수 있게 설정 적용 - 추후 application.properties를 환경별로 분리한다면 다양하게 적용할 수 있도록

    # 콘솔 창에 출력되는 로깅 메세지를 색으로 구분해서 출력
    spring.output.ansi.enabled=always
    # 로그 메세지가 저장되는 디렉터리 (절대경로/상대경로 모두 가능)
    logging.file.path=logs
    # 로그 레벨 - logging.level.{패키지 경로}를 통해 설정
    logging.level.root=DEBUG
    # profile 설정
    spring.profiles.include=file-logging,console-logging
    

    logback-spring.xml

    다중 profile을 위해 console-logging, file-logging 분리

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="60 seconds">
        <property name="LOG_PATH" value="${LOG_PATH}"/>
        <property name="LOG_FILE_NAME" value="spring"/>
        <property name="ERR_LOG_FILE_NAME" value="error"/>
        <property name="LOG_PATTERN"
            value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>
        <property name="LOG_CONSOLE_PATTERN"
            value="%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable"/>
    
        <springProfile name="console-logging">
            <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <pattern>${LOG_CONSOLE_PATTERN}</pattern>
                </encoder>
            </appender>
        </springProfile>
        <springProfile name="file-logging">
            <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <pattern>${LOG_PATTERN}</pattern>
                </encoder>
                <rollingPolicy
                    class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log
                    </fileNamePattern>
                    <timeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                        <maxFileSize>10MB</maxFileSize>
                    </timeBasedFileNamingAndTriggeringPolicy>
                    <maxHistory>30</maxHistory>
                </rollingPolicy>
            </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>${LOG_PATTERN}</pattern>
                </encoder>
                <rollingPolicy
                    class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log
                    </fileNamePattern>
                    <timeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                        <maxFileSize>10MB</maxFileSize>
                    </timeBasedFileNamingAndTriggeringPolicy>
                    <maxHistory>60</maxHistory>
                </rollingPolicy>
            </appender>
        </springProfile>
        <root>
            <springProfile name="console-logging">
                <appender-ref ref="CONSOLE"/>
            </springProfile>
    
            <springProfile name="file-logging">
                <appender-ref ref="FILE"/>
            </springProfile>
    
            <springProfile name="remote-logging">
                <appender-ref ref="REMOTE_LOG_SERVER"/>
            </springProfile>
        </root>
    </configuration>

    적용 결과

    logback이 아닌 다른 로깅 모듈로 바꾸고 싶다면?

     의존성 파일(build.gradle / pom.xml)에서 logback을 제거한 후, 다른 로깅 모듈 의존성을 추가

    Gradle

    // 제외
    configurations {
        all {
            compile.exclude module: 'spring-boot-starter-logging'
        }
    }
    
    // 추가 - 예. log4j2
    dependencies {
        compile 'org.springframework.boot:spring-boot-starter-log4j2'
    }

    Maven

    <dependency>
    <!-- 제거 -->
    <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    	<!-- 추가 - 예: log4j2 -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    

    참고하면 좋을 글

    https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-logging - 공식 문서

    https://meetup.toast.com/posts/149 - Springboot + logback 설명이 상세히 잘 나와있음

    https://www.baeldung.com/spring-boot-logging - Springboot logging 설명이 나와있음(영어)

    https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#core-properties

    - application.properties 관련 설정 공식 문서

    반응형

    댓글

Designed by Tistory.