ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • logback 에서의 rolling 정책 사용시 주의사항
    기록해야 기억한다/OSS(Open Source Software) 2021. 1. 7. 15:02
    SMALL

    logback 사용시 일반적으로 특정 시간이나 용량에 따라 파일을 이동하고 압축하는 정책을 적용해서 사용한다. 이 경우 몇 가지 case 를 통해 유의해서 사용해야 할 사항에 대한 기록이다.

     

    Appender 사용

    Appender 는 위임받은 이벤트에 대해 log 가 발생하면 출력스트림(console/file) 에 write 하는 역할을 한다. 

    package ch.qos.logback.core;
    
    import ch.qos.logback.core.spi.ContextAware;
    import ch.qos.logback.core.spi.FilterAttachable;
    import ch.qos.logback.core.spi.LifeCycle;
    
    
    public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {
    
      public String getName();
      public void setName(String name);
      void doAppend(E event);
    
    }

    doAppend() 는 Generic 파라미터를 통해 logback 등의 모듈에 따라 append 를 하고, 구현클래스를 통해 해당 target 에 결과를 생성합니다.

    보통의 경우라면 appender 를 이용해 log 를 종류별로 관리를 할 것이고, 보통 개발/운영 으로 크게 나누어 관리할 수 있다.

    개인 개발용 로그 appender

    개인개발용 로그는 잦은 재시작이 되기에 날짜기준으로 하기엔 확인이 불편하다. 그래서 공식사이트에서도 아래와 같은 방법을 안내한다.

    <configuration>
    
      <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
           the key "bySecond" into the logger context. This value will be
           available to all subsequent configuration elements. -->
      <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
    
      <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <!-- use the previously created timestamp to create a uniquely
             named log file -->
        <file>log-${bySecond}.txt</file>
        <encoder>
          <pattern>%logger{35} - %msg%n</pattern>
        </encoder>
      </appender>
    
      <root level="DEBUG">
        <appender-ref ref="FILE" />
      </root>
    </configuration>

    timestamp 태그를 통해 초단위 시간값을 받아서 파일이 생길때마다 해당 태그값을 사용하는 appender 를 생성했다.

    여기서 timestamp 값은 두 가지의 필수 attributes 를 가지는데 keydatePattern 이다. key 는 placeholder 로 사용할 수 있으며 다른 항목에서 ${key}으로 변수처럼 사용가능하다. datePattern 속성은 현재 시간 (구성 파일이 구문 분석되는 시간)을 문자열로 변환하는 데 사용되는 날짜 패턴을 나타내며 이는 SimpleDateFormat 의 정의를 따라야 한다.  

     그리고 부가적으로 timestamp 에 대한 시간 참조를 나타내는 timeReference 가 있고, 기본값(지정하지 않을 경우)으로 구성 파일의 해석이나 파싱시간(현재시간)에 따른다. 특정 상황에서는 context 의 생성 시간을 시간 참조로 사용하는 것이 유용할 수 있는데 이는 timeReference 속성을 "contextBirth"로 설정하여 수행 할 수 있다.

     

    주의 사항

    case 1.

    • 년도/월 의 구조를 가지는 폴더로 파일을 rolling 하는 정책을 적용
    • 년도와 월은 timestamp 태그를 이용하여 <appender/> 에 <fileNamePattern/> 에 placeholder 를 이용하여 log 패턴을 적용
    • 문제발생
      • 년도가 바뀌는 시점에 새로운 연도의 폴더에 12월이라는 폴더가 생성되어 rolling 파일이 그 폴더로 복사됨
      • 더불어 1월달의 rolling 파일도 해당 폴더에 섞여 들어감 --> ??(이건 다시 파악필요)
        • logback 내부적으로 renameUtil 을 사용하여 파일 이동을 수행하는데 해당 클래스 전후 파악필요
    • 원인
      • <timestamp> 의 datePattern 이 yyyy  가 아닌 YYYY 로 설정되어 있어서 발생
      • 새해(2021년이라 가정) 1월1일 시점에 12월31일 log 파일 rolling
        • yyyy : SimpleDateFormat 기준 year. 당일 날짜(timeReference 를 설정하지 않았으므로 현재시간). 해당 시점엔 2020년으로 인식
        • YYYY : SimpleDateFormat 기준 Week year. rolling file 이 생성된 2020년 12월 31일은 주단위 기준 2021년 1주에 해당하여 2021년으로 인식함

     

    @Test
    void simpleDateFormatTest() {
        SimpleDateFormat YYYY = new SimpleDateFormat("YYYY");
        SimpleDateFormat yyyy = new SimpleDateFormat("yyyy");
        Calendar calendar = Calendar.getInstance();
        calendar.set(2020, Calendar.DECEMBER, 31);
        Date from = new Date(calendar.getTimeInMillis());
        System.out.println(yyyy.format(from));
        System.out.println(YYYY.format(from));
    }

    즉, 2020/12/31 이더라도 SimpleDateFormat 에 따라 Year 의 값이 달라 질 수 있다. 2020/12/31일이 아닌 2021/01/01 (당해의 첫주)이 속한 주의 모든 2020년도 날짜들은 'YYYY' 인 경우 모두 2021로 반환된다. 위의 결과는 아래와 같다. 

    2020
    2021
    Week Year 인 'Y'가 지정되고 Calendar 구현클래스가 Week Year 를 지원하지 않는 경우 'y' 이 대신 사용됩니다. getCalendar().isWeekDateSupported() 를 호출하여 week years 지원 여부를 테스트 할 수 있습니다.

     

    위처럼 logback 의 메뉴얼을 정확히 인지하지 않았고 별 의심없이 되겠지하고 생각했던 경우이다.

    반응형
    LIST

    댓글

Designed by Tistory.