본문 바로가기
Back-End/Spring

Spring Boot Logback 설정으로 로그파일 생성

by 어렵다어려웡 2021. 9. 4.

최근 회사에서 예외처리(에러) 및 엔드포인트에 대한 응답에 대한 데이터를 확인하기 위해서

직접 Slf4j 를 통해서 작성을 했으나 현재 동작시키고 있는 리눅스에서 백그라운드로 실행한다지만

 

좀더 실용성 있게 로그에 대한 정보를 파악하고 수집하고자 로그에 대한 정보를 파일로 저장해서

만들었으면 한다고 사수님께서 요청을 해주셨다.

 

직접 하는 과정에서 알아두면 좋을거 같고 혹여 다른 프로젝트를 스프링 프레임워크로 사용할 때도

적용시키면 괜찮을거 같아서 작성해본다.

 

기본적으로 스프링 부트는 프로퍼티파일에서 로그에 대한 레벨을 설정해서 사용이 가능하다.

 

보통 로그레벨은 TRACE < DEBUG < INFO < WARN < ERROR 순으로 설정되어있고 

지정한 레벨에 따라서 그 하위 레벨의 로그까지 같이 찍을 수 있다.

// application.properties
logging.level.root = info

예를 들어 위처럼 사용하면 INFO, WARN, ERROR 로그까지 볼수 있다는 점이다.

 

1. logback-spring.xml 파일 생성

해당 파일을 생성하는 이유는 사실 로그성데이터에 대한 상세한 설정 즉, 커스텀할때 사용된다.

스프링 부트는 resource 경로에 해당파일을 참조해서 로그에 대한 설정을 한다.

1-1 스프링부트의 참조 순서.

.1) resource 경로의 logback-spring.xml 파일을 읽는다.

 2) 만약 logback-spring.xml 파일이 없다면 properties 파일을 읽는다.

 3. 같이 있을 경우 logback-srping.xml 모두 적용되지만 properties 파일이 먼저 적용된다.

 

결과적으로 logback-spring.xml 파일을 통해서 스프링 부트가 Logback을 지원해준다는 것.

 

 

2. logback-spring.xml 파일 설정 

logback의 설정을 통해서 얻을 수 있는 기능이 있다.

 

* 로그 파일 생성

* 파일 관리

* 로그 패턴 설정

등등

 

실행하는 profile 에 따라서 설정또한 개별적으로 가능하다.

 

logback-spring.xml 전체 코드

<?xml version="1.0" encoding="UTF-8"?>
<!-- 15초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="15 seconds">
    <!-- Server Log Config -->
    <springProfile name="dev">
        <property resource="application.properties"/>
        <!-- log file path -->
        <property name="LOG_PATH" value="${log.config.path}"/>
        <!-- log file name -->
        <property name="LOG_FILE_NAME" value="${log.config.filename}"/>
        <!-- err log file name -->
        <property name="ERR_LOG_FILE_NAME" value="${error.log.config.filename}"/>
        <!-- log pattern -->
        <property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss} [%thread] [%logger{0}-%M:%line] - %msg%n "/>

        <appender name="DEV_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>${LOG_PATTERN}</pattern>
            </encoder>
        </appender>

        <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>
            <!-- Rolling 정책 (파일 관리설정) -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
                <fileNamePattern>${LOG_PATH}/${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>
                <!--<MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex>-->
            </rollingPolicy>
        </appender>

        <appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <!-- 에러로그를 설정하고 로그의 레벨이 맞으면 onMatch, 아니라면 onMismatch  -->
                <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>
            <!-- Rolling 정책 -->
            <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>30</maxHistory>
            </rollingPolicy>
        </appender>
        <root>
            <appender-ref ref="DEV_CONSOLE"/>
            <appender-ref ref="FILE"/>
            <appender-ref ref="Error"/>
        </root>

    </springProfile>
</configuration>

 

우선 단계적으로 설정을 확인해보자

    <springProfile name="dev">
        <property resource="application.properties"/>
        <!-- log file path -->
        <property name="LOG_PATH" value="${log.config.path}"/>
        <!-- log file name -->
        <property name="LOG_FILE_NAME" value="${log.config.filename}"/>
        <!-- err log file name -->
        <property name="ERR_LOG_FILE_NAME" value="${error.log.config.filename}"/>
        <!-- log pattern -->
        <property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss} [%thread] [%logger{0}-%M:%line] - %msg%n "/>
		---중략---

