본문 바로가기
Java/Java

Spring Logback 설정

by ddss6565 2023. 7. 16.

Spring은 logback.xml
Spring Boot는 logback-spring.xml

 

build.gradle

configurations.all {
    exclude group: 'commons-logging', module: 'commons-logging'
}
dependencies {
    compile group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0-alpha1'
    compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '2.0.0-alpha1'
    compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.0-alpha5'
}

 

 

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <property name="LOG_PATH" value="logs" />
    <property name="LOG_FILE_NAME" value="log" />

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/archive/${LOG_FILE_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>7</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
        </layout>
    </appender>

    <logger name="jdbc.sqltiming" level="WARN" additivity="false" />
    <logger name="jdbc.audit" level="OFF" />
    <logger name="jdbc.resultset" level="OFF" />
    <logger name="jdbc.resultsettable" level="OFF" />
    <logger name="jdbc.sqlonly" level="OFF" />
    <logger name="jdbc.connection" level="OFF" />

    <root level="WARN">
        <appender-ref ref="FILE" />
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

 

로그 필터링

implementation 'org.codehaus.janino:janino:3.1.8'
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
        <evaluator>
            <expression>message.contains("NOT_SQL_LOG")</expression>
        </evaluator>
        <onMismatch>NEUTRAL</onMismatch>
        <onMatch>DENY</onMatch>
    </filter>
    <encoder>
        <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
    </encoder>
</appender>
-- NOT_SQL_LOG
SELECT *
  FROM USERS

onMismatch, onMatch

ACCEPT 허용
DENY 거부
NEUTRAL 중립

필터가 여러개인 경우 ACCEPT와 DENY의 경우 바로 값이 리턴되어서 적용 됨.
순서대로 모든 필터를 검증하려면 NEUTRAL 값 사용.

 

로그 레벨 필터링

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
    </filter>
    <file>logs/error.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>logs/archive/error-%d{yyyy-MM-dd}.%i.log
        </fileNamePattern>
        <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>10mb</maxFileSize>
        </timeBasedFileNamingAndTriggeringPolicy>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
    </encoder>
</appender>

pattern 유형

패턴의미

%d 시간(yyyy-MM-dd HH:mm:ss, SSS형태)
%date{format} 원하는 형태로 시간 정보 출력 예) %date{yyyy.MM.dd HH:mm:ss.SSS}
%logger{length} Logger이름. {length}는 최대 자리수.
%thread 현재 스레드 이름
%-5level 로그 레벨 5는 출력 고정폭 값
%line 로그 라인
%msg 로그 메시지
%n 개행(new line) 처리
<!-- [2022.10.12 14:29:49] [Executor-10] [c.d.d.m.MigrationService           :97] INFO  2011-10 MigrationService 0/100 -->
<pattern>%d{[yyyy.MM.dd HH:mm:ss]} [%-35.35c{1}:%line] %-5p %msg%n</pattern>
<!-- 2022-10-12 | 14:38:37.310 | Executor-20          |  INFO | c.d.d.m.MigrationService  | 2022-05 MigrationService.run() 종료 1s -->
<pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>

로그 필터링 응용(Long Query 조회)

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">

    <appender name="SQL-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/sql/sql.log</file>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <matcher>
                    <name>matcher</name>
                    <regex>executed in [0-9]{4,}</regex>
                </matcher>
                <expression>matcher.matches(formattedMessage)</expression>
            </evaluator>
            <onMismatch>DENY</onMismatch>
            <onMatch>ACCEPT</onMatch>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>sql/sql.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>7</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <appender name="SQL-FILE-ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="SQL-FILE" />
        <queueSize>4096</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <includeCallerData>true</includeCallerData>
        <neverBlock>false</neverBlock>
    </appender>
    
    <logger name="jdbc.sqltiming" level="INFO" additivity="false">
        <appender-ref ref="SQL-FILE-ASYNC" />
    </logger>
    <logger name="jdbc.audit" level="OFF" />
    <logger name="jdbc.resultset" level="OFF" />
    <logger name="jdbc.resultsettable" level="OFF" />
    <logger name="jdbc.sqlonly" level="OFF" />
    <logger name="jdbc.connection" level="OFF" />

    <root level="INFO">
    </root>
 </configuration>

비동기 로그

별도의 Thread를 생성하여 로그를 출력하는 방법.
※로그 손실 가능성 있음.

<configuration scan="true" scanPeriod="30 seconds">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
        </layout>
    </appender>

    <appender name="STDOUT-ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="STDOUT" />
        <!-- queue의 사이즈 -->
        <queueSize>4096</queueSize>
        <!-- queue의 용량이 일정비율 이상 채워졌을 때 해당 비율 만큼 trace, debug, info level의 event를 삭제 함 -->
        <!-- 기본 20(20%), 0으로 할 경우 삭제하지 않음 -->
        <discardingThreshold>20</discardingThreshold>
        <!-- 로그를 호출한 라인수 정보 취득(성능에 영향 있음.) -->
        <includeCallerData>false</includeCallerData>
        <!-- queue에 용량이 가득찰 경우 blocking 상태에 빠지게 되는데, true로 하게 되면 log를 삭제하면서 계속 진행함. -->
        <neverBlock>true</neverBlock>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="STDOUT-ASYNC" />
    </root>

</configuration>

 

FileAppender

가동할 때 마다 파일로그를 갱신하고 싶을 경우
RollingFileAppender는 append 옵션이 true로 고정되어 있으므로
FileAppender를 이용해야 함.

 

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- true로 할 경우 항상 새로운 파일이 생성 됨. -->
    <append>false</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
    </filter>
    <file>logs/error/error.log</file>
    <encoder>
        <pattern>%d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %-5level | %-25.25logger{25} | %-4line | %msg%n</pattern>
    </encoder>
</appender>

 

반응형

'Java > Java' 카테고리의 다른 글

Spring @Async 어노테이션 사용  (0) 2023.07.16
Java Optional 사용법  (0) 2023.07.16
Java FX + Eclipse 개발 세팅  (0) 2023.07.16
Java에서 EzTransXP(일본어번역기) 사용법  (0) 2021.06.07
AES256 암복호화  (0) 2021.06.07

댓글