본문으로 바로가기

스프링(Spring) 설정 - Log4j 설정

category 공부/Spring 2018. 4. 26. 16:41

Log4j는 자바기반의 로깅 유틸리티로 Apache에서 만든 오픈소스 라이브러리라고 한다. Log4j는 옵션 설정을 통해서 선택적으로 로그를 남기거나 특정 파일에 로그를 생성하는 등 다양한 이점을 가지고 있다. 한번 설정을 해놓으면 개발할 때 편하다. sql문이 뭐가 찍히고, 어떤 값이 담겨오는 지 궁금한데 궁금 한 곳마다 system.out.prtinln()을 찍고 필요 없으면 또 찾아서 지우고, 너무 귀찮다. 그 귀찮음을 덜기 위해서 개발 전에 log4j를 설정한다.


Log4j.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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p: %c - %m%n" />
        </layout>
    </appender>
    
    <!-- Application Loggers -->
    <logger name="com.tody.lovely" >
        <level value="info" />
    </logger>
    
    <!-- 3rdparty Loggers -->
    <logger name="org.springframework.core">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.beans">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.context">
        <level value="info" />
    </logger>
 
    <logger name="org.springframework.web">
        <level value="info" />
    </logger>
 
    <!-- Root Logger -->
    <root>
        <priority value="warn" />
        <appender-ref ref="console" />
    </root>
    
</log4j:configuration>
cs

처음 프로젝트를 생성했을 때 만들어져 있는 log4j.xml 이다.


Log4j 레벨

로그 레벨

설명 

FATAL

 아주 심각한 에러가 발생한 상태를 나타낸다. 

ERROR

 어떠한 요청을 처리하는 중 문제가 발생한 상태를 나타낸다. 

 WARN

 프로그램의 실행에는 문제가 없지만, 향후 시스템 에러의 원인이 될 수 있는

 경고성 메시지를 나타낸다.

 INFO

 어떠한 상태변경과 같은 정보성 메시지를 나타낸다. 

 DEBUG

 개발시 디버그 용도로 사용하는 메시지를 나타낸다. 

 TRACE

 디버그 레벨이 너무 광범위한것을 해결하기 위해서 좀 더 상세한 이벤트를 나타낸다.

출처:http://addio3305.tistory.com/43?category=772645[흔한 개발자의 개발 노트]


level value 값에 적혀 있는 것들이다. 위의 순서대로 높은 높은 레벨을 가지며, 출력 레벨 설정에 따라 설정 레벨 이상의 로그가 출력된다. 예를 들어 출력 레벨을 INFO라고 설정했다면, INFO를 포함한 INFO보다 높은 레벨인 WARN, ERROR, FATAL이 출력된다. 


Log4j 구성요소

 요소

 설명

Logger

 출력할 메시지를 Appender에 전달한다.

Appender

 전달된 로그를 어디에 출력할 지 결정한다. (콘솔 출력, 파일 기록, DB 저장 등)

Layout

 로그를 어떤 형식으로 출력할 지 결정한다.

출처:http://addio3305.tistory.com/43?category=772645[흔한 개발자의 개발 노트]


Logger(14행, 19행, 24행...)는 실제 로그 기능을 수행하는 객체로 Name을 가지고 사용된다. 로그 출력 레벨을 설정할 수 있고, 0개 이상의 Appender를 지정할 수 있다. 입력받은 로깅 메시지는 로그 레벨에 따라 Appender로 전달 된다. 기본적으로 최상위 logger인 Root logger(36행)을 설정해 주어야 한다. 

 요소

설명 

 jdbc.sqlonly

 SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다.

 jdbc.sqltiming

 SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다.

 jdbc.audit

 ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다.

 jdbc.resultset

 ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다.

출처:http://www.mimul.com/pebble/default/2008/10/24/1224847200000.html


