반응형

1. 개요

 로그는 시스템의 오류 파악이나 로직 분석을 위해 꼭 필요하다.

 실무를 접하면서 로그가 얼마나 중요한지를 많이 느끼고 있기 때문에 로그 개념을 다시 정리해보고자 글을 쓴다.

 그리고! 그냥 남기면 기억에 오래 남지 않으므로, 좀 특이한? 방식으로 로그를 남겨보았다.


2. 환경

  1) maven

  2) JDK 1.8

  3) Tomcat 8.0 


3. 준비

 1) Maven 라이브러리 추가

 log4j2 관련 라이브러리는 다음과 같다. pom.xml에 추가해주자!

1
2
3
4
5
6
7
8
9
10
11
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.13.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.0</version>
      </dependency>
     </dependencies>
cs

 2) log4j2.xml 파일 생성

 class 경로인 src/main/resources 경로에 log4j2.xml 파일을 생성한다.

log4j2.xml 파일 생성

 이로써 아~주 기본 환경설정이 벌써 끝나버렸다. @_@;


4. console log

 4.1) 필요 패키지, 클래스 생성

  콘솔에 로그를 찍어보자. 일단, 동작에 필요한 패키지와 클래스를 아래와 다음과 같이 생성한다.

 

패키지, 클래스 생성

   - Main, test 패키지 생성

   - test 패키지에 LogTest 클래스 생성

   - Main 패키지에 MainClass 객체를 생성

   - quartz 패키지도 일단 생성 (활용 부분에서 quartz를 사용해 로그를 예정이며, console 로그를 출력할 때는 사용 X)

 

  4.2) log4j2.xml 파일 코드

   console에 로그를 찍기 위해 아래 코드를 삽입한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration status="debug">
 
    <Appenders>
        <!-- 콜솔 -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd hh:mm:ss} %5p [%c] %m%n"/>
        </Console>
    </Appenders>
    
    <loggers>
        <root level="debug" additivity="true">
            <AppenderRef ref="console"/>
        </root>
    </loggers>
 
</configuration>
cs

 

 3번 줄의 configuration status 구문은 이 설정파일이 로드될 때 발생하는 로그에 대한 레벨을 설정하는 부분이다.

 말이 어렵지 실행화면을 보면 이해가 갈것이다. 

 

configuration status = "DEBUG"

log4j2.xml 의 내부 설정을 로드하면서 발생하는 DEBUG 이상의 로그들을 출력중이다.

status를 info로 설정하면 아~~~무 로그도 출력되지 않는다.

그 이유는 log4j2.xml 설정파일을 로드할 때의 정보는 내부적으로 DEBUG레벨로 찍고 있기 때문이다.

INFO 레벨은 DEBUG레벨보다 상위의 레벨이기 때문에 로그가 찍히지 않게 된다.

 

그렇다면 log4j2.xml 파일을 로드할 때 문제가 생기도록 코드를 바꾼 후 status를 info로 설정한다면?

내부적으로 error 로그가 발생할 것이고, 이는 info 레벨보다 높기 때문에 로그가 찍힐 것이다.

테스트로 5번줄의 Appenders 태그 명을 Appenderss로 바꾼 후 실행시켰다.

제일 아랫줄의 ERROR test.LogTest 부분이 log4j2.xml 을 로드하면서 생긴에러이다.

configuration status ="info" And Appenders -> Appenderss

 

* configuration 부분을 설명하기 위해 먼저 MainClass와 LogTest를 구현하였다. 현재 MainClass와 LogTest 를 생성만 한 상태에서는 위처럼 테스트가 불가능하다. 이런 설정이구나 라고만 이해하고 넘어가자. 

 

Appenders 태그 안에 실질적인 로그 설정 코드를 삽입한다.

현재 콘솔에 로그를 출력시키기 위해 <Console> 태그 관련 코드를 삽입하고 로그로 찍히는 패턴을 PatternLayout 태그를 통해 설정한다.

%d는 로그 시간에 관한 설정을 나타내는데 괄호 안의 형태로 포멧시킬 수 있다.

%p는 로그 레벨, %c는 로그가 발생한 클래스 경로, %m은 로그 메시지, %n은 개행이다. 

%5p는 로그 레벨이 출력되는 기본 문자열 길이를 5로 설정한다는 의미이다.

WARN 앞에 공백 보이시죠?

 

12번 줄의 loggers 는 설정한 로그 코드를 적용하는 부분이다.

root 태그를 사용하면 현재 시스템에서 발생하는 모든 로그를 찍어낼 수 있고, level을 debug로 설정하여 debug 이상의 로그만 출력되도록 한다. Appender를 이용해서 앞서 설정한 console을 적용시키면, 결과적으로 기동하는 시스템내에서 발생하는 모든 로그 중 debug레벨 이상은 모두 찍히게 된다.

 

4.3) 클래스 파일 코드 작성

 - LogTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package test;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
 
 
public class LogTest {
    
    private Logger logger = LogManager.getLogger(LogTest.class);
    
    public void printLog() {
        logger.debug("[debug] log!");
        logger.info("[info] log!");
        logger.warn("[warn] log!");
        logger.error("[error] log!");
    }
}
 
