提交 2a660950 编写于 作者: wu-sheng's avatar wu-sheng

Initialize TraceSegment, TraceSegmentRef, Span, Context, Carrier Class.

上级 00127403
......@@ -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;
}
}
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";
}
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;
}
}
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;
}
}
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;
}
}
package com.a.eye.skywalking.util;
import java.util.UUID;
import com.a.eye.skywalking.conf.Constants;
import com.a.eye.skywalking.network.grpc.TraceId;
import java.util.UUID;
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 + "");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册