mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-16 00:05:57 +10:00
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@859 84d0f5b1-2673-498c-a247-62c4ff18d310
268 lines
8.2 KiB
Java
268 lines
8.2 KiB
Java
package com.profiler.context;
|
|
|
|
import com.profiler.common.util.AnnotationTranscoder;
|
|
import com.profiler.common.util.AnnotationTranscoder.Encoded;
|
|
import com.profiler.sender.DataSender;
|
|
import com.profiler.sender.LoggingDataSender;
|
|
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
/**
|
|
* @author netspider
|
|
*/
|
|
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 boolean tracingEnabled = true;
|
|
|
|
private TraceID root;
|
|
private CallStack callStack;
|
|
|
|
private DataSender dataSender = DEFULT_DATA_SENDER;
|
|
|
|
public Trace() {
|
|
// traceObject에서 spanid의 유효성을 히스토리를 관리한다면 같은 thread에서는 span랜덤생성아이디의 충돌을 방지할수 있기는 함.
|
|
this.root = TraceID.newTraceId();
|
|
this.callStack = new CallStack();
|
|
StackFrame stackFrame = createStackFrame(root, ROOT_STACKID);
|
|
this.callStack.setStackFrame(stackFrame);
|
|
}
|
|
|
|
public Trace(TraceID continueRoot) {
|
|
this.root = continueRoot;
|
|
this.callStack = new CallStack();
|
|
StackFrame stackFrame = createStackFrame(continueRoot, ROOT_STACKID);
|
|
this.callStack.setStackFrame(stackFrame);
|
|
}
|
|
|
|
public DataSender getDataSender() {
|
|
return dataSender;
|
|
}
|
|
|
|
public void setDataSender(DataSender dataSender) {
|
|
this.dataSender = dataSender;
|
|
}
|
|
|
|
public void handle(TraceHandler handler) {
|
|
try {
|
|
TraceID nextId = getNextTraceId();
|
|
callStack.push();
|
|
StackFrame stackFrame = createStackFrame(nextId, HANDLER_STACKID);
|
|
callStack.setStackFrame(stackFrame);
|
|
handler.handle(nextId);
|
|
} finally {
|
|
// stackID check하면 좋을듯.
|
|
callStack.pop();
|
|
}
|
|
}
|
|
|
|
private StackFrame createStackFrame(TraceID nextId, int stackId) {
|
|
StackFrame stackFrame = new StackFrame();
|
|
stackFrame.setStackFrameId(stackId);
|
|
stackFrame.setTraceID(nextId);
|
|
|
|
Span span = new Span(nextId, null, null);
|
|
stackFrame.setSpan(span);
|
|
return stackFrame;
|
|
}
|
|
|
|
public void traceBlockBegin() {
|
|
traceBlockBegin(NOCHECK_STACKID);
|
|
}
|
|
|
|
public void markBeforeTime() {
|
|
StackFrame context = getCurrentStackFrame();
|
|
context.markBeforeTime();
|
|
}
|
|
|
|
public long afterTime() {
|
|
StackFrame context = getCurrentStackFrame();
|
|
return context.afterTime();
|
|
}
|
|
|
|
public void traceBlockBegin(int stackId) {
|
|
TraceID nextId = getNextTraceId();
|
|
callStack.push();
|
|
StackFrame stackFrame = createStackFrame(nextId, stackId);
|
|
callStack.setStackFrame(stackFrame);
|
|
}
|
|
|
|
public void traceBlockEnd() {
|
|
traceBlockEnd(NOCHECK_STACKID);
|
|
}
|
|
|
|
public void traceBlockEnd(int stackId) {
|
|
StackFrame currentStackFrame = callStack.getCurrentStackFrame();
|
|
if (currentStackFrame.getStackFrameId() != stackId) {
|
|
// 자체 stack dump를 하면 오류발견이 쉬울것으로 생각됨.
|
|
logger.warning("Corrupted CallStack found. StackId not matched");
|
|
}
|
|
callStack.pop();
|
|
}
|
|
|
|
public StackFrame getCurrentStackFrame() {
|
|
return callStack.getCurrentStackFrame();
|
|
}
|
|
|
|
public boolean removeCurrentTraceIdFromStack() {
|
|
StackFrame currentStackFrame = callStack.getCurrentStackFrame();
|
|
if (currentStackFrame != null) {
|
|
TraceID traceId = currentStackFrame.getTraceID();
|
|
callStack.currentStackFrameClear();
|
|
// spanMap.remove(traceId);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get current TraceID. If it was not set this will return null.
|
|
*
|
|
* @return
|
|
*/
|
|
public TraceID getCurrentTraceId() {
|
|
return callStack.getCurrentStackFrame().getTraceID();
|
|
}
|
|
|
|
public void enable() {
|
|
tracingEnabled = true;
|
|
}
|
|
|
|
public void disable() {
|
|
tracingEnabled = false;
|
|
}
|
|
|
|
public TraceID getNextTraceId() {
|
|
TraceID current = getCurrentTraceId();
|
|
return current.getNextTraceId();
|
|
}
|
|
|
|
|
|
private void logSpan(String key, Span span) {
|
|
if (key == null) {
|
|
return;
|
|
}
|
|
if (key.equals(Annotation.ClientRecv.getCode()) || key.equals(Annotation.ServerSend.getCode())) {
|
|
logSpan(span);
|
|
}
|
|
}
|
|
|
|
void logSpan(Span span) {
|
|
try {
|
|
if (logger.isLoggable(Level.INFO)) {
|
|
logger.info("[WRITE SPAN]" + span + " CurrentThreadID=" + Thread.currentThread().getId() + ",\n\t CurrentThreadName=" + Thread.currentThread().getName() + "\n\n");
|
|
}
|
|
|
|
// TODO: remove this, just for debugging
|
|
// if (spanMap.size() > 0) {
|
|
// System.out.println("##################################################################");
|
|
// System.out.println("# [DEBUG MSG] WARNING SpanMap size > 0 check spanMap. #");
|
|
// System.out.println("##################################################################");
|
|
// System.out.println("current spamMap=" + spanMap);
|
|
// }
|
|
|
|
dataSender.send(span.toThrift());
|
|
// span.cancelTimer();
|
|
} catch (Exception e) {
|
|
logger.log(Level.SEVERE, e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
public void record(Annotation annotation) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
annotate(annotation.getCode(), null);
|
|
}
|
|
|
|
public void record(Annotation annotation, long duration) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
annotate(annotation.getCode(), duration);
|
|
}
|
|
|
|
public void recordAttribute(final String key, final String value) {
|
|
recordAttribute(key, (Object) value);
|
|
}
|
|
|
|
public void recordAttribute(final String key, final Object value) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
try {
|
|
Span span = getCurrentStackFrame().getSpan();
|
|
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) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
annotate(message, null);
|
|
}
|
|
|
|
public void recordRpcName(final String service, final String rpc) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
try {
|
|
Span span = getCurrentStackFrame().getSpan();
|
|
span.setServiceName(service);
|
|
span.setName(rpc);
|
|
} 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) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
try {
|
|
Span span = getCurrentStackFrame().getSpan();
|
|
span.setEndPoint(endPoint);
|
|
span.setTerminal(isTerminal);
|
|
} catch (Exception e) {
|
|
logger.log(Level.SEVERE, e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
private void annotate(final String key, final Long duration) {
|
|
if (!tracingEnabled)
|
|
return;
|
|
|
|
try {
|
|
Span span = getCurrentStackFrame().getSpan();
|
|
span.addAnnotation(new HippoAnnotation(System.currentTimeMillis(), key, duration));
|
|
logSpan(key, span);
|
|
} catch (Exception e) {
|
|
logger.log(Level.SEVERE, e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
|
|
} |