Appender(6행)는 로그를 출력할 위치, 출력 형식 등을 지정할 수 있다. 여러 종류의 Appender가 있지만 몇개만 알아보자. 아래 표의 4개 말고도 SMTPAppender, DBAppender 등이 있는데, 이걸 이용하면 로그를 원격 위치에 기록할 수도 있다. 필요하면 찾아보자. 아 그리고 주의해야 할 것이 있다. Appender태그는 Logger태그들보다 위에 있어야 한다.

요소 

설명 

 ConsoleAppender

 org.apache.log4j.ConsoleAppender

 콘솔에 로그 메시지를 출력한다.

 FilerAppender

 org.apache.log4j.FilerAppender

 로그 메시지를 지정된 파일에 기록한다.

 RollingFileAppender

 org.apache.log4j.RollingFileAppender

 파일 크기가 일정 수준 이상이 되면 기존 파일을 백업파일로 두고 처음부터 다시 기록한다.

 DailyRollingFilerAppender

 org.apache.log4j.Daily.Rolling.File.Appender

 일정 기간 단위로 로그 파일을 생성하고 기록한다.


LayOut(8행)은 로그를 출력하는 형태를 만들 수 있다. PatternLayout을 이용하는게 가장 적합하다. 로그의 출력 형태, Layout을 자신이 원하는 형식으로 바꿀 수 있다 ConversionPattern(10행)의 패턴들에 대해서 알아보자. 붉은 표시는 성능에 영향을 준다.

 패턴

설명 

%m 

 로그 내용 출력

%p

 debug, info, warn, error 등의 priority 출력

%r

 어플리케이션 시작 후 이벤트가 발생하는 시점까지의 경과시간. (밀리세컨드로 출력)

%c

 package 출력

%C

 클래스명 출력

%d

 이벤트 발생 날짜 출력

%n

 개행문자(\n) 출력

%M

 로깅이 발생한 method 이름 출력

%F

 로깅이 발생한 프로그램 파일명 출력

%l

 로깅이 발생한 caller 정보 출력

%L

 로깅이 발생한 caller 라인수 출력

%x

 로깅이 발생한 thread와 관련된 NDC 출력

%X

 로깅이 발생한 thread와 관련된 MDC 출력

%

 % 출력 표시

%t

 쓰레드 이름 출력



logger를 이해할 수 있는 예가 있다. 나도 이해가 잘되서 들고왔다.

Logger Name 

Level 

Appender 

Additivity 

 Root

DEBUG 

Console 

 

 Vehicle

 INFO

RollingFile

 ture

 Vehicle.Car

 ERROR

 Filer

 false


여기서 Additivity는 상위 Logger로부터의 상속 여부를 의미합니다. True(기본값)일 경우, 먼저 모든 상위 로거들의 설정값을 상속받아 현재 로거에 설정된 값을 재적용(덮어쓰기) 시키며, False로 설정하게 된다면 해당 로거는 상위 로거의 설정내용을 상속받지 않습니다.


즉, Vehicle의 경우 Root 로거로부터 DEBUG 레벨 설정을 상속받지만 현재 로거에 INFO 레벨이 적용되어 있기 때문에 최종적으로 INFO 레벨이 적용되며, Root 로거의 Console Appender와 Vehicle 로거의 RollingFile Appender 모두에게 로그 메시지를 전달하게 됩니다.


Vehicle.Car의 경우 Additivity 값이 false 이기 때문에 상위 로거인 Root, Vehicle 로거로 부터 설정을 상속받지 않아 최종적으로 ERROR 레벨 이상의 로그가 File Appender로 전달되게 됩니다.


만일 Logger 설정되지 않은 클래스명( ex – Vehicle.Airplane)이 입력되었을 경우, 상위 로거인 Vehicle의 설정내용으로 동일하게 적용됩니다.


출처 : https://thinkwarelab.wordpress.com/2016/11/18/java%EC%97%90%EC%84%9C-logback%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A1%9C%EA%B9%85logging-%EC%82%AC%EC%9A%A9%EB%B2%95/




