diff --git a/src/main/java/com/profiler/context/DeadlineSpanMap.java b/src/main/java/com/profiler/context/DeadlineSpanMap.java index b069cdef3..71acc6177 100644 --- a/src/main/java/com/profiler/context/DeadlineSpanMap.java +++ b/src/main/java/com/profiler/context/DeadlineSpanMap.java @@ -2,24 +2,27 @@ package com.profiler.context; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; public class DeadlineSpanMap { - private final Map map = new ConcurrentHashMap(); + private final ConcurrentMap map = new ConcurrentHashMap(); public Span update(TraceID traceId, SpanUpdater spanUpdater) { - Span span = map.get(traceId.getTraceId()); + TraceID.TraceKey traceIdKey = traceId.getTraceKey(); + Span span = map.get(traceIdKey); if (span == null) { span = new Span(traceId, null, null); - map.put(traceId.getTraceId(), span); + + map.put(traceIdKey, span); } return spanUpdater.updateSpan(span); } public Span remove(TraceID traceId) { - return map.remove(traceId.getTraceId()); + return map.remove(traceId.getTraceKey()); } public int size() { diff --git a/src/main/java/com/profiler/context/SpanID.java b/src/main/java/com/profiler/context/SpanID.java index 7b0b6383a..334934256 100644 --- a/src/main/java/com/profiler/context/SpanID.java +++ b/src/main/java/com/profiler/context/SpanID.java @@ -1,12 +1,19 @@ package com.profiler.context; -import java.util.UUID; +import java.util.Random; public class SpanID { - public static final String ROOT_SPAN_ID = null; - public static String newSpanID() { - UUID uuid = UUID.randomUUID(); - return uuid.toString(); - } + public static final long ROOT_SPAN_ID = 0; + public static final long NULL = -1; + + private static Random seed = new Random(); + + public static long newSpanID() { + long id = seed.nextLong(); + if (id == NULL) { + return newSpanID(); + } + return id; + } } diff --git a/src/main/java/com/profiler/context/TraceID.java b/src/main/java/com/profiler/context/TraceID.java index 78d20b5b2..a257c8cea 100644 --- a/src/main/java/com/profiler/context/TraceID.java +++ b/src/main/java/com/profiler/context/TraceID.java @@ -3,33 +3,70 @@ package com.profiler.context; import java.util.UUID; public class TraceID { - private String traceId; - private String parentSpanId; - private String spanId; + private UUID traceId; + private long parentSpanId; + private long spanId; private boolean sampled; private int flags; public static TraceID newTraceId() { - return new TraceID(UUID.randomUUID().toString(), null, SpanID.newSpanID(), false, 0); + UUID uuid = UUID.randomUUID(); + return new TraceID(uuid, SpanID.NULL, SpanID.newSpanID(), false, 0); } - public TraceID(String traceId, String parentSpanId, String spanId, boolean sampled, int flags) { - this.traceId = (traceId == null) ? parentSpanId : traceId; - this.parentSpanId = (parentSpanId == null) ? spanId : parentSpanId; + + public TraceID(UUID traceId, long parentSpanId, long spanId, boolean sampled, int flags) { + this.traceId = traceId; + this.parentSpanId = parentSpanId; this.spanId = spanId; this.sampled = sampled; this.flags = flags; } - public String getTraceId() { + public UUID getTraceId() { return traceId; } - public String getParentSpanId() { + public TraceKey getTraceKey() { + long most = traceId.getMostSignificantBits(); + long least = traceId.getLeastSignificantBits(); + return new TraceKey(most, least); + } + + public static class TraceKey { + private long most; + private long least; + public TraceKey(long most, long least) { + this.most = most; + this.least = least; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TraceKey that = (TraceKey) o; + + if (least != that.least) return false; + if (most != that.most) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (most ^ (most >>> 32)); + result = 31 * result + (int) (least ^ (least >>> 32)); + return result; + } + } + + public long getParentSpanId() { return parentSpanId; } - public String getSpanId() { + public long getSpanId() { return spanId; } @@ -41,15 +78,15 @@ public class TraceID { return flags; } - public void setTraceId(String traceId) { + public void setTraceId(UUID traceId) { this.traceId = traceId; } - public void setParentSpanId(String parentSpanId) { + public void setParentSpanId(long parentSpanId) { this.parentSpanId = parentSpanId; } - public void setSpanId(String spanId) { + public void setSpanId(long spanId) { this.spanId = spanId; } diff --git a/src/main/java/com/profiler/modifier/connector/interceptors/ExecuteMethodInterceptor.java b/src/main/java/com/profiler/modifier/connector/interceptors/ExecuteMethodInterceptor.java index dcaf9be62..19b9aa73d 100644 --- a/src/main/java/com/profiler/modifier/connector/interceptors/ExecuteMethodInterceptor.java +++ b/src/main/java/com/profiler/modifier/connector/interceptors/ExecuteMethodInterceptor.java @@ -34,9 +34,10 @@ public class ExecuteMethodInterceptor implements StaticAroundInterceptor { TraceID nextId = Trace.getNextId(); - request.addHeader(Header.HTTP_TRACE_ID.toString(), nextId.getTraceId()); - request.addHeader(Header.HTTP_SPAN_ID.toString(), nextId.getSpanId()); - request.addHeader(Header.HTTP_PARENT_SPAN_ID.toString(), nextId.getParentSpanId()); + // UUID format을 그대로. + request.addHeader(Header.HTTP_TRACE_ID.toString(), nextId.getTraceId().toString()); + request.addHeader(Header.HTTP_SPAN_ID.toString(), Long.toString(nextId.getSpanId())); + request.addHeader(Header.HTTP_PARENT_SPAN_ID.toString(), Long.toString(nextId.getParentSpanId())); request.addHeader(Header.HTTP_SAMPLED.toString(), String.valueOf(nextId.isSampled())); request.addHeader(Header.HTTP_FLAGS.toString(), String.valueOf(nextId.getFlags())); diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/InvokeMethodInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/InvokeMethodInterceptor.java index 206e820f3..fc91b2a3a 100644 --- a/src/main/java/com/profiler/modifier/tomcat/interceptors/InvokeMethodInterceptor.java +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/InvokeMethodInterceptor.java @@ -1,46 +1,35 @@ package com.profiler.modifier.tomcat.interceptors; import java.util.Enumeration; +import java.util.UUID; import javax.servlet.http.HttpServletRequest; -import com.profiler.context.Annotation; -import com.profiler.context.Header; -import com.profiler.context.Trace; -import com.profiler.context.TraceID; +import com.profiler.context.*; import com.profiler.interceptor.StaticAroundInterceptor; import com.profiler.trace.RequestTracer; import com.profiler.util.NamedThreadLocal; +import com.profiler.util.NumberUtils; public class InvokeMethodInterceptor implements StaticAroundInterceptor { - private ThreadLocal start = new NamedThreadLocal("InvokeMethodInterceptor-starttime"); + private ThreadLocal start = new NamedThreadLocal("InvokeMethodInterceptor-starttime"); - @Override - public void before(Object target, String className, String methodName, Object[] args) { - try { - HttpServletRequest request = (HttpServletRequest) args[0]; - String requestURL = request.getRequestURI(); - String clientIP = request.getRemoteAddr(); + @Override + public void before(Object target, String className, String methodName, Object[] args) { + try { + HttpServletRequest request = (HttpServletRequest) args[0]; + String requestURL = request.getRequestURI(); + String clientIP = request.getRemoteAddr(); + String parameters = getParameter(request); - String traceID = request.getHeader(Header.HTTP_TRACE_ID.toString()); - String parentSpanID = request.getHeader(Header.HTTP_PARENT_SPAN_ID.toString()); - String spanID = request.getHeader(Header.HTTP_SPAN_ID.toString()); + UUID traceID = getTraceId(request); + if (traceID != null) { + long parentSpanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_PARENT_SPAN_ID.toString()), SpanID.NULL); + long spanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_SPAN_ID.toString()), SpanID.NULL); + boolean sampled = Boolean.parseBoolean(request.getHeader(Header.HTTP_SAMPLED.toString())); + int flags = NumberUtils.parseInteger(request.getHeader(Header.HTTP_FLAGS.toString()), 0); - Boolean sampled = null; - if (request.getHeader(Header.HTTP_SAMPLED.toString()) != null) { - sampled = Boolean.valueOf(request.getHeader(Header.HTTP_SAMPLED.toString())); - } - - Integer flags = null; - if (request.getHeader(Header.HTTP_FLAGS.toString()) != null) { - flags = Integer.valueOf(request.getHeader(Header.HTTP_FLAGS.toString())); - } - - String parameters = getParameter(request); - - // record - if (traceID != null) { TraceID id = new TraceID(traceID, parentSpanID, spanID, sampled, flags); // TODO : refactor this, just for debug @@ -51,44 +40,56 @@ public class InvokeMethodInterceptor implements StaticAroundInterceptor { Trace.setTraceId(TraceID.newTraceId()); } - Trace.recordRpcName("tomcat", requestURL); - Trace.recordServerAddr(request.getLocalAddr(), request.getLocalPort()); - Trace.record("Parameter=" + parameters); - Trace.record(new Annotation.ServerRecv()); - - RequestTracer.startTransaction(requestURL, clientIP, System.currentTimeMillis(), parameters); + Trace.recordRpcName("tomcat", requestURL); + Trace.recordServerAddr(request.getLocalAddr(), request.getLocalPort()); + Trace.record("Parameter=" + parameters); + Trace.record(new Annotation.ServerRecv()); + RequestTracer.startTransaction(requestURL, clientIP, System.currentTimeMillis(), parameters); start.set(System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } + + @Override + public void after(Object target, String className, String methodName, Object[] args, Object result) { + // TODO result 가 Exception 타입일경우 호출 실패임. + Trace.record(new Annotation.ServerSend(), System.currentTimeMillis() - start.get()); + start.remove(); + RequestTracer.endTransaction(); + } + + private UUID getTraceId(HttpServletRequest request) { + String header = request.getHeader(Header.HTTP_TRACE_ID.toString()); + if (header == null) { + return null; + } + try { + return UUID.fromString(header); + } catch (IllegalArgumentException e) { + return null; + } + } - @Override - public void after(Object target, String className, String methodName, Object[] args, Object result) { - Trace.record(new Annotation.ServerSend(), System.currentTimeMillis() - start.get()); - start.remove(); - RequestTracer.endTransaction(); - } + private String getParameter(HttpServletRequest request) { + Enumeration attrs = request.getParameterNames(); + + StringBuilder params = new StringBuilder(); - private String getParameter(HttpServletRequest request) { - Enumeration attrs = request.getParameterNames(); + while (attrs.hasMoreElements()) { + String keyString = attrs.nextElement().toString(); + Object value = request.getParameter(keyString); - StringBuilder params = new StringBuilder(); + if (value != null) { + String valueString = value.toString(); + int valueStringLength = valueString.length(); - while (attrs.hasMoreElements()) { - String keyString = attrs.nextElement().toString(); - Object value = request.getParameter(keyString); + if (valueStringLength > 0 && valueStringLength < 100) + params.append(keyString).append("=").append(valueString); + } + } - if (value != null) { - String valueString = value.toString(); - int valueStringLength = valueString.length(); - - if (valueStringLength > 0 && valueStringLength < 100) - params.append(keyString).append("=").append(valueString); - } - } - - return params.toString(); - } + return params.toString(); + } } diff --git a/src/main/java/com/profiler/util/NumberUtils.java b/src/main/java/com/profiler/util/NumberUtils.java new file mode 100644 index 000000000..2ed62066e --- /dev/null +++ b/src/main/java/com/profiler/util/NumberUtils.java @@ -0,0 +1,26 @@ +package com.profiler.util; + +public class NumberUtils { + public static long parseLong(String str, long defaultLong) { + if(str== null) { + return defaultLong; + } + try { + return Long.parseLong(str); + } catch (NumberFormatException e) { + return defaultLong; + } + } + + public static int parseInteger(String str, int defaultInt) { + if(str == null) { + return defaultInt; + } + try { + return Integer.parseInt(str); + } catch (NumberFormatException e) { + return defaultInt; + } + } + +} diff --git a/src/main/java/com/profiler/util/StringUtils.java b/src/main/java/com/profiler/util/StringUtils.java new file mode 100644 index 000000000..ff81351cb --- /dev/null +++ b/src/main/java/com/profiler/util/StringUtils.java @@ -0,0 +1,10 @@ +package com.profiler.util; + +public class StringUtils { + + public static String defaultString(String str, String defaultStr) { + return str == null ? defaultStr : str; + } + + +} diff --git a/src/test/java/com/profiler/context/HeaderTest.java b/src/test/java/com/profiler/context/HeaderTest.java new file mode 100644 index 000000000..f65d97980 --- /dev/null +++ b/src/test/java/com/profiler/context/HeaderTest.java @@ -0,0 +1,10 @@ +package com.profiler.context; + +import org.junit.Test; + +public class HeaderTest { + @Test + public void testToString() throws Exception { + System.out.println(Header.HTTP_FLAGS); + } +} diff --git a/src/test/java/com/profiler/context/SpanIDTest.java b/src/test/java/com/profiler/context/SpanIDTest.java new file mode 100644 index 000000000..debdbf28a --- /dev/null +++ b/src/test/java/com/profiler/context/SpanIDTest.java @@ -0,0 +1,21 @@ +package com.profiler.context; + +import org.junit.Test; + +import java.util.UUID; + +public class SpanIDTest { + @Test + public void newUUID() { + UUID uuid = UUID.randomUUID(); + UUID id = new UUID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + + System.out.println(uuid); + System.out.println(id); + +// System.out.println(uuid.node()); + uuid.compareTo(uuid); + System.out.println(uuid.version()); + System.out.println(Long.MAX_VALUE+"-"+Long.MAX_VALUE); + } +} diff --git a/thrift/Trace.thrift b/thrift/Trace.thrift index 792af1c36..69075e667 100644 --- a/thrift/Trace.thrift +++ b/thrift/Trace.thrift @@ -27,11 +27,12 @@ struct BinaryAnnotation { } struct Span { - 1: string traceID - 2: string name, - 3: string spanID, - 4: optional string parentSpanId, - 5: list annotations, - 6: list binaryAnnotations - 7: optional bool debug = 0 + 1: long mostTraceID + 2: long leastTraceID + 3: string name, + 4: long spanID, + 5: optional long parentSpanId, + 6: list annotations, + 7: list binaryAnnotations + 8: optional bool debug = 0 } \ No newline at end of file