티스토리 뷰
요즘 패킷 스니핑 자바 어플리케이션을 토이로 깨작깨작 건드리고 있다.
console창에 띄우기에는 정리도 안된 패킷들이 너무 많이 올라와서 log4j2 설정을 만져서 메모장으로 정리하려고 했는데... config 파일이 생각보다 공부할 게 많아보여서.. 생각난 김에 정리나 해보려고 한다.
전자정부 프레임워크 레퍼런스에서 해당 내용을 아주 기깔나게 정리하여 참고했다.
Spring 환경에서 Log4j2.xml 파일은 프로젝트가 초기화될 때 자동으로 호출되어 로그에 대한 설정 정보를 가지고 로그를 찍는다.
(따로 스프링 Config 파일에 명시하지 않았다면, 기본적으로 Log4j2.xml 파일을 resources 디렉토리에서 찾는다.)
Log4j 2는 XML 파일의 최상위 요소가 반드시 <Configuration> 여야 한다.
이 Configuration 태그 아래에 Logger, Appender, Layout 설정 등과 관련한 하위 요소를 정의하면 된다.
대충 기본적인 Log4j2.xml의 형식은 아래와 같다.
◎Log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<!-- Appender, Layout 설정 -->
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout/>
</Console>
<File name="file" fileName="./logs/file/sample.log" append="false">
<PatternLayout pattern="%d %5p [%c] %m%n"/>
</File>
</Appenders>
<!-- Logger 설정 -->
<Loggers>
<Logger name="egovLogger" level="DEBUG" additivity="false">
<AppenderRef ref="console"/>
<AppenderRef ref="file"/>
</Logger>
<Rootlevel="ERROR">
<AppenderRef ref="console"/>
</Root>
</Loggers>
</Configuration>
- Logger
Logger는 로깅 작업을 수행하는 Log4j 주체로, Logger 설정을 제외한 모든 로깅 기능이 이 Logger를 통해 처리된다.
사용자는 어플리케이션 내에서 사용할 Logger를 정의해야하며, Log Level과 Appender 설정에 따라 출력 대상과 위치가 결정된다.
Root Logger를 포함한 모든 Logger는 상위 요소인 <Loggers> 아래에 선언한다. Root Logger는 <Root> 요소로, 일반 Logger는 <Logger> 요소로 정의한다.
Logger는 하나 이상 정의할 수 있으며, Root 요소를 반드시 정의해야한다.
<Loggers>
<!-- attribute: name(Logger명), level(Log Level), additivity(중복로깅여부, true or false) -->
<!-- element: AppenderRef(Appender명) -->
<Logger name="X.Y" level="INFO" additivity="false">
<AppenderRef ref="console"/>
</Logger>
<Logger name="X" level="DEBUG" additivity="false">
<AppenderRef ref="console"/>
</Logger>
<Rootlevel="ERROR">
<AppenderRef ref="console"/>
</Root>
</Loggers>
사용자가 호출한 Logger 객체가 어떤 설정을 따르는지 이해하기 위해서는 Logger Hierarchy를 알고 있어야 한다.
내부적으로 설정 파일에 정의된 각 Logger 설정에 따라 LoggerConfig 오브젝트가 생성되며,
Logger Name에 따라 오브젝트 간 부모-자식 관계가 성립한다. 즉 부모 Logger의 설정을 자식 Logger가 상속받는다.
예를 들어 “X.Y” Logger의 부모는 “X”이고, “X” Logger의 부모는 Root Logger(최상위)이다.
다음은 Hierarchy 규칙과 예시이다.
1) 호출한 Logger Name과 동일한 Logger가 있는 경우, 해당 Logger 설정을 따른다.
2) 동일한 Logger는 없지만, Parent Logger가 존재하는 경우, Parent Logger 설정을 따른다.
3) Parent Logger도 존재하지 않는 경우, Root Logger 설정을 따른다.
LoogerName | Assigned LoggerConfig | Level | Java Code | Description |
root | root | ERROR | LogManager.getLogger(“root”); | 설정 파일의 Root 설정을 따름 |
X | X | DEBUG | LogManager.getLogger(“X”); | 설정 파일의 X Logger 설정을 따름 |
X.Y | X.Y | INFO | LogManager.getLogger(“X.Y”); | 설정 파일의 X.Y Logger 설정을 따름 |
X.Y.Z | X.Y | INFO | LogManager.getLogger(“X.Y.Z”); | X.Y.Z Logger 설정이 없으므로, 부모인 X.Y 설정을 따름 |
X.YZ | X | DEBUG | LogManager.getLogger(“X.YZ”); | X.YZ Logger 설정이 없으므로, 부모인 X 설정을 따름 |
Y | root | ERROR | LogManager.getLogger(“Y”); | Y Logger 설정이 없으므로, 부모인 Root 설정을 따름 |
- Logger Level
Log4j 2는 FATAL, ERROR, WARN, INFO, DEBUG, TRACE의 Log Level을 제공한다.
각각 trace(), debug(), info(), warn(), error(), fatal()라는 로깅 메서드를 이용해 로그를 출력할 수 있다.
로그 레벨은 다음과 같다. (FATAL > ERROR > WARN > INFO > DEBUG > TRACE)
로그 레벨 | 설명 |
FATAL | 아주 심각한 에러가 발생한 상태를 나타냄. 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능할 경우가 해당하는데, 일반적으로는 어플리케이션에서는 사용할 일이 없음. |
ERROR | 요청을 처리하는중 문제가 발생한 상태를 나타냄. |
WARN | 처리 가능한 문제이지만, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄. |
INFO | 로그인, 상태변경과 같은 정보성 메시지를 나타냄. |
DEBUG | 개발시 디버그 용도로 사용한 메시지를 나타냄. |
TRACE | 디버그 레벨이 너무 광범위한 것을 해결하기 위해서 좀더 상세한 상태를 나타냄. |
어플리케이션 수행 중 Log Level을 변경할 수도 있다.
이 때 Logger Configuration을 변경하는 것이므로, Logger 설정 정보를 참조하는 메서드를 호출할 수 있도록 org.apache.logging.log4j.Logger를 org.apache.logging.log4j.core.Logger로 캐스팅해야 한다.
Log Level 변경하려면 변경할 Level값을 파라미터로 setLevel() 메서드를 호출한다.
setLevel() 호출 이후부터 Log Level이 변경되며, 지정된 로그레벨 이하의 Log Event는 무시된다.
package egovframe.sample;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LoggerTest {
Logger logger = LogManager.getLogger(); // Root Logger 설정을 따름, Log Level: ERROR
org.apache.logging.log4j.core.Logger targetLogger = (org.apache.logging.log4j.core.Logger) logger;
targetLogger.debug("변경 전 - debug"); // 출력됨
targetLogger.error("변경 전 - error"); // 출력 안됨
targetLogger.setLevel(Level.DEBUG); // DEBUG, INFO, WARN, ERROR, FATAL 출력 가능
targetLogger.debug("변경 후 - debug"); // 출력됨
targetLogger.error("변경 후 - error"); // 출력됨
}
- Appender
Appender는 로그가 출력되는 위치를 나타낸다.
XXXAppender로 끝나는 클래스들의 이름을 보면, 출력 위치를 어느 정도 짐작할 수 있다.
Log4j 2는 Console, File, RollingFile, Socket, DB 등 다양한 로그 출력 위치과 방법을 지원한다.
기존 Log4j 1.x와 크게 달라진 점은 Appender 종류를 class 속성값으로 구분한 것과 달리, Log4j 2에서는 태그로 구분한다.
출력 위치에 따라 Appender 종류와 설정 태그가 달라지며, 아래 표는 각 Appender 정의 태그와 출력 위치이다.
Appenders | 태그명 | 출력 위치 |
ConsoleAppneder | <Console> | 콘솔에 출력 |
FileAppneder | <File> | 파일에 출력 |
RollingFileAppneder | <RollingFile> | 조건에 따라 파일에 출력 |
JDBCAppender | <JDBC> | RDB Table에 출력 |
모든 Appender 요소는 상위 요소인 <Appenders> 아래에 선언한다.
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout /> <!-- 디폴트 패턴 적용, %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n -->
</Console>
</Appenders>
<Loggers>
<Logger name="egovLogger" level="DEBUG" additivity="false">
<AppenderRef ref="console" />
</Logger>
<Rootlevel="ERROR">
<AppenderRef ref="console" />
</Root>
</Loggers>
가장 많이 사용되는 콘솔과 파일 Appender 정의 시 필요한 기본 설정에 대한 설명이다.
로그를 콘솔에 출력하기 위한 Appender
<!-- attribute: name(Appender명), target(출력방향지정, "SYSTEM_OUT" or "SYSTEM_ERR"(default)), follow, ignoreExceptions -->
<!-- element: Layout(출력패턴설정), Filters -->
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %5p [%c] %m%n" />
</Console>
2) FileAppender
로그를 파일에 출력하기 위한 Appender
<!-- attribute: name(Appender명), fileName(target파일명), append(이어쓰기여부, true(default) or false), locking, immediateFlush, ignoreExceptions, bufferedIO -->
<!-- element: Layout(출력패턴설정), Filters -->
<!-- append="false"이면 매번 로깅 시 기존 로그 파일을 clear하고 새로 로깅 -->
<File name="file" fileName="./logs/file/sample.log" append="false">
<PatternLayout pattern="%d %5p [%c] %m%n" />
</File>
<File name="mdcFile" fileName="./logs/file/mdcSample.log" append="false">
<!-- Thread Context Map(also known as MDC) 객체의 key와 매칭되는 value를 로깅 - %X{key} -->
<!-- ex) ThreadContext.put(“testKey”, “testValue”);인 경우, 레이아웃 패턴 %X{testKey}에 의해 “testValue” 로깅 -->
<PatternLayout pattern="%d %5p [%c] [%X{class} %X{method} %X{testKey}] %m%n" />
</File>
TriggeringPolicy와 RolloverStrategy에 따라 로그를 파일에 출력하기 위한 Appender로, FileAppender는 지정한 파일에 로그가 계속 남으므로 한 파일의 크기가 지나치게 커질 수 있고, 계획적인 로그관리가 불가능해진다.
그러나 RollingFileAppender는 파일의 크기 또는 파일 백업 인덱스 등의 지정을 통해서 특정 크기 이상으로 파일 크기가 커지게 되면, 기존파일(target)을 백업파일(history)로 바꾸고, 다시 처음부터 로깅을 시작한다.
<!-- attribute: name(Appender명), fileName(target파일명), filePattern(history파일명), append, immediateFlush, ignoreExceptions, bufferedIO -->
<!-- element: Layout(출력패턴설정), Filters, Policy(file rolling 조건 설정), Strategy(file name과 location 관련 설정) -->
<RollingFile name="rollingFile" fileName="./logs/rolling/rollingSample.log" filePattern="./logs/rolling/rollingSample.%i.log">
<PatternLayout pattern="%d %5p [%c] %m%n" />
<Policies>
<!-- size 단위: Byte(default), KB, MB, or GB -->
<SizeBasedTriggeringPolicy size="1000" />
</Policies>
<!-- 기존 maxIndex 속성이 Strategy 엘리먼트로 변경됨 -->
<!-- index는 min(default 1)부터 max(default 7)까지 증가, 아래에는 max="3"으로 settting -->
<!-- fileIndex="min"이므로 target file의 size가 1000 byte를 넘어가면, fileIndex가 1(min)인 history file에 백업 (fixed window strategy) -->
<!-- 그 다음 1000 byte를 넘어가면, rollingSample.1.log을 rollingSample.2.log 파일에 복사하고, target 파일을 rollingSample.1.log에복사한 후 target 파일에 새로 로깅 -->
<DefaultRolloverStrategy max="3" fileIndex="min" />
</RollingFile>
4) DailyRollingFileAppender
기존 DailyRollingFileAppender가 삭제되고, RollingFileAppender에서 <TimeBasedTriggeringPolicy> 엘리먼트로 설정 가능하도록 변경되었다.
설정한 날짜 또는 조건에 맞춰 로깅을 수행하며, interval 속성을 이용해 rolling 간격을 지정할 수 있다.
<RollingFile name="rollingFile" fileName="./logs/rolling/dailyRollingSample.log" filePattern="./logs/daily/dailyRollingSample.log.%d{yyyy-MM-dd-HH-mm-ss}">
<PatternLayout pattern="%d %5p [%c] %m%n" />
<Policies>
<!-- interval(default 1)이므로 1초 간격으로 rolling 수행 -->
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
- Layout 설정
Layout은 발생한 로그 이벤트의 포맷을 지정하고, 원하는 형식으로 로그를 출력할 수 있다.
Appenders 설정과 마찬가지로 Log4j 2에서는 Layout을 class 속성이 아닌 태그로 구분한다.
출력 형식에 따라 Layout의 종류가 달라지며, 아래와 같은 Layouts을 제공한다.
일반적으로 디버깅에 가장 적합한 PatternLayout만 사용하긴 한다.
PatternLayout은 Appender 요소의 하위 요소로 정의한다.
<Console>
<!-- 디폴트 패턴 적용, "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" -->
<PatternLayout />
</Console>
<PatternLayout />을 선언하면 디폴트 pattern이 적용되며, pattern 속성을 이용하여 일자, 시간, 클래스, 로거명, 메시지 등 여러 정보를 선택하여 다양한 조합의 로그 메시지를 출력할 수 있다.
%로 시작하고 %뒤에는 format modifiers와 conversion character로 정의한다.
예) %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
패턴 | 설명 |
c, logger | 로깅 이벤트를 발생시키기 위해 선택한 로거의 이름을 출력 |
C, class | 로깅 이벤트가 발생한 클래스의 풀네임명을 출력 |
M, method | 로깅 이벤트가 발생한 메서드명을 출력 |
F, file | 로깅 이벤트가 발생한 클래스의 파일명을 출력 |
l, location | 로깅 이벤트가 발생한 클래스의 풀네임명.메서드명(파일명:라인번호)를 출력 |
d, date | 로깅 이벤트의 일자와 시간을 출력,\\SimpleDateFormat클래스에 정의된 패턴으로 출력 포맷 지정가능 |
L, line | 로깅 이벤트가 발생한 라인 번호를 출력 |
m, msg, message | 로그문에서 전달된 메시지를 출력 |
n | 줄바꿈 |
p, level | 로깅 이벤트의 레벨을 출력 |
r, relative | 로그 처리시간 (milliseconds) |
t, thread | 로깅 이벤트가 발생한 스레드명을 출력 |
%% | %를 출력하기 위해 사용하는 패턴 |
'Support' 카테고리의 다른 글
[Linux] 리눅스 자주 사용하는 기본 명령어 정리 (0) | 2022.08.09 |
---|---|
[DOS & Batch] batch file Ref (0) | 2022.04.18 |
[git] 현재 개발 중인 프로젝트에서 gitignore 추가가 안될 때 (0) | 2021.07.28 |
[lumbok] 기본 어노테이션 요약 (0) | 2021.07.01 |
[lib] Lombok (0) | 2021.06.30 |
- Async
- redux
- 인천 구월동 맛집
- AsyncStorage
- react-native
- react
- Promise
- 이탈리안 레스토랑
- 파니노구스토
- redux-thunk
- 정보보안기사 #실기 #정리
- 맛집
- 인천 구월동 이탈리안 맛집
- await
- javascript
- Total
- Today
- Yesterday