* springProfile - name속성을 통해서 어떤 profile을 활성화했는지에 따라서 설정을 할수 있다.

위 설정의 경우 profile 의 활성화가 'dev' 일 경우 'application.properties' 파일을 참조한다는 것을 의미한다.

 

그러면 그 하위 <property>들은 참조하고 있는 properties 파일을 확인하여 설정되어있는 프로퍼티를 확인하고 

그 값을 얻어낸다

//application.properties
log.config.path=/var/log
log.config.filename=console
error.log.config.filename=error

LOG_PATTERN 프로퍼티는 말 그대로 로그의 형식을 의미한다.

 

다음은 에러로그 발생시 만들어내는 파일에 대한 설정이다.

<filter> 태그를 제외하고 그외 설정은 동일하므로 밑의 설정만 설명.

<appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <!-- 에러로그를 설정하고 로그의 레벨이 맞으면 onMatch, 아니라면 onMismatch  -->
                <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>
            <!-- 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>

* <filter> 태그 

<level> 태그로 로그의 레벨을 확인한다.  만약 레벨이 일치하면 <onMatch>, 아니라면 <onMismatch> 태그의

속성을 사용해서 어떤식으로 결과를 보여줄지 처리를 한다.

 

* <file> 태그

말 그대로 파일 생성시 나타낼 이름의 패턴을 지정한다.

 

* <encoder>, <pattern> 태그

로그를 출력하는 공간이다.

 

* <rollingPolicy> 태그

로그성 파일에 대한 관리에 있어서 중요한 설정이다.

파일의 보관 주기를 설정할 수 있고 파일크기에 따라서 또다른 파일을 생성하는 등의 관리가 가능하다.

만약  <timeBasedFileNamingAndTriggeringPolicy> 태그를 지울 경우 하나의 파일에 하루치 로그를

저장해둘수 있다, 하지만 그럴 경우 성능에 살짝 지장을 줄 가능성이 존재한다.

 

 

<root>
  <appender-ref ref="DEV_CONSOLE"/>
  <appender-ref ref="FILE"/>
  <appender-ref ref="Error"/>
</root>

* <root> 태그

해당 설정들을 적용할 때 사용한다.

필자의 경우 실제 전체 코드가 이렇다.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 15초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="15 seconds">
    <!-- Local Log Config -->
    <springProfile name="local">
        <property resource="application.properties"/>

        <property name="LOG_PATTERN" value=" %d{yy-MM-dd HH:mm:ss} %highlight(%-5level) [%thread] [%logger{0}-%M:%line] - %msg%n "/>
        <!-- Console Appender -->
        <appender name="LOCAL_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>${LOG_PATTERN}</pattern>
            </encoder>
        </appender>
        <root>
            <appender-ref ref="LOCAL_CONSOLE"/>
        </root>
    </springProfile>

    <!-- Server Log Config -->
    <springProfile name="dev">
        <property resource="application.properties"/>
      
		--중략--
        
    </springProfile>
</configuration>

직접 로컬에서 사용할때는 파일이 필요하지 않기 때문에

LOG_PATTERN 만 설정해줘서 파일생성에 대한 설정은 하지 않았으며

 

서버에서 사용할 dev 의 경우 로그파일을 생성해줘야 하기 때문에 포스팅에 사용했던 코드들이 존재한다.

 

만약 profile에 상관없이 한번의 설정을 모두 적용시키고 싶다면 아래와 같이한다.

<?xml version="1.0" encoding="UTF-8"?>
<!-- 15초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
<configuration scan="true" scanPeriod="15 seconds">
    <!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다.-->
    <!-- Local Log Config -->
    <springProfile name="local">
     <!-- 해당파일의 ${log.config.filename} 등등의 프로퍼티를 읽어온다.
        <property resource="application.properties"/>
    </springProfile>

    <!-- Server Log Config -->
    <springProfile name="dev">
        <property resource="application.properties"/>
    </springProfile>
      
      --중략-- (파일설정코드들)
      
      <root>
        <appender-ref ref="DEV_CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="Error"/>
      </root>

</configuration>