Initialize TraceSegment, TraceSegmentRef, Span, Context, Carrier Class.
This commit is contained in:
parent
001274037a
commit
2a660950cf
|
|
@ -71,7 +71,7 @@ public class Span {
|
|||
* Value -1 means no parent span if this {@link TraceSegment}.
|
||||
* @param operationName {@link #operationName}
|
||||
*/
|
||||
public Span(int spanId, int parentSpanId, String operationName){
|
||||
private Span(int spanId, int parentSpanId, String operationName){
|
||||
this.spanId = spanId;
|
||||
this.parentSpanId = parentSpanId;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
|
@ -91,6 +91,17 @@ public class Span {
|
|||
this(spanId, -1, operationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new span, by given span id and given parent {@link Span}.
|
||||
*
|
||||
* @param spanId given by the creator, and must be unique id in the {@link TraceSegment}
|
||||
* @param parentSpan {@link Span}
|
||||
* @param operationName {@link #operationName}
|
||||
*/
|
||||
public Span(int spanId, Span parentSpan, String operationName){
|
||||
this(spanId, parentSpan.spanId, operationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the active Span.
|
||||
* When it is finished, it will be archived by the given {@link TraceSegment}, which owners it.
|
||||
|
|
@ -177,4 +188,8 @@ public class Span {
|
|||
log(Collections.singletonMap("event", event));
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSpanId() {
|
||||
return spanId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,4 +96,8 @@ public class TraceSegment {
|
|||
public void finish(){
|
||||
this.endTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String getTraceSegmentId() {
|
||||
return traceSegmentId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,40 @@
|
|||
package com.a.eye.skywalking.trace;
|
||||
|
||||
/**
|
||||
*
|
||||
* {@link TraceSegmentRef} is like a pointer, which ref to another {@link TraceSegment}.
|
||||
*
|
||||
* Created by wusheng on 2017/2/17.
|
||||
*/
|
||||
public class TraceSegmentRef {
|
||||
/**
|
||||
* {@link TraceSegment#traceSegmentId}
|
||||
*/
|
||||
private String traceSegmentId;
|
||||
|
||||
/**
|
||||
* {@link Span#spanId}
|
||||
*/
|
||||
private int spanId;
|
||||
|
||||
/**
|
||||
* Create a {@link TraceSegmentRef} instance, without any data.
|
||||
*/
|
||||
public TraceSegmentRef() {
|
||||
}
|
||||
|
||||
public String getTraceSegmentId() {
|
||||
return traceSegmentId;
|
||||
}
|
||||
|
||||
public void setTraceSegmentId(String traceSegmentId) {
|
||||
this.traceSegmentId = traceSegmentId;
|
||||
}
|
||||
|
||||
public int getSpanId() {
|
||||
return spanId;
|
||||
}
|
||||
|
||||
public void setSpanId(int spanId) {
|
||||
this.spanId = spanId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,25 @@ public final class StringUtil {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String join(final char delimiter, final String... strings) {
|
||||
if (strings.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (strings.length == 1) {
|
||||
return strings[0];
|
||||
}
|
||||
int length = strings.length - 1;
|
||||
for (final String s : strings) {
|
||||
length += s.length();
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder(length);
|
||||
sb.append(strings[0]);
|
||||
for (int i = 1; i < strings.length; ++i) {
|
||||
if (!isEmpty(strings[i])) {
|
||||
sb.append(delimiter).append(strings[i]);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,5 @@ public class Constants {
|
|||
* This is the version, which will be the first segment of traceid.
|
||||
* Ref {@link TraceIdGenerator#generate()}
|
||||
*/
|
||||
public static int SDK_VERSION = 212017;
|
||||
|
||||
public static final String CONTEXT_DATA_SEGMENT_SPILT_CHAR = "#&";
|
||||
public static String SDK_VERSION = "302017";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package com.a.eye.skywalking.trace;
|
||||
|
||||
import com.a.eye.skywalking.util.StringUtil;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* {@link ContextCarrier} is a data carrier of {@link TracerContext}.
|
||||
* It holds the snapshot (current state) of {@link TracerContext}.
|
||||
*
|
||||
* Created by wusheng on 2017/2/17.
|
||||
*/
|
||||
public class ContextCarrier extends TraceSegmentRef implements Serializable {
|
||||
|
||||
/**
|
||||
* Serialize this {@link ContextCarrier} to a {@link String},
|
||||
* with '|' split.
|
||||
*
|
||||
* @return the serialization string.
|
||||
*/
|
||||
public String serialize() {
|
||||
return StringUtil.join('|', this.getTraceSegmentId(), this.getSpanId() + "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize fields with the given text.
|
||||
*
|
||||
* @param text carries {@link #traceSegmentId} and {@link #spanId}, with '|' split.
|
||||
*/
|
||||
public ContextCarrier deserialize(String text) {
|
||||
if(text != null){
|
||||
String[] parts = text.split("|");
|
||||
if(parts.length == 2){
|
||||
try{
|
||||
setSpanId(Integer.parseInt(parts[1]));
|
||||
setTraceSegmentId(parts[0]);
|
||||
}catch(NumberFormatException e){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.a.eye.skywalking.trace;
|
||||
|
||||
/**
|
||||
* {@link TracerContext} controls the whole context of {@link TraceSegment}. Any {@link TraceSegment} relates to
|
||||
* single-thread, so this context use {@link ThreadLocal} to maintain the context, and make sure, since a {@link
|
||||
* TraceSegment} starts, all ChildOf spans are in the same context.
|
||||
*
|
||||
* What is 'ChildOf'? {@see https://github.com/opentracing/specification/blob/master/specification.md#references-between-spans}
|
||||
*
|
||||
*
|
||||
* Created by wusheng on 2017/2/17.
|
||||
*/
|
||||
public enum ContextManager {
|
||||
INSTANCE;
|
||||
|
||||
private static ThreadLocal<TracerContext> CONTEXT = new ThreadLocal<>();
|
||||
|
||||
public TracerContext get() {
|
||||
TracerContext segment = CONTEXT.get();
|
||||
if (segment == null) {
|
||||
segment = new TracerContext();
|
||||
CONTEXT.set(segment);
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package com.a.eye.skywalking.trace;
|
||||
|
||||
import com.a.eye.skywalking.util.TraceIdGenerator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link TracerContext} maintains the context.
|
||||
* You manipulate (create/finish/get) spans and (inject/extract) context.
|
||||
*
|
||||
* Created by wusheng on 2017/2/17.
|
||||
*/
|
||||
public final class TracerContext {
|
||||
private TraceSegment segment;
|
||||
|
||||
/**
|
||||
* Active spans stored in a Stack, usually called 'ActiveSpanStack'.
|
||||
* This {@link ArrayList} is the in-memory storage-structure.
|
||||
*
|
||||
* I use {@link ArrayList#size()} as a pointer, to the top element of 'ActiveSpanStack'.
|
||||
* And provide the top 3 important methods of stack:
|
||||
* {@link #pop()}, {@link #push(Span)}, {@link #peek()}
|
||||
*/
|
||||
private List<Span> activeSpanStack = new ArrayList<Span>(20);
|
||||
|
||||
private int spanIdGenerator;
|
||||
|
||||
TracerContext() {
|
||||
this.segment = new TraceSegment(TraceIdGenerator.generate());
|
||||
this.spanIdGenerator = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new span, as an active span, by the given operationName
|
||||
*
|
||||
* @param operationName {@link Span#operationName}
|
||||
* @return the new active span.
|
||||
*/
|
||||
public Span createSpan(String operationName) {
|
||||
Span parentSpan = peek();
|
||||
Span span;
|
||||
if (parentSpan == null) {
|
||||
span = new Span(spanIdGenerator++, operationName);
|
||||
} else {
|
||||
span = new Span(spanIdGenerator++, parentSpan, operationName);
|
||||
}
|
||||
push(span);
|
||||
return span;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the active span of current context.
|
||||
*/
|
||||
public Span activeSpan() {
|
||||
Span span = peek();
|
||||
if (span == null) {
|
||||
throw new IllegalStateException("No active span.");
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the span. And finish the {@link #segment} if all {@link #activeSpanStack} elements are finished.
|
||||
*
|
||||
* @param span to finish. It must the the top element of {@link #activeSpanStack}.
|
||||
*/
|
||||
public void stopSpan(Span span) {
|
||||
Span lastSpan = peek();
|
||||
if (lastSpan == span) {
|
||||
segment.archive(pop());
|
||||
} else {
|
||||
throw new IllegalStateException("Stopping the unexpected span = " + span);
|
||||
}
|
||||
|
||||
if (activeSpanStack.isEmpty()) {
|
||||
segment.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a snapshot of this {@link TracerContext},
|
||||
* and save current state to the given {@link ContextCarrier}.
|
||||
*
|
||||
* @param carrier holds the snapshot
|
||||
*/
|
||||
private void inject(ContextCarrier carrier) {
|
||||
carrier.setTraceSegmentId(this.segment.getTraceSegmentId());
|
||||
carrier.setSpanId(this.activeSpan().getSpanId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ref this {@link ContextCarrier} to this {@link TraceSegment}
|
||||
*
|
||||
* @param carrier holds the snapshot, if get this {@link ContextCarrier} from remote, make sure {@link
|
||||
* ContextCarrier#deserialize(String)} called.
|
||||
*/
|
||||
private void extract(ContextCarrier carrier) {
|
||||
this.segment.ref(carrier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the top element of 'ActiveSpanStack', and remove it.
|
||||
*/
|
||||
private Span pop() {
|
||||
return activeSpanStack.remove(getTopElementIdx());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Span at the top of 'ActiveSpanStack'
|
||||
*
|
||||
* @param span
|
||||
*/
|
||||
private void push(Span span) {
|
||||
activeSpanStack.add(activeSpanStack.size(), span);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the top element of 'ActiveSpanStack' only.
|
||||
*/
|
||||
private Span peek() {
|
||||
if (activeSpanStack.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return activeSpanStack.get(getTopElementIdx());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of 'ActiveSpanStack'
|
||||
*
|
||||
* @return the index
|
||||
*/
|
||||
private int getTopElementIdx() {
|
||||
return activeSpanStack.size() - 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package com.a.eye.skywalking.util;
|
||||
|
||||
import com.a.eye.skywalking.conf.Constants;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.a.eye.skywalking.conf.Constants;
|
||||
import com.a.eye.skywalking.network.grpc.TraceId;
|
||||
|
||||
public final class TraceIdGenerator {
|
||||
private static final ThreadLocal<Integer> ThreadTraceIdSequence = new ThreadLocal<Integer>(){
|
||||
private static final ThreadLocal<Integer> ThreadTraceIdSequence = new ThreadLocal<Integer>() {
|
||||
@Override
|
||||
protected Integer initialValue() {
|
||||
return 0;
|
||||
|
|
@ -32,14 +30,13 @@ public final class TraceIdGenerator {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public static TraceId generate() {
|
||||
public static String generate() {
|
||||
Integer seq = ThreadTraceIdSequence.get();
|
||||
seq++;
|
||||
ThreadTraceIdSequence.set(seq);
|
||||
|
||||
return TraceId.newBuilder().addSegments(Constants.SDK_VERSION)
|
||||
.addSegments(System.currentTimeMillis()).addSegments(PROCESS_UUID)
|
||||
.addSegments(BuriedPointMachineUtil.getProcessNo())
|
||||
.addSegments(Thread.currentThread().getId()).addSegments(seq).build();
|
||||
return StringUtil.join('.',
|
||||
Constants.SDK_VERSION + "", System.currentTimeMillis() + "", PROCESS_UUID + "",
|
||||
BuriedPointMachineUtil.getProcessNo() + "", Thread.currentThread().getId() + "", seq + "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue