티스토리 뷰

반응형

안녕하십니까 이번에는 Log4j2를 이용한 날짜별 로그를 찍어보겠습니다.

 

우선 로그란 

컴퓨팅에서 로그파일(logfile)은 운영 체제나 다른 소프트웨어가 실행 중에 발생하는 이벤트나 각기 다른 사용자의 통신 소프트웨어 간의 메시지를 기록한 파일이다. 로그를 기록하는 행위는 로깅(logging)이라고 한다.  - 위키 백과 - 

 

Server든 Client든 배포 및 운영을 하면서 에러나 버그가 발생 시 원인을 찾기 위해 로그 파일을 이용해 에러 발생 위치를 찾을 수 있습니다.

 

Java를 이용하면서 Log를 남기는 방법은 다양합니다. 

가장 기본적으로 System.out.println을 이용하여 로그를 찍게 할 수 있습니다.

하지만 이 방법으로 메세지를 찍는다면 발생 시간, 발생 위치 등 필용한 정보를 알기 위해 또 하나의 로직을 개발 해야겠죠? 그리고 System.out.println자체가 속도가 느려서 효율적이지 못합니다.

 

그 외에도 Java 내장 Log함수를 이용한다던가, 외부 라이브러리를 이용하던가 방법은 다양합니다.

 

그 중에서 저는 SLF4J를 이용한 Log4j2를 이용한 로깅을 해보겠습니다.

SLF4J (Simple Logging Facade for Java)는 다양한 로깅 프레임 워크 (예 : java.util.logging, logback, log4j)에 대한 간단한 외관 또는 추상화 역할을하여 최종 사용자가 배치  원하는 로깅 프레임 워크를 플러그인 할 수 있도록합니다.

 

그리고 최근까지도 logback을 이용하시는 분들이 많은데 저는 Log4j와 logback을 보안해서 만든 Log4j2를 이용하겠습니다.

 

Dependency는 이렇게 추가할 겁니다.

Lombok까지 추가하는 이유는 Lombok을 이용한다면 SLF4j를 어노테이션 만으로 추가를 할 수 있어 매우 편합니다.

 

Log4j2에 대한 설명은 공식 홈페이지여기 참고하세요.

    // Log4j2
	compile 'org.apache.logging.log4j:log4j-api:2.12.1'
	compile 'org.apache.logging.log4j:log4j-core:2.12.1'
    
 	// lombok
	compileOnly 'org.projectlombok:lombok:1.18.6'
	annotationProcessor 'org.projectlombok:lombok:1.18.6'

 

Log4j2는 다른 로그 프레임워크와 같이 XML로 설정할 수 있는데,

Log4j2는 그 뿐만 아니라 json, yaml(yml), properties파일로도 설정을 할 수 있습니다.

 

