spring core advanced : ThreadLocal
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package com.example.advanced;
|
||||
|
||||
import com.example.advanced.trace.logtrace.FieldLogTrace;
|
||||
import com.example.advanced.trace.logtrace.LogTrace;
|
||||
import com.example.advanced.trace.logtrace.ThreadLocalLogTrace;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -10,6 +10,6 @@ public class LogTraceConfig {
|
||||
|
||||
@Bean
|
||||
public LogTrace logTrace() {
|
||||
return new FieldLogTrace();
|
||||
return new ThreadLocalLogTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.example.advanced.trace.logtrace;
|
||||
|
||||
import com.example.advanced.trace.TraceId;
|
||||
import com.example.advanced.trace.TraceStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ThreadLocalLogTrace implements LogTrace {
|
||||
|
||||
private static final String START_PREFIX = "-->";
|
||||
private static final String COMPLETE_PREFIX = "<--";
|
||||
private static final String EX_PREFIX = "<X-";
|
||||
|
||||
private ThreadLocal<TraceId> traceIdHolder = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public TraceStatus begin(String message) {
|
||||
syncTraceId();
|
||||
TraceId traceId = traceIdHolder.get();
|
||||
long startTimeMs = System.currentTimeMillis();
|
||||
log.info("[{}] {}{}", traceId.getId(), addSpace(START_PREFIX, traceId.getLevel()), message);
|
||||
return new TraceStatus(traceId, startTimeMs, message);
|
||||
}
|
||||
|
||||
private void syncTraceId() {
|
||||
TraceId traceId = traceIdHolder.get();
|
||||
if (traceId == null) {
|
||||
traceIdHolder.set(new TraceId());
|
||||
} else {
|
||||
traceIdHolder.set(traceId.createNextId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(TraceStatus status) {
|
||||
complete(status, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exception(TraceStatus status, Exception e) {
|
||||
complete(status, e);
|
||||
}
|
||||
|
||||
private void complete(TraceStatus status, Exception e) {
|
||||
long stopTimeMs = System.currentTimeMillis();
|
||||
long resultTimeMs = stopTimeMs - status.getStartTimeMs();
|
||||
TraceId traceId = status.getTraceId();
|
||||
if (e == null) {
|
||||
log.info("[{}] {}{} time={}ms", traceId.getId(), addSpace(COMPLETE_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs);
|
||||
} else {
|
||||
log.info("[{}] {}{} time={}ms ex={}: 예외 발생!", traceId.getId(), addSpace(EX_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs, e.getClass());
|
||||
}
|
||||
|
||||
releaseTraceId();
|
||||
}
|
||||
|
||||
private void releaseTraceId() {
|
||||
TraceId traceId = traceIdHolder.get();
|
||||
if (traceId.isFirstLevel()) {
|
||||
traceIdHolder.remove();
|
||||
} else {
|
||||
traceIdHolder.set(traceId.createPreviousId());
|
||||
}
|
||||
}
|
||||
|
||||
private String addSpace(String prefix, int level) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < level; i++) {
|
||||
sb.append((i == level - 1) ? "|" + prefix : "| ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.advanced.trace.logtrace;
|
||||
|
||||
import com.example.advanced.trace.TraceStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ThreadLocalLogTraceTest {
|
||||
|
||||
ThreadLocalLogTrace trace = new ThreadLocalLogTrace();
|
||||
|
||||
@Test
|
||||
void begin_end_level2() {
|
||||
TraceStatus status1 = trace.begin("hello1");
|
||||
TraceStatus status2 = trace.begin("hello2");
|
||||
trace.end(status2);
|
||||
trace.end(status1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void begin_exception_level2() {
|
||||
TraceStatus status1 = trace.begin("hello1");
|
||||
TraceStatus status2 = trace.begin("hello2");
|
||||
trace.exception(status2, new IllegalStateException());
|
||||
trace.exception(status1, new IllegalStateException());
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import org.junit.jupiter.api.Test;
|
||||
@Slf4j
|
||||
public class FieldServiceTest {
|
||||
|
||||
private FieldService fieldService = new FieldService();
|
||||
private final FieldService fieldService = new FieldService();
|
||||
|
||||
@Test
|
||||
void field() {
|
||||
@@ -23,7 +23,7 @@ public class FieldServiceTest {
|
||||
Thread threadA = new Thread(userA);
|
||||
threadA.setName("thread-A");
|
||||
Thread threadB = new Thread(userB);
|
||||
threadA.setName("thread-B");
|
||||
threadB.setName("thread-B");
|
||||
|
||||
threadA.start();
|
||||
// sleep(2000);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.example.advanced.trace.threadlocal;
|
||||
|
||||
import com.example.advanced.trace.threadlocal.code.ThreadLocalService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Slf4j
|
||||
public class ThreadLocalServiceTest {
|
||||
|
||||
private final ThreadLocalService threadLocalService = new ThreadLocalService();
|
||||
|
||||
@Test
|
||||
void field() {
|
||||
log.info("main start");
|
||||
Runnable userA = () -> {
|
||||
threadLocalService.logic("userA");
|
||||
};
|
||||
|
||||
Runnable userB = () -> {
|
||||
threadLocalService.logic("userB");
|
||||
};
|
||||
|
||||
Thread threadA = new Thread(userA);
|
||||
threadA.setName("thread-A");
|
||||
Thread threadB = new Thread(userB);
|
||||
threadB.setName("thread-B");
|
||||
|
||||
threadA.start();
|
||||
// sleep(2000);
|
||||
threadB.start();
|
||||
sleep(3000);
|
||||
log.info("main exit");
|
||||
}
|
||||
|
||||
private void sleep(int millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.advanced.trace.threadlocal.code;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ThreadLocalService {
|
||||
|
||||
private ThreadLocal<String> nameStore = new ThreadLocal<>();
|
||||
|
||||
public String logic(String name) {
|
||||
log.info("저장 name={} -> nameStore={}", name, nameStore.get());
|
||||
nameStore.set(name);
|
||||
sleep(1000);
|
||||
log.info("조회 nameStore={}", nameStore.get());
|
||||
return nameStore.get();
|
||||
}
|
||||
|
||||
private void sleep(int millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user