[스프링부트] AOP를 이용한 로그파일 설정 & slf4j 본문

백앤드 개발일지/스프링부트

[스프링부트] AOP를 이용한 로그파일 설정 & slf4j

giron 2021. 11. 7. 23:58
728x90

프로젝트가 거의 막바지 단계에 다다라서 운영할 때 꼭 필요한 로그를 찍으려고 한다. 이번 로그는 AOP를 이용해서 찍었지만 다음번에는 인터셉터를 이용해서 찍어보려고 한다. (경험은 많을수록 좋으니😇😇)

Log설정

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.8'

우리는 aop를 적용할것이기 때문에 aop와 p6spy라이브러리를 추가해준다.

slf4j slf4j2 p6spy는 나중에 정리해보도록 하겠다. 참고 주소는 글 맨 아래에 남겨두겠다!

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <timestamp key="BY_DATE" datePattern="yyyy-MM-dd"/>
    <property name="LOG_PATTERN"
              value="[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"/>
    <property name="DB_PATTERN" value="%green(    > %msg%n)"/>
    <property name="LOG_LOCATION" value="./logs"/>
    <property name="BACKUP_LOCATION" value="./logs"/>
    <property name="DEBUG_LOCATION" value="debug"/>
    <property name="INFO_LOCATION" value="info"/>
    <property name="WARN_LOCATION" value="warn"/>
    <property name="ERROR_LOCATION" value="error"/>
    <property name="MAX_FILE_SIZE" value="100MB"/>
    <property name="MAX_HISTORY" value="14"/>

    <springProfile name="test, local">
        <include resource="logging/console-appender.xml"/>
        <logger name="com.woowacourse.gongseek" level="DEBUG">
            <appender-ref ref="CONSOLE"/>
        </logger>
        <logger name="org.springframework.boot" level="INFO">
            <appender-ref ref="CONSOLE"/>
        </logger>
        <logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>
        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" additivity="false">
            <appender-ref ref="CONSOLE-DB"/>
        </logger>
        <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="TRACE" additivity="false">
            <appender-ref ref="CONSOLE-DB"/>
        </logger>
    </springProfile>

    <springProfile name="dev">
        <include resource="logging/file-debug-appender.xml"/>
        <include resource="logging/file-info-appender.xml"/>
        <include resource="logging/file-warn-appender.xml"/>
        <include resource="logging/file-error-appender.xml"/>
        <logger name="com.woowacourse.gongseek" level="DEBUG">
            <appender-ref ref="FILE-DEBUG"/>
            <appender-ref ref="FILE-INFO"/>
            <appender-ref ref="FILE-WARN"/>
            <appender-ref ref="FILE-ERROR"/>
        </logger>
        <logger name="org.springframework.boot" level="INFO">
            <appender-ref ref="FILE-INFO"/>
            <appender-ref ref="FILE-WARN"/>
            <appender-ref ref="FILE-ERROR"/>
        </logger>
    </springProfile>

    <springProfile name="prod">
        <include resource="logging/file-info-appender.xml"/>
        <include resource="logging/file-warn-appender.xml"/>
        <include resource="logging/file-error-appender.xml"/>
        <logger name="com.woowacourse.gongseek" level="INFO">
            <appender-ref ref="FILE-INFO"/>
            <appender-ref ref="FILE-WARN"/>
            <appender-ref ref="FILE-ERROR"/>
        </logger>
        <logger name="org.springframework.boot" level="INFO">
            <appender-ref ref="FILE-INFO"/>
            <appender-ref ref="FILE-WARN"/>
            <appender-ref ref="FILE-ERROR"/>
        </logger>
    </springProfile>

</configuration>

application.yml

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        format_sql: true
        show_sql: false //해당 설정을 false로 해야 로그에서 설정한 로깅이 콘솔로만 보인다.
        				//true로 하면 바인딩 쿼리와 sql쿼리 둘다 나가므로 false로 해두자
    database-platform: org.hibernate.dialect.MySQL57Dialect

logging:
  level.org:
    hibernate.type:
      descriptor:
        sql.BasicBinder: TRACE

console-appender.xml

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

    <appender name="CONSOLE-DB" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>utf8</charset>
            <Pattern>${DB_PATTERN}</Pattern>
        </encoder>
    </appender>
</included>

file-debug-appender.xml

<included>
    <appender name="FILE-DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_LOCATION}/${DEBUG_LOCATION}/debug-${BY_DATE}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${BACKUP_LOCATION}/${DEBUG_LOCATION}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            <maxHistory>${MAX_HISTORY}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

file-error-appender.xml

<included>
    <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_LOCATION}/${ERROR_LOCATION}/error-${BY_DATE}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${BACKUP_LOCATION}/${ERROR_LOCATION}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            <maxHistory>${MAX_HISTORY}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

file-info-appender.xml

<included>
    <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_LOCATION}/${INFO_LOCATION}/info-${BY_DATE}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${BACKUP_LOCATION}/${INFO_LOCATION}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            <maxHistory>${MAX_HISTORY}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

file-warn-appender.xml

<included>
    <appender name="FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_LOCATION}/${WARN_LOCATION}/warn-${BY_DATE}.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${BACKUP_LOCATION}/${WARN_LOCATION}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            <maxHistory>${MAX_HISTORY}</maxHistory>
        </rollingPolicy>
    </appender>
</included>

위와 같이 설정하면 세팅은 끝났다.

 

그리고 나는 애노테이션을 만들어서 매서드 위에 그 애노테이션을 올리면 그 매서드가 실행했을 때의 실행 시간을 로그로 찍으려고 한다.

LogAop

@Aspect
@Component
@Slf4j
public class LogAop {
    @Around("@annotation(LogExecutionTime)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        log.info("time : " + (double)(endTime - startTime) / 1000);
        return proceed;
    }
}

LogExecutionTime

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}

그 후, 컨트롤러에 아래와 같이 설정하고 홈 화면으로 들어가면....!

홈 컨트롤러

😆😉😆😉 잘 출력이 되었다.

log

이상 실용적으로 스프링부트에서 로그를 찍는 방법을 알아보았다. 자세한 개념적인 내용은 https://www.youtube.com/watch?v=MxxeKXydn4A <<설명을 정말 잘해주셨다!

*나중에 시간이 생기면 한번 정리해보겠다!

 


  • ec2에서 로그파일을 기록할때 app/dev/logs 경로는 미리 만들어 두어야 한다. (그렇지 않으면 권한이 없어서 안 만들어진다.)
  • log파일 만들 때, 상대 경로로 하면 안 된다. 절대 경로로 설정해야 한다.

 

728x90
Comments