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 파일을 생성한다.
이로써 아~주 기본 환경설정이 벌써 끝나버렸다. @_@;
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 구문은 이 설정파일이 로드될 때 발생하는 로그에 대한 레벨을 설정하는 부분이다.
말이 어렵지 실행화면을 보면 이해가 갈것이다.
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 부분을 설명하기 위해 먼저 MainClass와 LogTest를 구현하였다. 현재 MainClass와 LogTest 를 생성만 한 상태에서는 위처럼 테스트가 불가능하다. 이런 설정이구나 라고만 이해하고 넘어가자.
Appenders 태그 안에 실질적인 로그 설정 코드를 삽입한다.
현재 콘솔에 로그를 출력시키기 위해 <Console> 태그 관련 코드를 삽입하고 로그로 찍히는 패턴을 PatternLayout 태그를 통해 설정한다.
%d는 로그 시간에 관한 설정을 나타내는데 괄호 안의 형태로 포멧시킬 수 있다.
%p는 로그 레벨, %c는 로그가 발생한 클래스 경로, %m은 로그 메시지, %n은 개행이다.
%5p는 로그 레벨이 출력되는 기본 문자열 길이를 5로 설정한다는 의미이다.
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초마다 로그를 찍도록 해보겠다. @_@;
이 부분은 스프링에 대한 조금의 지식을 갖고 있다면 어렵지 않게 구현할 수 있다.
다음 글에서 진행하도록 하겠다.
'백엔드 > JAVA' 카테고리의 다른 글
[JAVA] DefaultHttpClient와 CloseableHttpClient의 차이 1 (0) | 2021.08.24 |
---|---|
[JAVA] 접근제어자, public, private, default, protected 정의, 예제 (0) | 2021.06.07 |
[Java] 예외처리, Throw, Throws란 / 예외와 에러의 차이 / 예제 (1) | 2021.06.04 |
[JAVA] String을 Json 으로 변환. String to Json (1) | 2021.02.03 |
[WEB] log4j2 사용 / log4j2.xml / log4j2 설정/ 활용 2편 (0) | 2020.09.18 |