From 6a63099ad01a8e753c8ec2c0eed392d41eab0c35 Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Mon, 12 Nov 2012 08:01:50 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[LUCYSUS-1744]?= =?UTF-8?q?=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EC=A0=81=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@855 84d0f5b1-2673-498c-a247-62c4ff18d310 --- .../java/com/profiler/context/AsyncTrace.java | 128 ++++++++++++++++++ .../java/com/profiler/context/CallStack.java | 31 +++-- .../com/profiler/context/GlobalCallTrace.java | 35 +++++ src/main/java/com/profiler/context/Trace.java | 27 ++-- .../com/profiler/context/TraceContext.java | 8 ++ .../modifier/DefaultModifierRegistry.java | 6 +- .../modifier/arcus/ArcusClientModifier.java | 48 ++++--- .../BaseOperationImplInterceptor.java | 59 ++++++++ .../interceptors/ConstructInterceptor.java | 40 ++++++ .../StandardHostValveInvokeInterceptor.java | 2 +- 10 files changed, 336 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/profiler/context/AsyncTrace.java create mode 100644 src/main/java/com/profiler/context/GlobalCallTrace.java create mode 100644 src/main/java/com/profiler/modifier/arcus/interceptors/BaseOperationImplInterceptor.java create mode 100644 src/main/java/com/profiler/modifier/arcus/interceptors/ConstructInterceptor.java diff --git a/src/main/java/com/profiler/context/AsyncTrace.java b/src/main/java/com/profiler/context/AsyncTrace.java new file mode 100644 index 000000000..1b52d1609 --- /dev/null +++ b/src/main/java/com/profiler/context/AsyncTrace.java @@ -0,0 +1,128 @@ +package com.profiler.context; + +import com.profiler.common.util.AnnotationTranscoder; +import com.profiler.sender.DataSender; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class AsyncTrace { + private Logger logger = Logger.getLogger(this.getClass().getName()); + // 일단 c&p + private static final AnnotationTranscoder transcoder = new AnnotationTranscoder(); + // private int id; + // 비동기일 경우 traceenable의 경우 애매함. span을 보내는것으로 데이터를 생성하므로 약간 이상. +// private boolean tracingEnabled; + private Span span; + private DataSender dataSender; + + public AsyncTrace(Span span) { + this.span = span; + } + + public void record(Annotation annotation) { + annotate(annotation.getCode(), null); + } + + public void record(Annotation annotation, long duration) { + annotate(annotation.getCode(), duration); + } + + public void recordAttribute(final String key, final String value) { + recordAttibute(key, (Object) value); + } + + public void recordAttibute(final String key, final Object value) { + try { + // TODO 사용자 thread에서 encoding을 하지 않도록 변경. + AnnotationTranscoder.Encoded enc = transcoder.encode(value); + span.addAnnotation(new HippoAnnotation(System.currentTimeMillis(), key, enc.getValueType(), enc.getBytes(), null)); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } + + public void recordMessage(String message) { + annotate(message, null); + } + + public void recordRpcName(final String service, final String rpc) { + + try { + spanUpdate(new SpanUpdater() { + @Override + public Span updateSpan(Span span) { + span.setServiceName(service); + span.setName(rpc); + return span; + } + }); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } + + public void recordTerminalEndPoint(final String endPoint) { + recordEndPoint(endPoint, true); + } + + public void recordEndPoint(final String endPoint) { + recordEndPoint(endPoint, false); + } + + // TODO: final String... endPoint로 받으면 합치는데 비용이 들어가 그냥 한번에 받는게 나을것 같음. + private void recordEndPoint(final String endPoint, final boolean isTerminal) { + try { + spanUpdate(new SpanUpdater() { + @Override + public Span updateSpan(Span span) { + // set endpoint to both span and annotations + span.setEndPoint(endPoint); + span.setTerminal(isTerminal); + return span; + } + }); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } + + private void annotate(final String key, final Long duration) { + + try { + spanUpdate(new SpanUpdater() { + @Override + public Span updateSpan(Span span) { + span.addAnnotation(new HippoAnnotation(System.currentTimeMillis(), key, duration)); + return span; + } + }); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } + + + private void spanUpdate(SpanUpdater spanUpdater) { + if (span.isExistsAnnotationKey(Annotation.ClientRecv.getCode()) || span.isExistsAnnotationKey(Annotation.ServerSend.getCode())) { + logSpan(span); + } + } + + void logSpan(Span span) { + try { + if (logger.isLoggable(Level.INFO)) { + Thread thread = Thread.currentThread(); + logger.info("[WRITE SPAN]" + span + " CurrentThreadID=" + thread.getId() + ",\n\t CurrentThreadName=" + thread.getName()); + } + + this.dataSender.send(span.toThrift()); +// span.cancelTimer(); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + } +} diff --git a/src/main/java/com/profiler/context/CallStack.java b/src/main/java/com/profiler/context/CallStack.java index 18e17bf55..d5935f6a5 100644 --- a/src/main/java/com/profiler/context/CallStack.java +++ b/src/main/java/com/profiler/context/CallStack.java @@ -1,5 +1,7 @@ package com.profiler.context; +import java.util.Arrays; + /** * @author netspider */ @@ -7,15 +9,18 @@ public class CallStack { // CallStack을 동시성 환경에서 복사해서 볼수 있는 방법이 필요함. private StackFrame[] stack = new StackFrame[4]; - // TODO 개별변수에 volatile을해도 동시성이 해결되지 않으므로 일단 제거. + // 추적 depth크기 제한을 위해서 필요. 해당 사이즈를 넘어갈경우 부드럽게 트레이스를 무시하는 로직이 필요함. + private final int TRACE_STACK_MAX_SIZE = 64; + private int index = 0; - - public StackFrame getCurrentStackFrame() { + // copy시의 락 생각할 경우 좀더 정교하게 잡을수 있을듯. + // push, pop, copy만 락을 잡아도 될거 같은 생각이 듬. + public synchronized StackFrame getCurrentStackFrame() { return stack[index]; } - public StackFrame getParentStackFrame() { + public synchronized StackFrame getParentStackFrame() { if (index > 0) { return stack[index - 1]; } @@ -23,11 +28,11 @@ public class CallStack { } - public void setStackFrame(StackFrame stackFrame) { + public synchronized void setStackFrame(StackFrame stackFrame) { stack[index] = stackFrame; } - public void push() { + public synchronized void push() { index++; if (index > stack.length - 1) { StackFrame[] old = stack; @@ -36,18 +41,24 @@ public class CallStack { } } - public int getStackFrameIndex() { + public synchronized int getStackFrameIndex() { return index; } - public void pop() { + public synchronized void pop() { if (index > 0) { -// TODO 이전 reference를 제거해야 되나? + stack[index] = null; index--; } } - public void currentStackFrameClear() { + public synchronized void currentStackFrameClear() { stack[index] = null; } + + public synchronized StackFrame[] copyStackFrame() { + StackFrame[] copy = new StackFrame[index]; + System.arraycopy(stack, 0, copy, 0, index); + return copy; + } } diff --git a/src/main/java/com/profiler/context/GlobalCallTrace.java b/src/main/java/com/profiler/context/GlobalCallTrace.java new file mode 100644 index 000000000..3a5711697 --- /dev/null +++ b/src/main/java/com/profiler/context/GlobalCallTrace.java @@ -0,0 +1,35 @@ +package com.profiler.context; + +import com.profiler.sender.DataSender; + +import java.util.Timer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * + */ +public class GlobalCallTrace { + private static AtomicInteger timerId = new AtomicInteger(0); + + private ConcurrentMap trace = new ConcurrentHashMap(32); + private AtomicInteger idGenerator = new AtomicInteger(0); + private DataSender dataSender; + + private Timer timer = new Timer("GlobalCallTrace-Timer-" + timerId.getAndIncrement(), true); + + public int registerTraceObject(T target) { + int id = idGenerator.getAndIncrement(); + trace.put(id, target); + return id; + } + + public T removeTraceObject(int id) { + return trace.get(id); + } + + public void setDataSender(DataSender dataSender) { + this.dataSender = dataSender; + } +} diff --git a/src/main/java/com/profiler/context/Trace.java b/src/main/java/com/profiler/context/Trace.java index a920c7117..1bec1aeb6 100644 --- a/src/main/java/com/profiler/context/Trace.java +++ b/src/main/java/com/profiler/context/Trace.java @@ -15,31 +15,33 @@ public final class Trace { private final Logger logger = Logger.getLogger(Trace.class.getName()); + private static final AnnotationTranscoder transcoder = new AnnotationTranscoder(); + private static final DataSender DEFULT_DATA_SENDER = new LoggingDataSender(); + public static final int HANDLER_STACKID = -2; public static final int NOCHECK_STACKID = -1; public static final int ROOT_STACKID = 0; // private static final DeadlineSpanMap spanMap = new DeadlineSpanMap(); - // private static final ThreadLocal traceIdLocal = new NamedThreadLocal("TraceId"); private boolean tracingEnabled = true; private TraceID root; private CallStack callStack; - private static final AnnotationTranscoder transcoder = new AnnotationTranscoder(); - private static final DataSender DEFULT_DATA_SENDER = new LoggingDataSender(); + private DataSender dataSender = DEFULT_DATA_SENDER; public Trace() { + // traceObject에서 spanid의 유효성을 히스토리를 관리한다면 같은 thread에서는 span랜덤생성아이디의 충돌을 방지할수 있기는 함. this.root = TraceID.newTraceId(); this.callStack = new CallStack(); - StackFrame stackFrame = createCallInfo(root, ROOT_STACKID); + StackFrame stackFrame = createStackFrame(root, ROOT_STACKID); this.callStack.setStackFrame(stackFrame); } public Trace(TraceID continueRoot) { this.root = continueRoot; this.callStack = new CallStack(); - StackFrame stackFrame = createCallInfo(continueRoot, ROOT_STACKID); + StackFrame stackFrame = createStackFrame(continueRoot, ROOT_STACKID); this.callStack.setStackFrame(stackFrame); } @@ -55,7 +57,7 @@ public final class Trace { try { TraceID nextId = getNextTraceId(); callStack.push(); - StackFrame stackFrame = createCallInfo(nextId, HANDLER_STACKID); + StackFrame stackFrame = createStackFrame(nextId, HANDLER_STACKID); callStack.setStackFrame(stackFrame); handler.handle(nextId); } catch (Exception e) { @@ -66,7 +68,7 @@ public final class Trace { } } - private StackFrame createCallInfo(TraceID nextId, int stackId) { + private StackFrame createStackFrame(TraceID nextId, int stackId) { StackFrame stackFrame = new StackFrame(); stackFrame.setStackFrameId(stackId); stackFrame.setTraceID(nextId); @@ -81,19 +83,19 @@ public final class Trace { } public void markBeforeTime() { - StackFrame context = getCurrentStackContext(); + StackFrame context = getCurrentStackFrame(); context.markBeforeTime(); } public long afterTime() { - StackFrame context = getCurrentStackContext(); + StackFrame context = getCurrentStackFrame(); return context.afterTime(); } public void traceBlockBegin(int stackId) { TraceID nextId = getNextTraceId(); callStack.push(); - StackFrame stackFrame = createCallInfo(nextId, stackId); + StackFrame stackFrame = createStackFrame(nextId, stackId); callStack.setStackFrame(stackFrame); } @@ -110,7 +112,7 @@ public final class Trace { callStack.pop(); } - public StackFrame getCurrentStackContext() { + public StackFrame getCurrentStackFrame() { return callStack.getCurrentStackFrame(); } @@ -149,12 +151,13 @@ public final class Trace { private void spanUpdate(SpanUpdater spanUpdater) { - StackFrame currentStackFrame = getCurrentStackContext(); + StackFrame currentStackFrame = getCurrentStackFrame(); Span span = spanUpdater.updateSpan(currentStackFrame.getSpan()); if (span.isExistsAnnotationKey(Annotation.ClientRecv.getCode()) || span.isExistsAnnotationKey(Annotation.ServerSend.getCode())) { // remove current context threadId from callStack // removeCurrentTraceIdFromStack(); logSpan(span); + } } diff --git a/src/main/java/com/profiler/context/TraceContext.java b/src/main/java/com/profiler/context/TraceContext.java index d962938eb..38296daa9 100644 --- a/src/main/java/com/profiler/context/TraceContext.java +++ b/src/main/java/com/profiler/context/TraceContext.java @@ -23,8 +23,11 @@ public class TraceContext { private final ActiveThreadCounter activeThreadCounter = new ActiveThreadCounter(); private static final DataSender DEFAULT_DATA_SENDER = new LoggingDataSender(); + private DataSender dataSender = DEFAULT_DATA_SENDER; + private GlobalCallTrace globalCallTrace = new GlobalCallTrace(); + public TraceContext() { } @@ -48,11 +51,16 @@ public class TraceContext { this.threadLocal.set(null); } + public GlobalCallTrace getGlobalCallTrace() { + return globalCallTrace; + } + public ActiveThreadCounter getActiveThreadCounter() { return activeThreadCounter; } public void setDataSender(DataSender dataSender) { this.dataSender = dataSender; + this.globalCallTrace.setDataSender(dataSender); } } diff --git a/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java index a9e8f046c..e8b834e9f 100644 --- a/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java +++ b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java @@ -54,9 +54,9 @@ public class DefaultModifierRegistry implements ModifierRegistry { public void addConnectorModifier() { HTTPClientModifier httpClientModifier = new HTTPClientModifier(byteCodeInstrumentor); addModifier(httpClientModifier); -// 잠시 arcus안되게 주석처리. -// ArcusClientModifier arcusClientModifier = new ArcusClientModifier(byteCodeInstrumentor); -// addModifier(arcusClientModifier); + + ArcusClientModifier arcusClientModifier = new ArcusClientModifier(byteCodeInstrumentor); + addModifier(arcusClientModifier); } public void addTomcatModifier() { diff --git a/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java b/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java index d66b3c2db..c6a440957 100644 --- a/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java +++ b/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java @@ -7,6 +7,7 @@ import java.util.logging.Logger; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; import com.profiler.modifier.AbstractModifier; +import com.profiler.modifier.arcus.interceptors.ConstructInterceptor; /** * @author netspider @@ -31,29 +32,32 @@ public class ArcusClientModifier extends AbstractModifier { try { InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - /** - * inject both current and next traceId. - */ - aClass.addTraceVariable("__traceId", "__setTraceId", "__getTraceId", "com.profiler.context.TraceID"); - aClass.addTraceVariable("__nextTraceId", "__setNextTraceId", "__getNextTraceId", "com.profiler.context.TraceID"); - aClass.insertCodeAfterConstructor(null, "{ __setTraceId(com.profiler.context.Trace.getCurrentTraceId()); __setNextTraceId(com.profiler.context.Trace.getNextTraceId()); }"); + aClass.addTraceVariable("__asyncTraceId", "__setAsyncTraceId", "__getAsyncTraceId", "int"); + aClass.addConstructorInterceptor(null, new ConstructInterceptor()); - /** - * inject nano time for checking send time. - */ - aClass.addTraceVariable("__commandCreatedTime", "__setCommandCreatedTime", "__getCommandCreatedTime", "long"); - aClass.insertCodeAfterConstructor(null, "{ __setCommandCreatedTime(System.nanoTime()); }"); - - /** - * inject cancelled time - */ - aClass.addTraceVariable("__cancelledTime", "__setCancelledTime", "__getCancelledTime", "long"); - - /** - * insert trace code. - */ - aClass.insertCodeBeforeMethod("transitionState", new String[]{"net.spy.memcached.ops.OperationState"}, getTransitionStateAfterCode()); - aClass.insertCodeBeforeMethod("cancel", null, getCancelBeforeCode()); +// /** +// * inject both current and next traceId. +// */ +// aClass.addTraceVariable("__traceId", "__setTraceId", "__getTraceId", "com.profiler.context.TraceID"); +// aClass.addTraceVariable("__nextTraceId", "__setNextTraceId", "__getNextTraceId", "com.profiler.context.TraceID"); +// aClass.insertCodeAfterConstructor(null, "{ __setTraceId(com.profiler.context.Trace.getCurrentTraceId()); __setNextTraceId(com.profiler.context.Trace.getNextTraceId()); }"); +// +// /** +// * inject nano time for checking send time. +// */ +// aClass.addTraceVariable("__commandCreatedTime", "__setCommandCreatedTime", "__getCommandCreatedTime", "long"); +// aClass.insertCodeAfterConstructor(null, "{ __setCommandCreatedTime(System.nanoTime()); }"); +// +// /** +// * inject cancelled time +// */ +// aClass.addTraceVariable("__cancelledTime", "__setCancelledTime", "__getCancelledTime", "long"); +// +// /** +// * insert trace code. +// */ +// aClass.insertCodeBeforeMethod("transitionState", new String[]{"net.spy.memcached.ops.OperationState"}, getTransitionStateAfterCode()); +// aClass.insertCodeBeforeMethod("cancel", null, getCancelBeforeCode()); return aClass.toBytecode(); } catch (Exception e) { diff --git a/src/main/java/com/profiler/modifier/arcus/interceptors/BaseOperationImplInterceptor.java b/src/main/java/com/profiler/modifier/arcus/interceptors/BaseOperationImplInterceptor.java new file mode 100644 index 000000000..ce9081b8f --- /dev/null +++ b/src/main/java/com/profiler/modifier/arcus/interceptors/BaseOperationImplInterceptor.java @@ -0,0 +1,59 @@ +package com.profiler.modifier.arcus.interceptors; + +import com.profiler.context.AsyncTrace; +import com.profiler.context.GlobalCallTrace; +import com.profiler.context.Trace; +import com.profiler.context.TraceContext; +import com.profiler.interceptor.StaticAfterInterceptor; + +/** + * + */ +public class BaseOperationImplInterceptor implements StaticAfterInterceptor { + @Override + public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { + + TraceContext traceContext = TraceContext.getTraceContext(); + GlobalCallTrace globalCallTrace = traceContext.getGlobalCallTrace(); + AsyncTrace asyncTrace = globalCallTrace.removeTraceObject(1); + +// com.profiler.context.Trace.setTraceId(__nextTraceId); +// +// +// /** +// * After sending command to the Arcus server. now waiting server +// * response. +// */ +// code.append("if (newState == net.spy.memcached.ops.OperationState.READING) {"); +// +// code.append(" java.net.SocketAddress socketAddress = handlingNode.getSocketAddress();"); +// code.append(" if (socketAddress instanceof java.net.InetSocketAddress) {"); +// code.append(" java.net.InetSocketAddress addr = (java.net.InetSocketAddress) handlingNode.getSocketAddress();"); +// code.append(" com.profiler.context.Trace.recordTerminalEndPoint(\"ARCUS:\" + addr.getHostName() + \":\" + addr.getPort());"); +// code.append(" }"); +// code.append(" com.profiler.context.Trace.recordRpcName(\"ARCUS\", this.getClass().getSimpleName());"); +// code.append(" com.profiler.context.Trace.recordAttribute(\"arcus.command\", ((cmd == null) ? \"UNKNOWN\" : new String(cmd.array())));"); +// code.append(" com.profiler.StopWatch.start(this.hashCode());"); +// code.append(" com.profiler.context.Trace.record(com.profiler.context.Annotation.ClientSend, System.nanoTime() - __commandCreatedTime);"); + + /** + * Received all response or timed out. + */ +// code.append("} else if (newState == net.spy.memcached.ops.OperationState.COMPLETE || newState == net.spy.memcached.ops.OperationState.TIMEDOUT) {"); +// code.append(" if (exception != null) { "); +// code.append(" com.profiler.context.Trace.recordAttribute(\"exception\", com.profiler.util.InterceptorUtils.exceptionToString(exception));"); +// code.append(" }"); +// +// code.append(" if (!cancelled) {"); +// code.append(" com.profiler.context.Trace.record(com.profiler.context.Annotation.ClientRecv, com.profiler.StopWatch.stopAndGetElapsed(this.hashCode()));"); +// code.append(" } else {"); +// code.append(" com.profiler.context.Trace.recordAttribute(\"exception\", \"cancelled by user\");"); +// code.append(" com.profiler.context.Trace.record(com.profiler.context.Annotation.ClientRecv, System.nanoTime() - __cancelledTime);"); +// code.append(" }"); +// +// code.append("}"); +// +//// code.append("com.profiler.context.Trace.traceBlockEnd();"); +// code.append("}"); + } +} diff --git a/src/main/java/com/profiler/modifier/arcus/interceptors/ConstructInterceptor.java b/src/main/java/com/profiler/modifier/arcus/interceptors/ConstructInterceptor.java new file mode 100644 index 000000000..6b9a5f9e7 --- /dev/null +++ b/src/main/java/com/profiler/modifier/arcus/interceptors/ConstructInterceptor.java @@ -0,0 +1,40 @@ +package com.profiler.modifier.arcus.interceptors; + +import com.profiler.context.*; +import com.profiler.interceptor.StaticAfterInterceptor; +import com.profiler.util.MetaObject; +import com.profiler.util.StringUtils; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class ConstructInterceptor implements StaticAfterInterceptor { + + private final Logger logger = Logger.getLogger(ConstructInterceptor.class.getName()); + private MetaObject asyncTraceId = new MetaObject("__setAsyncTraceId", int.class); + + @Override + public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { + if (logger.isLoggable(Level.INFO)) { + logger.info("after " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args) + " result:" + result); + } + TraceContext traceContext = TraceContext.getTraceContext(); + Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + GlobalCallTrace globalCallTrace = traceContext.getGlobalCallTrace(); + + TraceID nextTraceId = trace.getNextTraceId(); + Span span = new Span(nextTraceId, null, null); + AsyncTrace asyncTrace = new AsyncTrace(span); + + int asyncId = globalCallTrace.registerTraceObject(asyncTrace); + + asyncTraceId.invoke(target, asyncId); + } +} diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java index 7d8611891..9904c87b3 100644 --- a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java @@ -80,7 +80,7 @@ public class StandardHostValveInvokeInterceptor implements StaticAroundIntercept return; } traceContext.detachTraceObject(); - if (trace.getCurrentStackContext().getStackFrameId() != 0) { + if (trace.getCurrentStackFrame().getStackFrameId() != 0) { logger.warning("Corrupted CallStack found. StackId not Root(0)"); // 문제 있는 callstack을 dump하면 도움이 될듯. }