본격적으로 log4j를 설정하기 앞서 log4j 설정 파일은 xml과 properties로 설정이 가능하다. 인터넷에 찾아보면 properties로 설정하는 경우가 많은데, log4j 설정파일은 xml로 설정하기를 권장한다. properties는 옛날 방식이기도 하고 최신 log4j는 xml과 json을 이용한 설정만 지원하고 있다. 개인적으로 properties로 하니까 더 복잡한 느낌이 들었다.. 하하


1. pom.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
        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>
cs

기본 프로젝트 pom.xml에 들어가면 위와 같이 log4j가 추가 되어 있을 것이다. 그래서 따로 추가하지 않아도 된다.



2. log4j.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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p: %c - %m%n" />
        </layout>
    </appender>
    
    <!-- Application Loggers -->
    <logger name="com.tody.lovely" >
        <level value="info" />
    </logger>
    
    <!-- 3rdparty Loggers -->
    <logger name="org.springframework.core">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.beans">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.context">
        <level value="info" />
    </logger>
 
    <logger name="org.springframework.web">
        <level value="info" />
    </logger>
 
    <!-- Root Logger -->
    <root>
        <priority value="warn" />
        <appender-ref ref="console" />
    </root>
    
</log4j:configuration>
cs


기본 프로젝트에 있는 log4j.xml이다. 서버를 실행 시키면 위의 사진과 같이 콘솔창에 빨간 글씨들 사이에 하얀 글씨들이 보일 것이다. 그게 바로 여기서 설정한 로그 메시지들이다. Root Logger의 레벨이 warn 이고, Appender Logger들의 레벨은 info다. 전부 warn레벨을 상속받지만, 현재 info 레벨이 적용된다. 그리고 ConsoleAppender에 로그 메시지를 전송한다. 현재는 이렇게 찍히지만, 이제 우리 입맛에 맞게, 로그의 종류에 따라 다르게 출력되게 logj4.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
45
46
47
48
49
50
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %5p [%c] %m%n" />
        </layout>
    </appender>
    
    <!-- *추가* -->
    <appender name="console-infolog" class="org.apache.log4j.ConsoleAppender">
          <layout class="org.apache.log4j.PatternLayout">
              <param name="ConversionPattern" value="%d %5p %m%n"/>
          </layout>  
    </appender>
    <!--  -->
    
    <!-- Application Loggers -->
    <logger name="com" additivity="false">
        <level value="debug" />
        <appender-ref ref="console"/>
    </logger>
    
    <!-- 3rdparty Loggers -->
    <logger name="org.springframework.core">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.beans">
        <level value="info" />
    </logger>
    
    <logger name="org.springframework.context">
        <level value="info" />
    </logger>
 
    <logger name="org.springframework.web">
        <level value="info" />
    </logger>
 
    <!-- Root Logger -->
    <root>
        <priority value="off" />
        <appender-ref ref="console" />
    </root>
    
</log4j:configuration>
cs

2가지의 Appender ( console, console-infolog )와 기존의 4가지 Logger와 추가된 Logger가 있다. 기존의 4가지 Logger(28~42행)는 삭제해줘도 된다. Logger마다 메세지를 전달하는 Appender가 다르니 잘 확인하자. 그리고 상속을 하지 않는(Additivity=false) 이유는 로그가 2번 출력되서 보통 상속하지 않는다.


서버를 돌리면 기존 4가지 Logger를 지우지 않았다면 그대로 출력되고, 지웠다면 빨간 글씨만 출력될 것이다. log4j의 설정 끝!



참고 블로그

http://addio3305.tistory.com/

http://cofs.tistory.com/354

https://thinkwarelab.wordpress.com/2016/11/18/java%EC%97%90%EC%84%9C-logback%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A1%9C%EA%B9%85logging-%EC%82%AC%EC%9A%A9%EB%B2%95/