cs

로그 객체를 설정하고, printLog() 메서드에 debug, info, warn, error로그를 출력하는 코드를 삽입한다.

 

 - MainClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package Main;
 
import test.LogTest;
 
public class MainClass {
 
    public static void main(String[] args) {
        
        LogTest logTest = new LogTest();
        logTest.printLog();
    }
}
 
cs

앞서 만든 LogTest 객체 생성 후 printLog() 메서드를 호출하는 코드를 삽입한다.

 

이제 MainClass를 실행시켜보자!

이러한 로그가 출력되면 성공!

만약 에러 로그만 출력하고 싶다면 log4j2.xml 의 root level을 error로 설정하면 된다.

 

5. RollingFile log

로그를 파일로 남기는 방법 중 하나로, 날짜, 시간 등에 따라 로그파일을 생성하여 보관하고 싶거나, 로그파일의 용량이 너무 커 압축파일 형태로 로그를 남기고싶다면 이 설정을 사용하면 된다.

 

5.1) log4j2.xml 파일 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration status="DEBUG">
 
    <Appenders>
        <!-- 콜솔 -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd hh:mm:ss} %5p [%c] %m%n"/>
        </Console>
        
        <!-- 파일  -->
        <RollingFile name ="RollingFile">
            <FileName>C:/log/mylog.txt</FileName>
            <FilePattern>C:/log/%d{yyyy-MM-dd-hh-mm}/mylog.zip</FilePattern>
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss} %5p [%c] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>
            </Policies>
        </RollingFile>
        
        <RollingFile name ="RollingFileError">
            <FileName>C:/log/mylog_error.txt</FileName>
            <FilePattern>C:/log/%d{yyyy-MM-dd-hh-mm}/mylog_error.zip</FilePattern>
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss} %5p [%c] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>
            </Policies>
        </RollingFile>
        
    </Appenders>
    
    <loggers>
        <root level="debug" additivity="true">
            <AppenderRef ref="console"/>
            <AppenderRef ref="RollingFile"/>
            <AppenderRef ref="RollingFileError" level = "ERROR"/>
        </root>
    </loggers>
    
</configuration> 
cs

코드가 갑자기 늘어났는데, 천천히 파악해보자.

일단 이 코드의 기능목표는 다음과 같다.

 가) 모든 로그가 찍히는 mylog.txt 파일 생성

 나) 에러 로그만 찍히는 mylog_error.txt 파일 생성

 다) 1분마다 찍힌 로그파일을 압축파일로 저장

 

 5.2) 코드 설명

 RollingFile 태그를 사용해야한다.

 FileName은 로그가 찍히게 될 파일경로,

 FilePattern은 파일이 Rolling 될때, 즉 조건에 의해 파일이 말릴 때의 파일 패턴. >> 날짜폴더/mylog.zip 형태

 Pattern은 찍히는 로그 형태

 TimeBasedTriggeringPolicy는 Rolling 조건을 시간으로 설정하고, interval은 1분 간격으로 Rolling한다는 의미.

 

 * interval은 앞서 설정한 FilePattern에 따라 1분이 될수도, 1시간이 될수도, 1일이 될수도 있다.

%d{yyyy-MM-dd-hh-mm}.log.zip interval = 1  1분마다 롤링
%d{yyyy-MM-dd-hh}.log.zip interval = 1  1시간마다 롤링
%d{yyyy-MM-dd}.log.zip interval = 1  1일마다 롤링

 

일반적으로 1일마다 롤링을 하지만, 로그 파일이 롤링되는 테스트 결과를 내일 확인할 수 없으니.. 1분마다 생성되도록 설정하였다.

 

위와 같이 일반 로그, 에러 로그에 대한 Rolling 로그 설정을 만들고, 

39 ~ 40번 줄처럼 RollingFile, RollingFileError 를 AppenderRef 태그를 통해 실제로 적용시켜보자.

단, RolingFileError는 ERROR 레벨 이상의 로그만 찍혀야 하기 때문에 level을 따로 ERROR로 설정한다.

 

이제 MainClass를 실행 시켰을 때 설정한 경로로 파일이 생성되어 로그가 찍히고 1분마다 zip파일로 남을까??

 

안남는다. 파일은 생성되고 순간의 로그는 파일에 찍히겠지만, 그게끝이야! 로그가 계속 찍히지 않으니까!

 

때문에 날짜 형식으로 폴더 하나가 생성되고, mylog, mylog_error 코드 안에 각각의 로그가 들어가면 성공이다.

 

"그럼 로그를 계속 찍어주려면 어떻게할까?? 반복문 돌려도 된다! while!

하지만 좀 더 의미있게 해보자...! 1초마다 찍히게 하는거야! 반복문을 통해서가 아닌 잡 스케줄러를 이용해서!!"

 

해서 활용편으로 quartz라는 스케줄러를 사용하여 1초마다 로그를 찍도록 해보겠다. @_@;

 

이 부분은 스프링에 대한 조금의 지식을 갖고 있다면 어렵지 않게 구현할 수 있다.

 

다음 글에서 진행하도록 하겠다.

 

 

반응형

+ Recent posts