본문 바로가기

WEB개발

[WEB개발] TheadLocal & MDC & Log4j2

 서버에서 로그를  확인할 경우 grep으로 로그를 캐치할 시 라인단위로 인식하기 때문에 모든 trace를 볼 수 없다.  MDC와 log4j2를 사용하면 각 접속한 IP별로 로그를 확인 할 수 있다.

 

ThreadLocal 

 

ThreadLocal 변수를 선언하면 멀티 스레드 환경에서 각 스레드마다 독립적인 변수를 가지고, get(), set() 메소드를 통해 값에 대해 접근할 수 있다.

 

public class TestThread implements Runnable {
	private ThreadLocal threadLocal = new ThreadLocal<DataObj>() {
		@Override protected DataObj initialValue() {
			DataObj dataObj = new DataObj();
			return dataObj;
	    }
	};
	
	@Override
	public void run() {
		
		DataObj dataObj = (DataObj) threadLocal.get();
		dataObj.setTrxNo(Math.random() + "");
		
		threadLocal.set(dataObj);
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(((DataObj) threadLocal.get()).getTrxNo());
	}

> 두 개의 쓰레드 런

0.5002465179334552
0.3244909506839274

 

MDC (Mapped Diagnostic Context)

 

 멀티 클라이언트 환경에서 다른 클라이언트와 값을 구별하여 로그를 추적할 수 있도록 제공되는 map이다.

ThreadLocal에 구별할 수 있는 키 값을 저장하여 Thread가 존재하는 동안 계속해서 사용할 수 있도록 하는 방법으로

현재 log4j 및 logback만 MDC기능을 제공하고 있다.

 

 MDC는 static으로 올라간 맵에 저장된다

public class MDCManager {
	private String clientIp;
	public String getClientIp() {
		return clientIp;
	}
	public void setClientIp(String clientIp) {
		MDC.put("clientIp" , clientIp);
		this.clientIp = clientIp;
	}
}

 

Log4j2

pom.xml 로깅

<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
<!-- Log4j2 SLF4J Bridge -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.5</version>
</dependency>
<!-- SLF4J JCL Bridge -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.18</version>
</dependency>

<!-- SLF4J Log4j 1.x Bridge -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.18</version>
</dependency>
<!-- Logging -->

 

log4j2.xml 설정

쓰레드로컬에 저장된 아이피별로 라우팅 시킨다.

 

패턴에 클라이언트 아이피가 있다면 라우팅 시킨다. 그러나 그 값이 DEFAULT라면 DEFAULT로 라우트한다.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>

	<!-- Appenders -->
	<Appenders>
		<Console name="STDOUT" target="SYSTEM_OUT">
			<PatternLayout pattern="%d %-5p [$${ctx:clientIp}][%t] %C{2} (%F:%L) - %m%n" />
		</Console>
		
		<Routing name="ROUTING">
			<Routes pattern="$${ctx:clientIp}">
	            <Route>
	                <RollingFile name="Rolling-${ctx:clientIp}" 
	                	fileName="C:/logs/myapp/${ctx:clientIp}_myapp.out" 
	                	filePattern="C:/logs/myapp/${ctx:clientIp}_myapp-%d{yyyy-MM-dd}.out">
						<PatternLayout>
							<pattern>%d{yyyy-MM-dd:hh:mm:ss} [%p][%C{1}][%M (%L)}][$${ctx:clientIp}] | %m%n</pattern>
						</PatternLayout>
						<Policies>
							<SizeBasedTriggeringPolicy size="50MB"/>
						</Policies>
						<DefaultRolloverStrategy max="1"/>
	                </RollingFile>
	            </Route>
	            
	            <Route key="DEFAULT">
	                <RollingFile name="Rolling-default" 
	                	fileName="C:/logs/myapp/default_myapp.out" 
	                	filePattern="C:/logs/myapp/default_myapp-%d{yyyy-MM-dd}.out">
						<PatternLayout>
							<pattern>%d{yyyy-MM-dd:hh:mm:ss} [%p][%C{1}][%M (%L)}][$${ctx:clientIp}] | %m%n</pattern>
						</PatternLayout>
						<Policies>
							<SizeBasedTriggeringPolicy size="50MB"/>
						</Policies>
						<DefaultRolloverStrategy max="1"/>
	                </RollingFile>
	            </Route>
	            
	        </Routes>
		</Routing>
	</Appenders>
	
	<Loggers>
		<!-- Application Loggers -->
		<Logger name="com.woo.test" level="debug">
			<AppenderRef ref="STDOUT" />
			<AppenderRef ref="ROUTING" />
		</Logger> 
		
		<Root level="debug">
		</Root>
	</Loggers>
</Configuration>

 

 

 

참조

https://055055.tistory.com/96