mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-18 01:06:03 +10:00
Merge pull request #12 from lioolli/master
Translated comments to English
This commit is contained in:
+3
-4
@@ -21,14 +21,13 @@ import java.util.Map;
|
||||
import com.navercorp.pinpoint.rpc.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* You must modify {@link com.navercorp.pinpoint.collector.receiver.tcp.AgentHandshakePropertyType} when you modify this enum type.
|
||||
* But There is no compatibility issue if you only add some properties.
|
||||
*
|
||||
* @author koo.taejin
|
||||
*/
|
||||
public enum AgentHandshakePropertyType {
|
||||
|
||||
// 해당 객체는 profiler, collector 양쪽에 함꼐 있음
|
||||
// 변경시 함께 변경 필요
|
||||
// map으로 처리하기 때문에 이전 파라미터 제거 대신 추가할 경우 확장성에는 문제가 없음
|
||||
|
||||
SUPPORT_SERVER("supportServer", Boolean.class),
|
||||
|
||||
HOSTNAME("hostName", String.class),
|
||||
|
||||
@@ -64,8 +64,8 @@ public class AgentInfoSenderListener implements FutureListener<ResponseMessage>
|
||||
private TBase<?, ?> deserialize(Future<ResponseMessage> future) {
|
||||
final ResponseMessage responseMessage = future.getResult();
|
||||
|
||||
// TODO theradlocalcache로 변경해야 되는지 검토 자주 생성이 될수 있는 객체라서 life cycle이 상이함.
|
||||
// caching해야 될려나?
|
||||
// TODO Should we change this to thread local cache? This object's life cycle is different because it could be created many times.
|
||||
// Should we cache this?
|
||||
byte[] message = responseMessage.getMessage();
|
||||
return SerializationUtils.deserialize(message, HeaderTBaseDeserializerFactory.DEFAULT_FACTORY, null);
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ public class AgentInformationFactory {
|
||||
if (serverType == null) {
|
||||
throw new NullPointerException("serverType must not be null");
|
||||
}
|
||||
// TODO 일단 임시로 호환성을 위해 agentid에 machinename을 넣도록 하자
|
||||
// TODO 박스 하나에 서버 인스턴스를 여러개 실행할 때에 문제가 될 수 있음.
|
||||
// For compatibility issue, use machineName as agentId when agengId is not provided.
|
||||
// This could be a problem if more than one server instances run on a box.
|
||||
final String machineName = NetworkUtils.getHostName();
|
||||
final String hostIp = NetworkUtils.getHostIp();
|
||||
final String agentId = getId("pinpoint.agentId", machineName, PinpointConstants.AGENT_NAME_MAX_LEN);
|
||||
@@ -62,8 +62,9 @@ public class AgentInformationFactory {
|
||||
if (id == null) {
|
||||
throw new NullPointerException("id must not be null");
|
||||
}
|
||||
// 에러 체크 로직을 bootclass 앞단으로 이동시켜야 함.
|
||||
// 아니면 여기서 체크해서 실패시 agent동작을 하지 않도록 하던가 하는 추가 동작을 해야함.
|
||||
|
||||
// TODO AgengId should be validated before bootclass.
|
||||
// or agent should stop when validataion is failed here.
|
||||
final byte[] bytes = BytesUtils.toBytes(id);
|
||||
if (bytes.length > maxlen) {
|
||||
logger.warn("{} is too long(1~24). value={}", idName, id);
|
||||
|
||||
+5
-6
@@ -98,10 +98,10 @@ public class ClassFileTransformerDispatcher implements ClassFileTransformer {
|
||||
if (className.equals("net/spy/memcached/CacheManager")) {
|
||||
logger.debug("no modifier for CacheManager");
|
||||
}
|
||||
// TODO : 디버그 용도로 추가함
|
||||
// TODO : modifier가 중복 적용되면 어떻게 되지???
|
||||
// TODO For debug
|
||||
// TODO What if a modifier is duplicated?
|
||||
if (this.profilerConfig.getProfilableClassFilter().filter(className)) {
|
||||
// 테스트 장비에서 callstack view가 잘 보이는지 확인하려고 추가함.
|
||||
// Added to see if call stack view is OK on a test machine.
|
||||
findModifier = this.modifierRegistry.findModifier("*");
|
||||
} else {
|
||||
return null;
|
||||
@@ -120,8 +120,7 @@ public class ClassFileTransformerDispatcher implements ClassFileTransformer {
|
||||
try {
|
||||
return findModifier.modify(classLoader, javassistClassName, protectionDomain, classFileBuffer);
|
||||
} finally {
|
||||
// null일 경우도 다시 원복하는게 맞음.
|
||||
// getContextClass 호출시 에러가 발생하였을 경우 여기서 호출당하지 않으므로 이부분에서 원복하는게 맞음.
|
||||
// The context class loader have to be recovered even if it was null.
|
||||
thread.setContextClassLoader(before);
|
||||
}
|
||||
}
|
||||
@@ -189,7 +188,7 @@ public class ClassFileTransformerDispatcher implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
/*
|
||||
* for plugins. This method is not used now because plugin feature is not completed yet.
|
||||
* for plugins. This method is not used yet because plugin feature is not completed.
|
||||
*/
|
||||
private void loadPlugins(DefaultModifierRegistry modifierRepository) {
|
||||
String pluginPath = agent.getAgentPath() + File.separatorChar + "plugin";
|
||||
|
||||
@@ -93,11 +93,10 @@ public class DefaultAgent implements Agent {
|
||||
private final AgentInformation agentInformation;
|
||||
private final ServerMetaDataHolder serverMetaDataHolder;
|
||||
|
||||
// agent의 상태,
|
||||
private volatile AgentStatus agentStatus;
|
||||
|
||||
static {
|
||||
// rpc쪽 preload
|
||||
// Preload classes related to pinpoint-rpc module.
|
||||
ClassPreLoader.preload();
|
||||
}
|
||||
|
||||
@@ -158,7 +157,6 @@ public class DefaultAgent implements Agent {
|
||||
|
||||
this.agentInfoSender = new AgentInfoSender(tcpDataSender, profilerConfig.getAgentInfoSendRetryInterval(), this.agentInformation, this.serverMetaDataHolder);
|
||||
|
||||
// JVM 통계 등을 주기적으로 수집하여 collector에 전송하는 monitor를 초기화한다.
|
||||
this.agentStatMonitor = new AgentStatMonitor(this.statDataSender, this.agentInformation.getAgentId(), this.agentInformation.getStartTime());
|
||||
|
||||
|
||||
@@ -171,8 +169,9 @@ public class DefaultAgent implements Agent {
|
||||
preLoadClass();
|
||||
|
||||
/**
|
||||
* FIXME tomcat의 경우에는 com.navercorp.pinpoint.profiler.modifier.tomcat.interceptor.CatalinaAwaitInterceptor가 org/apache/catalina/startup/Catalina/await함수가 실행되기
|
||||
* 전에 실행해주나. stand alone application은 그렇지 않으므로..
|
||||
* FIXME
|
||||
* In case of Tomcat, com.navercorp.pinpoint.profiler.modifier.tomcat.interceptor.CatalinaAwaitInterceptor invokes start() method
|
||||
* before entering await() method of org.apache.catalina.startup.Catalina. But for other applications, it must be invoked directly.
|
||||
*/
|
||||
if (typeResolver.isManuallyStartupRequired()) {
|
||||
start();
|
||||
@@ -223,9 +222,9 @@ public class DefaultAgent implements Agent {
|
||||
final String binderClassName = binder.getClass().getName();
|
||||
PLogger pLogger = binder.getLogger(binder.getClass().getName());
|
||||
pLogger.info("PLoggerFactory.initialize() bind:{} cl:{}", binderClassName, binder.getClass().getClassLoader());
|
||||
// static LoggerFactory에 binder를 붙임.
|
||||
// Set binder to static LoggerFactory
|
||||
// Should we unset binder at shutdonw hook or stop()?
|
||||
PLoggerFactory.initialize(binder);
|
||||
// shutdown hook이나 stop에 LoggerBinder의 연결을 풀어야 되는가?
|
||||
}
|
||||
|
||||
private TraceContext createTraceContext(short serverType) {
|
||||
@@ -290,10 +289,6 @@ public class DefaultAgent implements Agent {
|
||||
}
|
||||
|
||||
protected PinpointSocket createPinpointSocket(String host, int port, PinpointSocketFactory factory) {
|
||||
// 1.2 버전이 Tcp Data Command 허용하는 버전이 아니기 떄문에 true이던 false이던 무조건 SimpleLoggingMessageListener를 이용하게 함
|
||||
// SimpleLoggingMessageListener.LISTENER 는 서로 통신을 하지 않게 설정되어 있음 (테스트코드는 pinpoint-rpc에 존재)
|
||||
// 1.3 버전으로 할 경우 아래 분기에서 MessageListener 변경 필요
|
||||
|
||||
PinpointSocket socket = null;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
@@ -376,7 +371,7 @@ public class DefaultAgent implements Agent {
|
||||
this.agentInfoSender.stop();
|
||||
this.agentStatMonitor.stop();
|
||||
|
||||
// 종료 처리 필요.
|
||||
// Need to process stop
|
||||
this.spanDataSender.stop();
|
||||
this.statDataSender.stop();
|
||||
this.tcpDataSender.stop();
|
||||
|
||||
@@ -34,7 +34,7 @@ public class DefaultClassFileFilter implements ClassFileFilter {
|
||||
|
||||
@Override
|
||||
public boolean doFilter(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classFileBuffer) {
|
||||
// fast java class skip
|
||||
// fast skip java classes
|
||||
if (className.startsWith("java")) {
|
||||
if (className.startsWith("/", 4) || className.startsWith("x/", 4)) {
|
||||
return SKIP;
|
||||
@@ -42,11 +42,11 @@ public class DefaultClassFileFilter implements ClassFileFilter {
|
||||
}
|
||||
|
||||
if (classLoader == agentLoader) {
|
||||
// agent의 clssLoader에 로드된 클래스는 스킵한다.
|
||||
// skip classes loaded by agent class loader.
|
||||
return SKIP;
|
||||
}
|
||||
// 자기 자신의 패키지도 제외
|
||||
// 향후 패키지명 변경에 의해 코드 변경이 필요함.
|
||||
|
||||
// Skip pinpoint packages too.
|
||||
if (className.startsWith("com/navercorp/pinpoint/")) {
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
@@ -30,14 +30,13 @@ import java.util.Arrays;
|
||||
public class CallStack {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CallStack.class);
|
||||
// 추적 depth크기 제한을 위해서 필요. 해당 사이즈를 넘어갈경우 부드럽게 트레이스를 무시하는 로직이 필요함.
|
||||
private static final int TRACE_STACK_MAX_SIZE = 64;
|
||||
|
||||
private static final int STACK_SIZE = 8;
|
||||
private static final int STACK_INCREASE_SIZE = 8;
|
||||
|
||||
private final Span span;
|
||||
// CallStack을 동시성 환경에서 복사해서 볼수 있는 방법이 필요함.
|
||||
|
||||
// We have to find some way to copy call stack in concurrent situation.
|
||||
private StackFrame[] stack = new StackFrame[STACK_SIZE];
|
||||
|
||||
|
||||
@@ -54,14 +53,15 @@ public class CallStack {
|
||||
return span;
|
||||
}
|
||||
|
||||
// without synchronization for the present.
|
||||
// public synchronized int getIndex() {
|
||||
public int getIndex() {
|
||||
// 일단 락 안잡는 코드로 함.
|
||||
return index;
|
||||
}
|
||||
|
||||
// copy시의 락 생각할 경우 좀더 정교하게 잡을수 있을듯.
|
||||
// push, pop, copy만 락을 잡아도 될거 같은 생각이 듬.
|
||||
|
||||
// We could handle synchronization more precisely.
|
||||
// Maybe synchonizing push, pop, copy would be enough.
|
||||
public synchronized StackFrame getCurrentStackFrame() {
|
||||
return stack[index];
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public class CallStack {
|
||||
private PinpointException createStackException(String stackApiPoint, final int index) {
|
||||
final PinpointException ex = new PinpointException("Profiler CallStack check. index:" + index + " stackApiPoint:" + stackApiPoint);
|
||||
if (logger.isWarnEnabled()) {
|
||||
// 자체 stack dump 필요.
|
||||
// need to dump stack.
|
||||
logger.warn("invalid callStack found stack dump:{}", this, ex);
|
||||
}
|
||||
return ex;
|
||||
|
||||
+1
-15
@@ -40,11 +40,6 @@ public class DefaultAsyncTrace implements AsyncTrace {
|
||||
|
||||
|
||||
public static final int NON_REGIST = -1;
|
||||
// private int id;
|
||||
// 비동기일 경우 traceenable의 경우 애매함. span을 보내는것으로 데이터를 생성하므로 약간 이상.
|
||||
// private boolean tracingEnabled;
|
||||
|
||||
|
||||
|
||||
private final AtomicInteger state = new AtomicInteger(STATE_INIT);
|
||||
|
||||
@@ -136,12 +131,6 @@ public class DefaultAsyncTrace implements AsyncTrace {
|
||||
String drop = StringUtils.drop(th.getMessage());
|
||||
|
||||
recordAttribute(AnnotationKey.EXCEPTION, drop);
|
||||
|
||||
// TODO 비동기 api일 경우, span에 exception을 마크하기가 까다로움
|
||||
// AnnotationKey span = getCallStack().getSpan();
|
||||
// if (span.getErrCode() == 0) {
|
||||
// span.setErrCode(1);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +167,6 @@ public class DefaultAsyncTrace implements AsyncTrace {
|
||||
this.spanEvent.setDestinationId(destinationId);
|
||||
}
|
||||
|
||||
// TODO: endPoint로 받으면 합치는데 비용이 들어가 그냥 한번에 받는게 나을것 같음.
|
||||
@Override
|
||||
public void recordEndPoint(final String endPoint) {
|
||||
this.spanEvent.setEndPoint(endPoint);
|
||||
@@ -202,15 +190,13 @@ public class DefaultAsyncTrace implements AsyncTrace {
|
||||
|
||||
public void timeout() {
|
||||
if (state.compareAndSet(STATE_INIT, STATE_TIMEOUT)) {
|
||||
// TODO timeout spanEvent log 던지기.
|
||||
// 뭘 어떤 내용을 던져야 되는지 아직 모르겠음????
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
public boolean fire() {
|
||||
if (state.compareAndSet(STATE_INIT, STATE_FIRE)) {
|
||||
if (timeoutTask != null) {
|
||||
// timeout이 걸려 있는 asynctrace일 경우 호출해 준다.
|
||||
this.timeoutTask.cancel();
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -124,8 +124,8 @@ public final class DefaultTrace implements Trace {
|
||||
|
||||
private StackFrame createSpanEventStackFrame(int stackId) {
|
||||
SpanEvent spanEvent = new SpanEvent(callStack.getSpan());
|
||||
// Span내부의 SpanEvent로 들어가지 않을 경우 사용하기 위해 set한다.
|
||||
|
||||
// Set properties for the case when stackFrame is not used as part of Span.
|
||||
SpanEventStackFrame stackFrame = new SpanEventStackFrame(spanEvent);
|
||||
stackFrame.setStackFrameId(stackId);
|
||||
stackFrame.setSequence(nextSequence());
|
||||
@@ -185,7 +185,8 @@ public final class DefaultTrace implements Trace {
|
||||
// metricResponseTime();
|
||||
pop(ROOT_STACKID);
|
||||
callStack.popRoot();
|
||||
// 잘못된 stack 조작시 다음부터 그냥 nullPointerException이 발생할건데 괜찮은가?
|
||||
|
||||
// If the stack is not handled properly, NullPointerException will be thrown after this. Is it OK?
|
||||
this.currentStackFrame = null;
|
||||
}
|
||||
|
||||
@@ -227,7 +228,7 @@ public final class DefaultTrace implements Trace {
|
||||
public void traceBlockEnd(int stackId) {
|
||||
pop(stackId);
|
||||
StackFrame popStackFrame = callStack.pop();
|
||||
// pop 할때 frame위치를 원복해야 한다.
|
||||
// When pop, current frame have to be recovered.
|
||||
this.currentStackFrame = popStackFrame;
|
||||
}
|
||||
|
||||
@@ -235,7 +236,7 @@ public final class DefaultTrace implements Trace {
|
||||
final StackFrame currentStackFrame = this.currentStackFrame;
|
||||
int stackFrameId = currentStackFrame.getStackFrameId();
|
||||
if (stackFrameId != stackId) {
|
||||
// 자체 stack dump를 하면 오류발견이 쉬울것으로 생각됨
|
||||
// stack dump will make debugging easy.
|
||||
if (logger.isWarnEnabled()) {
|
||||
PinpointException exception = new PinpointException("Corrupted CallStack found");
|
||||
logger.warn("Corrupted CallStack found. StackId not matched. expected:{} current:{}", stackId, stackFrameId, exception);
|
||||
@@ -296,7 +297,7 @@ public final class DefaultTrace implements Trace {
|
||||
return;
|
||||
}
|
||||
final String drop = StringUtils.drop(th.getMessage(), 256);
|
||||
// exception class가 proxy라서 class Name이 불규칙하면 문제가 발생할수 있다.
|
||||
// An exception that is an instance of a proxy class could make something wrong becuase the class name will vary.
|
||||
final int exceptionId = traceContext.cacheString(th.getClass().getName());
|
||||
this.currentStackFrame.setExceptionInfo(exceptionId, drop);
|
||||
|
||||
@@ -320,7 +321,7 @@ public final class DefaultTrace implements Trace {
|
||||
|
||||
@Override
|
||||
public void recordApi(MethodDescriptor methodDescriptor, Object[] args) {
|
||||
// API 저장 방법의 개선 필요.
|
||||
// Need to improve the way of storing APIs.
|
||||
recordApi(methodDescriptor);
|
||||
recordArgs(args);
|
||||
}
|
||||
@@ -350,7 +351,7 @@ public final class DefaultTrace implements Trace {
|
||||
for (int i = start; i < max; i++) {
|
||||
recordAttribute(AnnotationKey.getArgs(i), args[i]);
|
||||
}
|
||||
// TODO MAX 사이즈를 넘는건 마크만 해줘야 하나?
|
||||
// TODO How to handle if args length is greater than MAX_ARGS_SIZE?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,7 +374,7 @@ public final class DefaultTrace implements Trace {
|
||||
for (int i = 0; i < max; i++) {
|
||||
recordAttribute(AnnotationKey.getArgs(i), args[i]);
|
||||
}
|
||||
// TODO MAX 사이즈를 넘는건 마크만 해줘야 하나?
|
||||
// TODO How to handle if args length is greater than MAX_ARGS_SIZE?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,14 +469,14 @@ public final class DefaultTrace implements Trace {
|
||||
|
||||
@Override
|
||||
public void recordEndPoint(final String endPoint) {
|
||||
// TODO API 단일화 필요.
|
||||
// TODO Need to unify API
|
||||
StackFrame currentStackFrame = this.currentStackFrame;
|
||||
currentStackFrame.setEndPoint(endPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordRemoteAddress(final String remoteAddress) {
|
||||
// TODO API 단일화 필요.
|
||||
// TODO Need to unify API
|
||||
StackFrame currentStackFrame = this.currentStackFrame;
|
||||
if (currentStackFrame instanceof RootStackFrame) {
|
||||
((RootStackFrame) currentStackFrame).setRemoteAddress(remoteAddress);
|
||||
|
||||
+9
-10
@@ -107,7 +107,7 @@ public class DefaultTraceContext implements TraceContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* sampling 여부까지 체크하여 유효성을 검증한 후 Trace를 리턴한다.
|
||||
* Return trace only if current transaction can be sampled.
|
||||
* @return
|
||||
*/
|
||||
public Trace currentTraceObject() {
|
||||
@@ -119,7 +119,7 @@ public class DefaultTraceContext implements TraceContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* 유효성을 검증하지 않고 Trace를 리턴한다.
|
||||
* Return trace without sampling check.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -145,7 +145,7 @@ public class DefaultTraceContext implements TraceContext {
|
||||
return profilerConfig;
|
||||
}
|
||||
|
||||
// remote 에서 샘플링 대상으로 선정된 경우.
|
||||
// Will be invoked when current transaction is picked as sampling target at remote.
|
||||
public Trace continueTraceObject(final TraceId traceID) {
|
||||
return traceFactory.continueTraceObject(traceID);
|
||||
}
|
||||
@@ -239,7 +239,7 @@ public class DefaultTraceContext implements TraceContext {
|
||||
if (transactionId == null) {
|
||||
throw new NullPointerException("transactionId must not be null");
|
||||
}
|
||||
// TODO parse error 때 예외 처리 필요.
|
||||
// TODO Should handle exception when parsing failed.
|
||||
return DefaultTraceId.parse(transactionId, parentSpanID, spanID, flags);
|
||||
}
|
||||
|
||||
@@ -254,13 +254,12 @@ public class DefaultTraceContext implements TraceContext {
|
||||
final Result cachingResult = this.sqlCache.put(normalizedSql);
|
||||
if (cachingResult.isNewValue()) {
|
||||
if (isDebug) {
|
||||
// TODO hit% 로그를 남겨야 문제 발생시 도움이 될듯 하다.
|
||||
// TODO logging hit ratio could help debugging
|
||||
logger.debug("NewSQLParsingResult:{}", parsingResult);
|
||||
}
|
||||
// newValue란 의미는 cache에 인입됬다는 의미이고 이는 신규 sql문일 가능성이 있다는 의미임.
|
||||
// 그러므로 메타데이터를 서버로 전송해야 한다.
|
||||
|
||||
|
||||
|
||||
// isNewValue means that the value is newly cached.
|
||||
// So the sql could be new one. We have to send sql metadata to collector.
|
||||
final TSqlMetaData sqlMetaData = new TSqlMetaData();
|
||||
sqlMetaData.setAgentId(getAgentId());
|
||||
sqlMetaData.setAgentStartTime(getAgentStartTime());
|
||||
@@ -268,7 +267,7 @@ public class DefaultTraceContext implements TraceContext {
|
||||
sqlMetaData.setSqlId(cachingResult.getId());
|
||||
sqlMetaData.setSql(normalizedSql);
|
||||
|
||||
// 좀더 신뢰성이 있는 tcp connection이 필요함.
|
||||
// Need more reliable tcp connection
|
||||
this.priorityDataSender.request(sqlMetaData);
|
||||
}
|
||||
parsingResult.setId(cachingResult.getId());
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.navercorp.pinpoint.common.util.ParsingResult;
|
||||
public class DisableTrace implements Trace {
|
||||
|
||||
public static final DisableTrace INSTANCE = new DisableTrace();
|
||||
// 구지 객체를 생성하여 사용할 필요가 없을듯.
|
||||
|
||||
private DisableTrace() {
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class DisableTrace implements Trace {
|
||||
|
||||
@Override
|
||||
public boolean canSampled() {
|
||||
// sampling false를 항상 false를 리턴한다.
|
||||
// always return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 뭔가 복잡한 비동기 call trace시 객체 등록용으로 쓰자.
|
||||
* 근데 손좀봐야 될듯.뭔가 좀 구림.
|
||||
* @author emeroad
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -38,12 +36,9 @@ public class GlobalCallTrace {
|
||||
|
||||
private ConcurrentMap<Integer, AsyncTrace> trace = new ConcurrentHashMap<Integer, AsyncTrace>(32);
|
||||
private AtomicInteger idGenerator = new AtomicInteger(0);
|
||||
// stop을 해줘야 할듯.
|
||||
private Timer timer = new Timer("Pinpoint-GlobalCallTrace-Timer-" + timerId.getAndIncrement(), true);
|
||||
|
||||
public int registerTraceObject(AsyncTrace asyncTrace) {
|
||||
// TODO 연관관계가 전달부분이 영 별로임.
|
||||
|
||||
TimeoutTask timeoutTask = new TimeoutTask(trace, asyncTrace.getAsyncId());
|
||||
asyncTrace.setTimeoutTask(timeoutTask);
|
||||
|
||||
@@ -68,7 +63,6 @@ public class GlobalCallTrace {
|
||||
if (asyncTrace != null) {
|
||||
boolean result = ((DefaultAsyncTrace)asyncTrace).fire();
|
||||
if (!result) {
|
||||
// 이미 timeout된 asyncTrace임.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ public class MetricTrace implements Trace {
|
||||
|
||||
private StackFrame createSpanEventStackFrame(int stackId) {
|
||||
SpanEvent spanEvent = new SpanEvent(callStack.getSpan());
|
||||
// Span내부의 SpanEvent로 들어가지 않을 경우 사용하기 위해 set한다.
|
||||
|
||||
|
||||
// Set properties for the case when stackFrame is not used as part of Span.
|
||||
SpanEventStackFrame stackFrame = new SpanEventStackFrame(spanEvent);
|
||||
stackFrame.setStackFrameId(stackId);
|
||||
|
||||
@@ -167,7 +167,8 @@ public class MetricTrace implements Trace {
|
||||
metricResponseTime();
|
||||
checkStackId(ROOT_STACKID);
|
||||
callStack.popRoot();
|
||||
// 잘못된 stack 조작시 다음부터 그냥 nullPointerException이 발생할건데 괜찮은가?
|
||||
|
||||
// If the stack is not handled properly, NullPointerException will be thrown after this. Is it OK?
|
||||
this.currentStackFrame = null;
|
||||
}
|
||||
|
||||
@@ -193,7 +194,7 @@ public class MetricTrace implements Trace {
|
||||
public void traceBlockEnd(int stackId) {
|
||||
checkStackId(stackId);
|
||||
StackFrame popStackFrame = callStack.pop();
|
||||
// pop 할때 frame위치를 원복해야 한다.
|
||||
// When pop, current frame have to be recovered.
|
||||
this.currentStackFrame = popStackFrame;
|
||||
}
|
||||
|
||||
@@ -201,7 +202,7 @@ public class MetricTrace implements Trace {
|
||||
final StackFrame currentStackFrame = this.currentStackFrame;
|
||||
int stackFrameId = currentStackFrame.getStackFrameId();
|
||||
if (stackFrameId != stackId) {
|
||||
// 자체 stack dump를 하면 오류발견이 쉬울것으로 생각됨
|
||||
// stack dump will make debugging easy.
|
||||
if (logger.isWarnEnabled()) {
|
||||
PinpointException exception = new PinpointException("Corrupted CallStack found");
|
||||
logger.warn("Corrupted CallStack found. StackId not matched. expected:{} current:{}", stackId, stackFrameId, exception);
|
||||
@@ -239,7 +240,7 @@ public class MetricTrace implements Trace {
|
||||
if (th == null) {
|
||||
return;
|
||||
}
|
||||
// TODO 추가적인 객체를 생성하지 않도록 MARK Exception이 있으면 좋을것 같음.
|
||||
// TODO We'd better having MARK Exception to prevent more objects being created.
|
||||
this.currentStackFrame.setExceptionInfo(EXCEPTION_MARK, "");
|
||||
|
||||
final Span span = getCallStack().getSpan();
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class SpanChunkFactory {
|
||||
if (flushData == null) {
|
||||
throw new NullPointerException("flushData must not be null");
|
||||
}
|
||||
// TODO 반드시 1개 이상이라는 조건을 충족해야 된다.
|
||||
// TODO must be equals to or greater than 1
|
||||
final int size = flushData.size();
|
||||
if (size < 1) {
|
||||
throw new IllegalArgumentException("flushData.size() < 1 size:" + size);
|
||||
|
||||
@@ -56,8 +56,9 @@ public class SpanEvent extends TSpanEvent {
|
||||
public void markStartTime() {
|
||||
// spanEvent.setStartElapsed((int) (startTime - parentSpanStartTime));
|
||||
final int startElapsed = (int)(System.currentTimeMillis() - span.getStartTime());
|
||||
// startElapsed이 0이면 마크를 안하는 로직은 거의 쓸모가 없다. 하지 말것.
|
||||
// Span에서 최초 SpanEvent나 0이 나올 가능성이 있고, 이후 SpanEvent의 경우는 거의 그렇지 않음.
|
||||
|
||||
// If startElapsed is 0, logic without mark is useless. Don't do that.
|
||||
// The first SpaneEvent of a Sapn could result in 0. Not likely afterwards.
|
||||
this.setStartElapsed(startElapsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ public class SpanId {
|
||||
// private static final Random seed = new Random();
|
||||
|
||||
public static long newSpanId() {
|
||||
// thread 마다 가능한 겹치지 않는 값이 생성되면 문제 없으므로 ThreadLocalRandom으로 변경함.
|
||||
final Random random = getRandom();
|
||||
|
||||
return createSpanId(random);
|
||||
}
|
||||
|
||||
// 이거 구현 바꾸면 다른 random 사용이 가능함.
|
||||
// Changed to ThreadLocalRandom because unique value per thread will be enough.
|
||||
// If you need to change Random implementation, modify this method.
|
||||
private static Random getRandom() {
|
||||
return ThreadLocalRandom.current();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public interface TraceFactory {
|
||||
|
||||
Trace disableSampling();
|
||||
|
||||
// remote 에서 샘플링 대상으로 선정된 경우.
|
||||
// picked as sampling target at remote
|
||||
Trace continueTraceObject(TraceId traceID);
|
||||
|
||||
Trace newTraceObject();
|
||||
|
||||
+2
-2
@@ -85,8 +85,8 @@ public class BufferedStorage implements Storage {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("storage is null. discard spanEvent:{}", spanEvent);
|
||||
}
|
||||
// 이미 span이 와서 flush된 상황임.
|
||||
// 비동기를 이쪽에 포함시키면 이렇게 될수 있으나. 현재 구조를 변경할 계획임.
|
||||
|
||||
// Already flushed. This could happen with async processing.
|
||||
return;
|
||||
}
|
||||
storage.add(spanEvent);
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class LogStorageFactory implements StorageFactory {
|
||||
|
||||
@Override
|
||||
public Storage createStorage() {
|
||||
// 상태 없음 그냥 재활용하면 됨.
|
||||
// reuse because it has no states.
|
||||
return DEFAULT_STORAGE;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ public class AspectWeaverClass {
|
||||
|
||||
private CtMethod copyMethod(CtClass sourceClass, CtMethod sourceMethod) throws CannotCompileException {
|
||||
|
||||
// id라도 더 줘야 될려나?
|
||||
// need id?
|
||||
|
||||
String copyMethodName = methodNameReplacer.replaceMethodName(sourceMethod.getName());
|
||||
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class ClassLoadChecker {
|
||||
if (className == null) {
|
||||
throw new NullPointerException("className must not be null");
|
||||
}
|
||||
// classLoader는 null일수도 있을거 같음. 몇몇 java reference의 최상위 로더의 경우 null 이 나옴.
|
||||
// classLoader could be null (some jdk classes)
|
||||
this.classLoader = classLoader;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
+19
-16
@@ -50,7 +50,8 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
private final boolean isDebug = logger.isDebugEnabled();
|
||||
|
||||
private final NamedClassPool rootClassPool;
|
||||
// classPool의 수평적 확장이 필요할수 있음. was에 여러개의 webapp가 있을 경우 충돌방지.
|
||||
|
||||
// TODO Need to separate childClassPool per class space to prevent collision(ex: multiple web applications on a Tomcat server)
|
||||
private final NamedClassPool childClassPool;
|
||||
|
||||
private Agent agent;
|
||||
@@ -68,7 +69,7 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
this.rootClassPool = createClassPool(pathNames, "rootClassPool");
|
||||
this.childClassPool = createChildClassPool(rootClassPool, "childClassPool");
|
||||
this.agent = agent;
|
||||
// agent의 class는 rootClassPool에 넣는다.
|
||||
// Add Pinpoint classes to rootClassPool
|
||||
checkLibrary(this.getClass().getClassLoader(), this.rootClassPool, this.getClass().getName());
|
||||
}
|
||||
|
||||
@@ -116,11 +117,12 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
}
|
||||
|
||||
public void checkLibrary(ClassLoader classLoader, NamedClassPool classPool, String javassistClassName) {
|
||||
// 최상위 classLoader일 경우 null이라 찾을필요가 없음.
|
||||
// if it's loaded by boot class loader, classLoader is null.
|
||||
if (classLoader == null) {
|
||||
return;
|
||||
}
|
||||
// TODO Util로 뽑을까?
|
||||
|
||||
// TODO extract to Util?
|
||||
final boolean findClass = findClass(javassistClassName, classPool);
|
||||
if (findClass) {
|
||||
if (isDebug) {
|
||||
@@ -160,16 +162,15 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
}
|
||||
try {
|
||||
final NamedClassPool classPool = findClassPool(classLoader);
|
||||
// classLoader로 락을 잡는게 안전함.
|
||||
// 어차피 classLoader에서 락을 잡고 들어오는점도 있고. 예외 사항이 발생할수 있기 때문에.
|
||||
// classLoader의 재진입 락을 잡고 들어오는게 무난함.
|
||||
|
||||
// It's safe to synchronize on classLoader because current thread already hold lock on classLoader.
|
||||
// Without lock, maybe something could go wrong.
|
||||
synchronized (classLoader) {
|
||||
if (this.classLoadChecker.exist(classLoader, defineClass)) {
|
||||
return classLoader.loadClass(defineClass);
|
||||
} else {
|
||||
final CtClass clazz = classPool.get(defineClass);
|
||||
|
||||
// 로그 레벨을 debug로 하니 개발때 제대로 체크 안하는 사람이 있어서 수정함.
|
||||
checkTargetClassInterface(clazz);
|
||||
|
||||
defineAbstractSuperClass(clazz, classLoader, protectedDomain);
|
||||
@@ -200,20 +201,22 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
private void defineAbstractSuperClass(CtClass clazz, ClassLoader classLoader, ProtectionDomain protectedDomain) throws NotFoundException, CannotCompileException {
|
||||
final CtClass superClass = clazz.getSuperclass();
|
||||
if (superClass == null) {
|
||||
// java.lang.Object가 아닌 경우 null은 안나올듯.
|
||||
// maybe java.lang.Object
|
||||
return;
|
||||
}
|
||||
final int modifiers = superClass.getModifiers();
|
||||
if (Modifier.isAbstract(modifiers)) {
|
||||
if (this.classLoadChecker.exist(classLoader, superClass.getName())) {
|
||||
// nestedClass는 자기 자신에게만 속해 있으므로 로드 여부 체크가 필요 없으나 abstractClass는 같이 사용할수 있으므로 체크해야 된다.
|
||||
// We have to check if abstract super classes is already loaded because it could be used by other classes unlike nested classes.
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInfo) {
|
||||
logger.info("defineAbstractSuperClass class:{} cl:{}", superClass.getName(), classLoader);
|
||||
}
|
||||
// 좀더 정확하게 java 스펙처럼 하려면 제귀를 돌면서 추가로 super를 확인해야 되나. 구지 그래야 되나 싶다. 패스.
|
||||
// 스펙상 1차원 abstractClass만 지원하는 것으로..
|
||||
|
||||
// If it was more strict we had to make a recursive call to check super class of super class.
|
||||
// But it seems like too much. We'll check direct super class only.
|
||||
superClass.toClass(classLoader, protectedDomain);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +227,7 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
return;
|
||||
}
|
||||
for (CtClass nested : nestedClasses) {
|
||||
// 재귀하면서 최하위부터 로드
|
||||
// load from inner-most to outer.
|
||||
defineNestedClass(nested, classLoader, protectedDomain);
|
||||
if (isInfo) {
|
||||
logger.info("defineNestedClass class:{} cl:{}", nested.getName(), classLoader);
|
||||
@@ -274,14 +277,14 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
|
||||
private void loadClassLoaderLibraries(ClassLoader classLoader, NamedClassPool classPool) {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
|
||||
// classLoader가 가지고 있는 전체 리소스를 가능한 패스로 다 걸어야 됨
|
||||
// 임의의 class가 없을 경우 class의 byte code를 classpool에 적재 할 수 없음.
|
||||
// We have to add every class path URLs to classPool.
|
||||
// To load bytecode of a class, ClassPool requires every classes referenced by the class.
|
||||
URL[] urlList = urlClassLoader.getURLs();
|
||||
for (URL tempURL : urlList) {
|
||||
String filePath = tempURL.getFile();
|
||||
try {
|
||||
classPool.appendClassPath(filePath);
|
||||
// 만약 한개만 로딩해도 된다면. return true 할것
|
||||
|
||||
if (isInfo) {
|
||||
logger.info("Loaded cl:{} classPool:{} {} ", classLoader.getClass().getName(), classPool.getName(), filePath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user