티스토리 뷰

728x90
반응형

log4j2란?


  • 어플리케이션에서 로그를 남기기 위한 기능이며 logging framework에서 제공하고 있는 대표적인 하나입니다.
  • logback에 비해 멀티 쓰레드환경에서 10배 가량 성능이 좋다고 알려져 있습니다.

 

system.out.println()
  • system.out.println() 을 사용해 디버깅을 위한 메세지를 출력할 수 있지만 이는 프로그램의 성능을 저하시킬 우려가 있습니다. 이에대해 우리는 logging framework를 이용해야합니다.

 

LOG LEVEL
  • 아래 사진처럼 로그 레벨이 존재하며 순서는 ALL -> OFF 입니다.

 

Gradle 적용
  • log4j2는 2021년 하반기에 큰 이슈가 있었습니다. 그래서 버전을 2.15.0 버전 이상을 사용해야하지만 2.16.0 버전에는 미흡한 문제가 있다고하여 2.17.1 버전을 사용하게 되었습니다.
  • 또한 org.springframework.boot:spring-boot-starter-web에는 기본적인 logging framework가 내재되어 있습니다.
  • springboot는 기본적으로 logback을 제공하고 있습니다. 그렇기 때문에 기본적으로 내제되어있는 모듈을 exclude해주어야 오류가 발생하지 않습니다.
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.17.1'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.17.1'
implementation group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '2.17.1'
implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.17.1'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.32'
implementation group: 'org.slf4j', name: 'jul-to-slf4j', version: '1.7.32'

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

 

application.yml 설정
  • log4j2.xml을 경로를 설정해줍니다. log4j2.xml은 resources 폴더 내부에 위치하여 있습니다.
logging:
  config: classpath:log4j2.xml

 

log4j2.xml 설정
  • 해당 용도에 맞게 로그파일을 분리해줍니다.
  • 일반 로그파일 : log.log
  • 디버그용 로그파일 : debug.log
  • 에러용 로그파일 : error.log
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">
    <!--변수 설정-->
    <Properties>
        <Property name="BASE_DIR">./logs</Property> <!--로그 파일 경로-->
        <Property name="LOG_FORMAT">[%date{yyyy-MM-dd HH:mm:ss}][%level][%file:%line] %msg%n</Property><!--로그 출력 형태-->
    </Properties>

    <Appenders>
        <!-- 콘솔 로그-->
        <Console name="Console-Appneder" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_FORMAT}"/>
        </Console>

        <!-- 로그 파일-->
        <RollingFile name="File-Appneder" fileName="${BASE_DIR}/log.log" filePattern="${BASE_DIR}/%d{yyyy-MM-dd}.log.zip">
            <PatternLayout pattern="${LOG_FORMAT}"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="15MB"/>                  <!-- 15MB 용량이 초과시 DefaultRolloverStrategy 정책만큼 넘버링 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- 일별 로그 파일 생성-->
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${BASE_DIR}">
                    <IfAccumulatedFileCount exceeds="4"/>   <!-- log 파일이 4개 이상일때 예전 log 파일 삭제 -->
                    <IfFileName glob="*.log"/>   <!-- 삭제할 파일명 -->
                    <IfLastModified age="3d"/>   <!-- 3일이 경과한 로그파일은 자동 삭제 -->
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 디버그 로그 파일-->
        <RollingFile name="DEBUG-Appneder" fileName="${BASE_DIR}/debug.log" filePattern="${BASE_DIR}/%d{yyyy-MM-dd}.debug-logs.zip">
            <PatternLayout pattern="${LOG_FORMAT}"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="15MB"/>                  <!-- 15MB 용량이 초과시 DefaultRolloverStrategy 정책만큼 넘버링 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- 일별 로그 파일 생성-->
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${BASE_DIR}">
                    <IfAccumulatedFileCount exceeds="4"/>   <!-- log 파일이 4개 이상일때 예전 log 파일 삭제 -->
                    <IfFileName glob="*.log"/>   <!-- 삭제할 파일명 -->
                    <IfLastModified age="3d"/>   <!-- 3일이 경과한 로그파일은 자동 삭제 -->
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 에러 로그 파일-->
        <RollingFile name="ERROR-Appneder" fileName="${BASE_DIR}/error.log" filePattern="${BASE_DIR}/%d{yyyy-MM-dd}.error-logs.zip">
            <PatternLayout pattern="${LOG_FORMAT}"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="15MB"/>                  <!-- 15MB 용량이 초과시 DefaultRolloverStrategy 정책만큼 넘버링 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- 일별 로그 파일 생성-->
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${BASE_DIR}">
                    <IfAccumulatedFileCount exceeds="4"/>   <!-- log 파일이 4개 이상일때 예전 log 파일 삭제 -->
                    <IfFileName glob="*.log"/>   <!-- 삭제할 파일명 -->
                    <IfLastModified age="3d"/>   <!-- 3일이 경과한 로그파일은 자동 삭제 -->
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console-Appneder"/>
            <AppenderRef ref="File-Appneder"/>
        </Root>

        <!-- springframework에서 발생하는 DEBUG 출력 -->
        <Logger name="org.springframework" level="DEBUG" additivity="false">
            <AppenderRef ref="DEBUG-Appneder"/>
        </Logger>

        <!-- 내 패키지에서 발생하는 error 출력 -->
        <Logger name="로그를 출력하고자하는 패키지경로" level="ERROR" additivity="false">
            <AppenderRef ref="ERROR-Appneder"/>
        </Logger>
    </Loggers>
</Configuration>

 

테스트 확인
  • 로그를 남길때는 필수 정보만 남기는것이 효율적이라고 생각합니다. 예를 들어 시간, 메세지, 누가, 어떤 행위 이러한 정보만 남기는 것이 좋다고 생각을 합니다.

DEBUG LOG

 

ERROR LOG

 

log4j2를 이용하여 SQL 로그 남기기


Gradle 적용
implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'

 

log4jdbc.log4j2.properties 파일 생성

 

  • resources/log4jdbc.log4j2.properties 경로에 파일을 만들어 줍니다.
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength=0

 

 

log4j2.xml 추가 설정
  • 기존에 설정되어 있는 Loggers 내부에 작성을 해줍니다.
<Logger name="jdbc.connection" level="OFF" additivity="false">
     <AppenderRef ref="Console-Appneder"/>
</Logger>
<Logger name="jdbc.audit" level="WARN" additivity="false">
    <AppenderRef ref="Console-Appneder"/>
</Logger>
<Logger name="jdbc.sqlonly" level="OFF" additivity="false">
    <AppenderRef ref="Console-Appneder"/>
</Logger>
<Logger name="jdbc.sqltiming" level="DEBUG" additivity="false">
    <AppenderRef ref="Console-Appneder"/>
</Logger>
<Logger name="jdbc.resultset" level="OFF" additivity="false">
    <AppenderRef ref="Console-Appneder"/>
</Logger>
<Logger name="jdbc.resultsettable" level="DEBUG" additivity="false">
    <AppenderRef ref="Console-Appneder"/>
</Logger>

 

데이터베이스 연결 정보 수정
  • application.yml 파일에 데이터 베이스 연결 정보를 수정합니다.
// 기존
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/example?serverTimezone=UTC&characterEncoding=UTF-8

// 변경
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/example?serverTimezone=UTC&characterEncoding=UTF-8

 

테스트 확인
  • 쿼리가 실행되는것이 확인되고 파라미터도 정상적으로 출력이 되고 있습니다.

728x90
반응형