저는 XML로 설정 해보겠습니다.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration status="DEBUG" monitorInterval="300">
    <!-- XML 안에서 사용할 Global property 설정 --> 
	<Properties>
    	<Property name="FILENAME">logs/</Property>
		<Property name="LAYOUT">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%level]
			%C{1.} - %msg%n</Property>
	</Properties>

	<Appenders>
        <!-- Log 외에 출력 -->
		<Console name="console" target="SYSTEM_OUT">
			<PatternLayout pattern="${LAYOUT}" />
		</Console>

		<RollingFile name="InfoAppender"
			fileName="${FILENAME}/info.log" filePattern="${FILENAME}/%d{yyyy-MM-dd}/info.log">
			<PatternLayout pattern="${LAYOUT}" />
            <!-- 밑의 태그를 이용하여 Level별로 로그를 남길 수 있다. -->
			<LevelRangeFilter minLevel="INFO" maxLevel="INFO"
				onMatch="ACCEPT" onMismatch="DENY" />
			<Policies>
				<SizeBasedTriggeringPolicy size="10MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
			<DefaultRolloverstrategy>
				<Delete basePath="/logs" maxDepth="3">
					<IfLastModified age="30d" />
				</Delete>
			</DefaultRolloverstrategy>
		</RollingFile>
		<RollingFile name="FatalAppender"
			fileName="${FILENAME}/fatal.log" filePattern="${FILENAME}/%d{yyyy-MM-dd}/fatal.log">
			<PatternLayout pattern="${LAYOUT} %throwable{full}" />
			<LevelRangeFilter minLevel="FATAL" maxLevel="FATAL"
				onMatch="ACCEPT" onMismatch="DENY" />
			<Policies>
				<SizeBasedTriggeringPolicy size="10MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
			<DefaultRolloverstrategy>
				<Delete basePath="/logs" maxDepth="3">
					<IfLastModified age="10d" />
				</Delete>
			</DefaultRolloverstrategy>
		</RollingFile>

		<RollingFile name="WarnAppender"
			fileName="${FILENAME}/warn.log" filePattern="${FILENAME}/%d{yyyy-MM-dd}/warn.log">
			<PatternLayout pattern="${LAYOUT} %throwable{full}" />
			<LevelRangeFilter minLevel="WARN" maxLevel="WARN"
				onMatch="ACCEPT" onMismatch="DENY" />
			<Policies>
				<SizeBasedTriggeringPolicy size="10MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
			<DefaultRolloverstrategy>
				<Delete basePath="/logs" maxDepth="3">
					<IfLastModified age="60d" />
				</Delete>
			</DefaultRolloverstrategy>
		</RollingFile>

		<RollingFile name="ErrorAppender"
			fileName="${FILENAME}/error.log" filePattern="${FILENAME}/%d{yyyy-MM-dd}/error.log">
			<PatternLayout pattern="${LAYOUT} %throwable{full}" />
			<LevelRangeFilter minLevel="ERROR" maxLevel="ERROR"
				onMatch="ACCEPT" onMismatch="DENY" />
			<Policies>
				<SizeBasedTriggeringPolicy size="10MB" />
				<TimeBasedTriggeringPolicy />
			</Policies>
			<DefaultRolloverstrategy>
				<Delete basePath="/logs" maxDepth="3">
					<IfLastModified age="60d" />
				</Delete>
			</DefaultRolloverstrategy>
		</RollingFile>
	</Appenders>


	<Loggers>
		<Logger name="co.cheolcheol.log" additivity="true">
			<AppenderRef ref="FatalAppender" />
			<AppenderRef ref="InfoAppender"  />
			<AppenderRef ref="WarnAppender"  />
			<AppenderRef ref="ErrorAppender" />
		</Logger>
        <!-- Root는 필수로 있어야 함 -->
		<Root level="INFO">
			<!-- <AppenderRef ref="console" />  -->
		</Root>
	</Loggers>
</configuration>

 

사용 예제는 다음과 같습니다.

@Log4j2
@Component
@Order(1)
public class SecurityFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest)request;
		log.info("Starting a transaction for req : {}", req.getRequestURI());
		
		chain.doFilter(request, response);
		
		log.info("Committing a transaction for req : {}", req.getRequestURI());
	}


}

어노테이션에서 @Log4j2가 보이실텐데, 이게 Lombok을 이용하여 바로 생성을 해준겁니다. 그 외에도 @SLF4j 등 다양한 로그 어노테이션이 있습니다.

 

Lombok을 사용 안하신다면  공홈 예제 처럼 변수 생성하고 해야해서 귀찮습니다.

 

어노테이션을 추가하면 log.info 처럼 로그를 이용하실 수 있습니다.

참고 및 출처

Log

https://ko.wikipedia.org/wiki/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%BC

 

SLF4j

https://en.wikipedia.org/wiki/SLF4J

 

Log4j2 

https://logging.apache.org/log4j/2.x/

 

 

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte3:fdl:%EC%84%A4%EC%A0%95_%ED%8C%8C%EC%9D%BC%EC%9D%84_%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94_%EB%B0%A9%EB%B2%95

 

https://m.blog.naver.com/PostView.nhn?blogId=cestlavie_01&logNo=220520201514&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

반응형

'BackEnd > Java' 카테고리의 다른 글

Spring boot JPA DTO Mapping ( Native Query to DTO )  (0) 2020.01.05
pm2 java  (0) 2019.09.24
Spring boot AWS S3를 이용한 File Upload/Download  (1) 2019.08.26
Java send HTTP request  (0) 2019.04.02
Spring boot + Mybatis 연결하기  (0) 2019.03.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함