提交 efe11cad 编写于 作者: Z zhangxin

Merge remote-tracking branch 'upstream/feature/3.0' into feature/3.0

......@@ -155,16 +155,4 @@
</plugins>
</build>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>bintray</id>
<name>bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
</project>
......@@ -17,5 +17,68 @@
<artifactId>skywalking-logging-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.a.eye</groupId>
<artifactId>skywalking-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/java/generated-source/protobuf/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.0.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.2:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.a.eye.skywalking.messages;
import com.a.eye.skywalking.trace.TraceSegment;
/**
* All messages, which need to send between Akka actors, should implement this interface.
* The whole {@link TraceSegment} supports this.
*
* T should be a protobuf Object, which is generated by protoc.
* {@see /sky-walking/skywalking-commons/skywalking-trace/src/main/proto/trace.proto}
*
* {@see https://github.com/google/protobuf/tree/master/java}
*
* Created by wusheng on 2017/2/22.
*/
public interface ISerializable<T> {
/**
* Serialize this object to T
* @return
*/
T serialize();
/**
* Initialize this object by the given message.
*
* @param message to init object.
*/
void deserialize(T message);
}
package com.a.eye.skywalking.trace;
import com.a.eye.skywalking.api.util.StringUtil;
import com.a.eye.skywalking.messages.ISerializable;
import com.a.eye.skywalking.trace.messages.proto.KeyValue;
import com.a.eye.skywalking.trace.messages.proto.LogDataMessage;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
......@@ -8,15 +14,22 @@ import java.util.Map;
*
* Created by wusheng on 2017/2/17.
*/
public class LogData {
private final long time;
private final Map<String, ?> fields;
public class LogData implements ISerializable<LogDataMessage>{
private long time;
private Map<String, ?> fields;
LogData(long time, Map<String, ?> fields) {
this.time = time;
if(fields == null){
throw new NullPointerException();
}
this.fields = fields;
}
LogData(LogDataMessage message){
deserialize(message);
}
public long getTime() {
return time;
}
......@@ -24,4 +37,38 @@ public class LogData {
public Map<String, ?> getFields() {
return Collections.unmodifiableMap(fields);
}
@Override
public LogDataMessage serialize() {
LogDataMessage.Builder logDataBuilder = LogDataMessage.newBuilder();
logDataBuilder.setTime(time);
if(fields != null){
for (Map.Entry<String, ?> entry : fields.entrySet()) {
KeyValue.Builder logEntryBuilder = KeyValue.newBuilder();
logEntryBuilder.setKey(entry.getKey());
String value = String.valueOf(entry.getValue());
if(!StringUtil.isEmpty(value)) {
logEntryBuilder.setValue(value);
}
logDataBuilder.addFields(logEntryBuilder);
}
}
return logDataBuilder.build();
}
@Override
public void deserialize(LogDataMessage message) {
time = message.getTime();
List<KeyValue> list = message.getFieldsList();
if(list != null){
HashMap initFields = new HashMap<String, String>();
for (KeyValue field : list) {
initFields.put(field.getKey(), field.getValue());
}
this.fields = initFields;
}
}
}
package com.a.eye.skywalking.trace;
import com.a.eye.skywalking.api.util.StringUtil;
import com.a.eye.skywalking.messages.ISerializable;
import com.a.eye.skywalking.trace.messages.proto.KeyValue;
import com.a.eye.skywalking.trace.messages.proto.LogDataMessage;
import com.a.eye.skywalking.trace.messages.proto.SpanMessage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
......@@ -17,7 +23,7 @@ import java.util.Map;
*
* Created by wusheng on 2017/2/17.
*/
public class Span {
public class Span implements ISerializable<SpanMessage> {
private int spanId;
private int parentSpanId;
......@@ -67,7 +73,7 @@ public class Span {
}
/**
*Create a new span, by given span id, parent span id, operationName and startTime.
* Create a new span, by given span id, parent span id, operationName and startTime.
* This span must belong a {@link TraceSegment}, also is a part of Distributed Trace.
*
* @param spanId given by the creator, and must be unique id in the {@link TraceSegment}
......@@ -76,7 +82,7 @@ public class Span {
* @param operationName {@link #operationName}
* @param startTime given start timestamp.
*/
private Span(int spanId, int parentSpanId, String operationName, long startTime){
private Span(int spanId, int parentSpanId, String operationName, long startTime) {
this.spanId = spanId;
this.parentSpanId = parentSpanId;
this.startTime = startTime;
......@@ -97,7 +103,6 @@ public class Span {
}
/**
*
* Create a new span, by given span id and give startTime but no parent span id,
* No parent span id means that, this Span is the first span of the {@link TraceSegment}
*
......@@ -121,16 +126,30 @@ public class Span {
}
/**
* Create a new span, by given span id, parent span, operationName and startTime.
* This span must belong a {@link TraceSegment}, also is a part of Distributed Trace.
*
* @param spanId
* @param parentSpan
* @param operationName
* @param startTime
* @param spanId given by the creator, and must be unique id in the {@link TraceSegment}
* @param parentSpan {@link Span}
* @param operationName {@link #operationName}
* @param startTime given start timestamp
*/
public Span(int spanId, Span parentSpan, String operationName, long startTime) {
this(spanId, parentSpan.spanId, operationName, startTime);
}
/**
* Create a new span, by given {@link SpanMessage}, which you can get from another {@link Span} object,
* by calling {@link Span#serialize()};
*
* @param spanMessage from another {@link Span#serialize()}
*/
public Span(SpanMessage spanMessage) {
tags = new HashMap<String, Object>();
logs = new LinkedList<LogData>();
this.deserialize(spanMessage);
}
/**
* Finish the active Span.
* When it is finished, it will be archived by the given {@link TraceSegment}, which owners it.
......@@ -149,7 +168,7 @@ public class Span {
* @param owner of the Span.
* @param endTime of the Span.
*/
public void finish(TraceSegment owner, long endTime){
public void finish(TraceSegment owner, long endTime) {
this.endTime = endTime;
owner.archive(this);
}
......@@ -159,7 +178,7 @@ public class Span {
*
* @return this Span instance, for chaining
*/
public Span setOperationName(String operationName){
public Span setOperationName(String operationName) {
this.operationName = operationName;
return this;
}
......@@ -239,6 +258,7 @@ public class Span {
*/
public Span log(Throwable t) {
Map<String, String> exceptionFields = new HashMap<String, String>();
exceptionFields.put("event", "error");
exceptionFields.put("error.kind", t.getClass().getName());
exceptionFields.put("message", t.getMessage());
exceptionFields.put("stack", ThrowableTransformer.INSTANCE.convert2String(t, 4000));
......@@ -246,6 +266,51 @@ public class Span {
return log(exceptionFields);
}
@Override
public SpanMessage serialize() {
SpanMessage.Builder builder = SpanMessage.newBuilder();
builder.setSpanId(spanId);
builder.setStartTime(startTime);
builder.setEndTime(endTime);
builder.setOperationName(operationName);
for (Map.Entry<String, Object> entry : tags.entrySet()) {
KeyValue.Builder tagEntryBuilder = KeyValue.newBuilder();
tagEntryBuilder.setKey(entry.getKey());
String value = String.valueOf(entry.getValue());
if (!StringUtil.isEmpty(value)) {
tagEntryBuilder.setValue(value);
}
builder.addTags(tagEntryBuilder);
}
for (LogData log : logs) {
builder.addLogs(log.serialize());
}
return builder.build();
}
@Override
public void deserialize(SpanMessage message) {
spanId = message.getSpanId();
startTime = message.getStartTime();
endTime = message.getEndTime();
operationName = message.getOperationName();
List<KeyValue> tagsList = message.getTagsList();
if(tagsList != null){
for (KeyValue tag : tagsList) {
tags.put(tag.getKey(), tag.getValue());
}
}
List<LogDataMessage> logsList = message.getLogsList();
if (logsList != null) {
for (LogDataMessage logDataMessage : logsList) {
logs.add(new LogData(logDataMessage));
}
}
}
private enum ThrowableTransformer {
INSTANCE;
......
package com.a.eye.skywalking.trace;
import com.a.eye.skywalking.messages.ISerializable;
import com.a.eye.skywalking.trace.messages.proto.SegmentMessage;
import com.a.eye.skywalking.trace.messages.proto.SegmentRefMessage;
import com.a.eye.skywalking.trace.messages.proto.SpanMessage;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
......@@ -13,7 +17,7 @@ import java.util.List;
*
* Created by wusheng on 2017/2/17.
*/
public class TraceSegment {
public class TraceSegment implements ISerializable<SegmentMessage> {
/**
* The id of this trace segment.
* Every segment has its unique-global-id.
......@@ -51,18 +55,36 @@ public class TraceSegment {
*/
private List<Span> spans;
/**
* The <code>applicationCode</code> represents a name of current application/JVM and indicates which is business
* role in the cluster.
*
* e.g. account_app, billing_app
*/
private String applicationCode;
/**
* Create a trace segment, by given segmentId.
* This segmentId is generated by TraceSegmentRef, AKA, from tracer/agent module.
*
* @param segmentId {@link #traceSegmentId}
*/
public TraceSegment(String segmentId) {
public TraceSegment(String segmentId, String applicationCode) {
this.traceSegmentId = segmentId;
this.applicationCode = applicationCode;
this.startTime = System.currentTimeMillis();
this.spans = new LinkedList<Span>();
}
/**
* Create a trace segment, by given {@link SegmentMessage}
*
* @param message from another {@link TraceSegment#serialize()}
*/
public TraceSegment(SegmentMessage message) {
deserialize(message);
}
/**
* Establish the link between this segment and its parents.
* The first time, you {@link #ref(TraceSegmentRef)} to parent, it is affirmed as {@link #primaryRef}.
......@@ -70,10 +92,10 @@ public class TraceSegment {
*
* @param refSegment {@link TraceSegmentRef}
*/
public void ref(TraceSegmentRef refSegment){
if(primaryRef == null){
public void ref(TraceSegmentRef refSegment) {
if (primaryRef == null) {
primaryRef = refSegment;
}else {
} else {
if (refs == null) {
refs = new LinkedList<TraceSegmentRef>();
}
......@@ -87,7 +109,7 @@ public class TraceSegment {
*
* @param finishedSpan
*/
public void archive(Span finishedSpan){
public void archive(Span finishedSpan) {
spans.add(finishedSpan);
}
......@@ -96,9 +118,9 @@ public class TraceSegment {
*
* return this, for chaining
*/
public TraceSegment finish(){
this.endTime = System.currentTimeMillis();
return this;
public TraceSegment finish() {
this.endTime = System.currentTimeMillis();
return this;
}
public String getTraceSegmentId() {
......@@ -125,6 +147,10 @@ public class TraceSegment {
return Collections.unmodifiableList(spans);
}
public String getApplicationCode() {
return applicationCode;
}
@Override
public String toString() {
return "TraceSegment{" +
......@@ -134,4 +160,47 @@ public class TraceSegment {
", spans.size=" + spans.size() +
'}';
}
@Override
public SegmentMessage serialize() {
SegmentMessage.Builder segmentBuilder = SegmentMessage.newBuilder();
segmentBuilder.setTraceSegmentId(traceSegmentId);
segmentBuilder.setStartTime(startTime);
segmentBuilder.setEndTime(endTime);
segmentBuilder.setApplicationCode(applicationCode);
segmentBuilder.setPrimaryRef(primaryRef.serialize());
for (TraceSegmentRef ref : refs) {
segmentBuilder.addRefs(ref.serialize());
}
for (Span span : spans) {
segmentBuilder.addSpans(span.serialize());
}
return segmentBuilder.build();
}
@Override
public void deserialize(SegmentMessage message) {
traceSegmentId = message.getTraceSegmentId();
startTime = message.getStartTime();
endTime = message.getEndTime();
applicationCode = message.getApplicationCode();
(primaryRef = new TraceSegmentRef()).deserialize(message.getPrimaryRef());
List<SegmentRefMessage> refsList = message.getRefsList();
if (refsList != null) {
this.refs = new LinkedList<TraceSegmentRef>();
for (SegmentRefMessage refMessage : refsList) {
TraceSegmentRef ref = new TraceSegmentRef();
ref.deserialize(refMessage);
refs.add(ref);
}
}
List<SpanMessage> spansList = message.getSpansList();
if (spansList != null) {
this.spans = new LinkedList<Span>();
for (SpanMessage spanMessage : spansList) {
spans.add(new Span(spanMessage));
}
}
}
}
package com.a.eye.skywalking.trace;
import com.a.eye.skywalking.messages.ISerializable;
import com.a.eye.skywalking.trace.messages.proto.SegmentRefMessage;
import com.a.eye.skywalking.trace.tag.Tags;
/**
* {@link TraceSegmentRef} is like a pointer, which ref to another {@link TraceSegment},
* use {@link #spanId} point to the exact span of the ref {@link TraceSegment}.
*
* Created by wusheng on 2017/2/17.
*/
public class TraceSegmentRef {
public class TraceSegmentRef implements ISerializable<SegmentRefMessage> {
/**
* {@link TraceSegment#traceSegmentId}
*/
......@@ -17,6 +21,16 @@ public class TraceSegmentRef {
*/
private int spanId = -1;
/**
* {@link TraceSegment#applicationCode}
*/
private String applicationCode;
/**
* {@link Tags#PEER_HOST}
*/
private String peerHost;
/**
* Create a {@link TraceSegmentRef} instance, without any data.
*/
......@@ -39,11 +53,48 @@ public class TraceSegmentRef {
this.spanId = spanId;
}
@Override
public String toString() {
public String getApplicationCode() {
return applicationCode;
}
public void setApplicationCode(String applicationCode) {
this.applicationCode = applicationCode;
}
public String getPeerHost() {
return peerHost;
}
public void setPeerHost(String peerHost) {
this.peerHost = peerHost;
}
@Override public String toString() {
return "TraceSegmentRef{" +
"traceSegmentId='" + traceSegmentId + '\'' +
", spanId=" + spanId +
", applicationCode='" + applicationCode + '\'' +
", peerHost='" + peerHost + '\'' +
'}';
}
@Override
public SegmentRefMessage serialize() {
SegmentRefMessage.Builder builder = SegmentRefMessage.newBuilder();
builder.setTraceSegmentId(traceSegmentId);
builder.setSpanId(spanId);
builder.setApplicationCode(applicationCode);
if(peerHost != null) {
builder.setPeerHost(peerHost);
}
return builder.build();
}
@Override
public void deserialize(SegmentRefMessage message) {
traceSegmentId = message.getTraceSegmentId();
spanId = message.getSpanId();
applicationCode = message.getApplicationCode();
peerHost = message.getPeerHost();
}
}
......@@ -17,7 +17,20 @@ public class BooleanTag extends AbstractTag<Boolean>{
span.setTag(key, tagValue);
}
@Override public Boolean get(Span span) {
return (Boolean)span.getTag(super.key);
/**
* Get a tag value, type of {@link Boolean}.
* After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Boolean}, if necessary.
*
* @param span
* @return tag value
*/
@Override
public Boolean get(Span span) {
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Boolean){
return (Boolean)tagValue;
}else {
return Boolean.valueOf(tagValue.toString());
}
}
}
......@@ -17,7 +17,20 @@ public class IntTag extends AbstractTag<Integer> {
span.setTag(super.key, tagValue);
}
@Override public Integer get(Span span) {
return (Integer)span.getTag(super.key);
/**
* Get a tag value, type of {@link Integer}.
* After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Integer}, if necessary.
*
* @param span
* @return tag value
*/
@Override
public Integer get(Span span) {
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Integer){
return (Integer)tagValue;
}else {
return Integer.valueOf(tagValue.toString());
}
}
}
......@@ -17,7 +17,19 @@ public class ShortTag extends AbstractTag<Short> {
span.setTag(super.key, tagValue);
}
/**
* Get a tag value, type of {@link Short}.
* After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Short}, if necessary.
*
* @param span
* @return tag value
*/
@Override public Short get(Span span) {
return (Short)span.getTag(super.key);
Object tagValue = span.getTag(super.key);
if(tagValue instanceof Short){
return (Short)tagValue;
}else {
return Short.valueOf(tagValue.toString());
}
}
}
......@@ -102,7 +102,7 @@ public final class Tags {
public static final BooleanTag ERROR = new BooleanTag("error");
/**
* PEER_HOST records host address of the peer, maybe IPV4, IPV6 or hostname.
* PEER_HOST records host address (ip:port, or ip1:port1,ip2:port2) of the peer, maybe IPV4, IPV6 or hostname.
*/
public static final StringTag PEER_HOST = new StringTag("peer.host");
......
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.a.eye.skywalking.trace.messages.proto";
message SegmentMessage {
string traceSegmentId = 1;
int64 startTime = 2;
int64 endTime = 3;
string applicationCode = 4;
SegmentRefMessage primaryRef = 5;
repeated SegmentRefMessage refs = 6;
repeated SpanMessage spans = 7;
}
message SegmentRefMessage {
string traceSegmentId = 1;
int32 spanId = 2;
string applicationCode = 3;
string peerHost = 4;
}
message SpanMessage {
int32 spanId = 1;
int64 startTime = 2;
int64 endTime = 3;
string operationName = 4;
repeated KeyValue tags = 5;
repeated LogDataMessage logs = 6;
}
message LogDataMessage {
int64 time = 1;
repeated KeyValue fields = 5;
}
message KeyValue {
string key = 1;
string value = 2;
}
......@@ -14,6 +14,8 @@ public class SpanTestCase {
public void testConstructors() {
Span span1 = new Span(0, "serviceA");
Span span2 = new Span(2, span1, "serviceA");
span2.setOperationName("serviceA-2");
Assert.assertEquals("serviceA-2", span2.getOperationName());
Assert.assertEquals(-1, span1.getParentSpanId());
Assert.assertEquals(0, span2.getParentSpanId());
......@@ -23,7 +25,7 @@ public class SpanTestCase {
@Test
public void testFinish() {
TraceSegment owner = new TraceSegment("trace_1");
TraceSegment owner = new TraceSegment("trace_1", "billing_app");
Span span1 = new Span(0, "serviceA");
......
package com.a.eye.skywalking.trace;
import com.a.eye.skywalking.trace.tag.Tags;
import org.junit.Assert;
import org.junit.Test;
......@@ -8,16 +9,17 @@ import org.junit.Test;
*/
public class TraceSegmentTestCase {
@Test
public void testConstructor(){
TraceSegment segment = new TraceSegment("trace_1");
public void testConstructor() {
TraceSegment segment = new TraceSegment("trace_1", "billing_app");
Assert.assertEquals("trace_1", segment.getTraceSegmentId());
Assert.assertTrue(segment.getStartTime() > 0);
Assert.assertEquals("billing_app", segment.getApplicationCode());
}
@Test
public void testRef(){
TraceSegment segment = new TraceSegment("trace_3");
public void testRef() {
TraceSegment segment = new TraceSegment("trace_3", "billing_app");
TraceSegmentRef ref1 = new TraceSegmentRef();
ref1.setTraceSegmentId("parent_trace_0");
......@@ -43,8 +45,8 @@ public class TraceSegmentTestCase {
}
@Test
public void testArchiveSpan(){
TraceSegment segment = new TraceSegment("trace_1");
public void testArchiveSpan() {
TraceSegment segment = new TraceSegment("trace_1", "billing_app");
Span span1 = new Span(1, "/serviceA");
segment.archive(span1);
......@@ -56,11 +58,53 @@ public class TraceSegmentTestCase {
}
@Test
public void testFinish(){
TraceSegment segment = new TraceSegment("trace_1");
public void testFinish() {
TraceSegment segment = new TraceSegment("trace_1", "billing_app");
Assert.assertTrue(segment.getEndTime() == 0);
segment.finish();
Assert.assertTrue(segment.getEndTime() > 0);
}
@Test
public void testSerialize() {
TraceSegment segment = new TraceSegment("trace_3", "billing_app");
TraceSegmentRef ref1 = new TraceSegmentRef();
ref1.setTraceSegmentId("parent_trace_0");
ref1.setSpanId(1);
ref1.setApplicationCode("REMOTE_APP");
ref1.setPeerHost("10.2.3.16:8080");
segment.ref(ref1);
TraceSegmentRef ref2 = new TraceSegmentRef();
ref2.setTraceSegmentId("parent_trace_1");
ref2.setSpanId(5);
ref2.setApplicationCode("REMOTE_APP");
ref2.setPeerHost("10.2.3.16:8080");
segment.ref(ref2);
TraceSegmentRef ref3 = new TraceSegmentRef();
ref3.setTraceSegmentId("parent_trace_1");
ref3.setSpanId(5);
ref3.setApplicationCode("REMOTE_APP");
ref3.setPeerHost("10.2.3.16:8080");
segment.ref(ref3);
Span span1 = new Span(1, "/serviceA");
Tags.SPAN_LAYER.asHttp(span1);
segment.archive(span1);
Span span2 = new Span(2, span1, "/db/sql");
Tags.SPAN_LAYER.asNoSQL(span2);
span2.log(new NullPointerException());
segment.archive(span2);
TraceSegment newSegment = new TraceSegment(segment.serialize());
Assert.assertEquals(segment.getSpans().size(), newSegment.getSpans().size());
Assert.assertEquals(segment.getPrimaryRef().getTraceSegmentId(), newSegment.getPrimaryRef().getTraceSegmentId());
Assert.assertEquals(Tags.SPAN_LAYER.get(segment.getSpans().get(0)), Tags.SPAN_LAYER.get(newSegment.getSpans().get(0)));
Assert.assertEquals(segment.getSpans().get(1).getLogs().get(0).getTime(), newSegment.getSpans().get(1).getLogs().get(0).getTime());
}
}
package com.a.eye.skywalking.api.context;
import com.a.eye.skywalking.trace.TraceSegmentRef;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.api.util.StringUtil;
import com.a.eye.skywalking.trace.tag.Tags;
import java.io.Serializable;
/**
......@@ -10,7 +12,26 @@ import java.io.Serializable;
*
* Created by wusheng on 2017/2/17.
*/
public class ContextCarrier extends TraceSegmentRef implements Serializable {
public class ContextCarrier implements Serializable {
/**
* {@link TraceSegment#traceSegmentId}
*/
private String traceSegmentId;
/**
* {@link Span#spanId}
*/
private int spanId = -1;
/**
* {@link TraceSegment#applicationCode}
*/
private String applicationCode;
/**
* {@link Tags#PEER_HOST}
*/
private String peerHost;
/**
* Serialize this {@link ContextCarrier} to a {@link String},
......@@ -19,7 +40,7 @@ public class ContextCarrier extends TraceSegmentRef implements Serializable {
* @return the serialization string.
*/
public String serialize() {
return StringUtil.join('|', this.getTraceSegmentId(), this.getSpanId() + "");
return StringUtil.join('|', this.getTraceSegmentId(), this.getSpanId() + "", this.getApplicationCode(), this.getPeerHost());
}
/**
......@@ -29,11 +50,13 @@ public class ContextCarrier extends TraceSegmentRef implements Serializable {
*/
public ContextCarrier deserialize(String text) {
if(text != null){
String[] parts = text.split("\\|");
if(parts.length == 2){
String[] parts = text.split("\\|", 4);
if(parts.length == 4){
try{
setSpanId(Integer.parseInt(parts[1]));
setTraceSegmentId(parts[0]);
setApplicationCode(parts[2]);
setPeerHost(parts[3]);
}catch(NumberFormatException e){
}
......@@ -48,7 +71,38 @@ public class ContextCarrier extends TraceSegmentRef implements Serializable {
* @return true for unbroken {@link ContextCarrier} or no-initialized. Otherwise, false;
*/
public boolean isValid(){
return !StringUtil.isEmpty(getTraceSegmentId()) && getSpanId() > -1;
return !StringUtil.isEmpty(traceSegmentId) && getSpanId() > -1 && !StringUtil.isEmpty(applicationCode) && !StringUtil.isEmpty(peerHost);
}
public String getTraceSegmentId() {
return traceSegmentId;
}
public int getSpanId() {
return spanId;
}
public void setTraceSegmentId(String traceSegmentId) {
this.traceSegmentId = traceSegmentId;
}
public void setSpanId(int spanId) {
this.spanId = spanId;
}
public String getApplicationCode() {
return applicationCode;
}
public void setApplicationCode(String applicationCode) {
this.applicationCode = applicationCode;
}
public String getPeerHost() {
return peerHost;
}
public void setPeerHost(String peerHost) {
this.peerHost = peerHost;
}
}
package com.a.eye.skywalking.api.context;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.api.util.TraceIdGenerator;
import com.a.eye.skywalking.trace.TraceSegmentRef;
import com.a.eye.skywalking.trace.tag.Tags;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
......@@ -28,8 +31,11 @@ public final class TracerContext {
private int spanIdGenerator;
/**
* Create a {@link TraceSegment} and init {@link #spanIdGenerator} as 0;
*/
TracerContext() {
this.segment = new TraceSegment(TraceIdGenerator.generate());
this.segment = new TraceSegment(TraceIdGenerator.generate(), Config.SkyWalking.APPLICATION_CODE);
this.spanIdGenerator = 0;
}
......@@ -111,6 +117,8 @@ public final class TracerContext {
public void inject(ContextCarrier carrier) {
carrier.setTraceSegmentId(this.segment.getTraceSegmentId());
carrier.setSpanId(this.activeSpan().getSpanId());
carrier.setApplicationCode(Config.SkyWalking.APPLICATION_CODE);
carrier.setPeerHost(Tags.PEER_HOST.get(activeSpan()));
}
/**
......@@ -120,7 +128,12 @@ public final class TracerContext {
* ContextCarrier#deserialize(String)} called.
*/
public void extract(ContextCarrier carrier) {
this.segment.ref(carrier);
TraceSegmentRef ref = new TraceSegmentRef();
ref.setTraceSegmentId(carrier.getTraceSegmentId());
ref.setSpanId(carrier.getSpanId());
ref.setApplicationCode(carrier.getApplicationCode());
ref.setPeerHost(carrier.getPeerHost());
this.segment.ref(ref);
}
/**
......
package com.a.eye.skywalking.api.util;
/**
* Created data xin on 2016/12/4.
*/
public class RoutingKeyGenerator {
public static int generate(String originData) {
char[] value = originData.toCharArray();
int h = 0;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
}
return h;
}
}
......@@ -12,17 +12,21 @@ public class ContextCarrierTestCase {
ContextCarrier carrier = new ContextCarrier();
carrier.setTraceSegmentId("trace_id_A");
carrier.setSpanId(100);
carrier.setApplicationCode("REMOTE_APP");
carrier.setPeerHost("10.2.3.16:8080");
Assert.assertEquals("trace_id_A|100", carrier.serialize());
Assert.assertEquals("trace_id_A|100|REMOTE_APP|10.2.3.16:8080", carrier.serialize());
}
@Test
public void testDeserialize(){
ContextCarrier carrier = new ContextCarrier();
carrier.deserialize("trace_id_A|100");
carrier.deserialize("trace_id_A|100|REMOTE_APP|10.2.3.16:8080");
Assert.assertEquals("trace_id_A", carrier.getTraceSegmentId());
Assert.assertEquals(100, carrier.getSpanId());
Assert.assertEquals("REMOTE_APP", carrier.getApplicationCode());
Assert.assertEquals("10.2.3.16:8080", carrier.getPeerHost());
}
@Test
......@@ -44,7 +48,7 @@ public class ContextCarrierTestCase {
Assert.assertFalse(carrier.isValid());
carrier = new ContextCarrier();
carrier.deserialize("trace_id|100");
carrier.deserialize("trace_id|100|REMOTE_APP|10.2.3.16:8080");
Assert.assertTrue(carrier.isValid());
}
}
......@@ -2,6 +2,7 @@ package com.a.eye.skywalking.api.context;
import com.a.eye.skywalking.trace.Span;
import com.a.eye.skywalking.trace.TraceSegment;
import com.a.eye.skywalking.trace.tag.Tags;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
......@@ -56,11 +57,12 @@ public class TracerContextTestCase {
TracerContext context = new TracerContext();
Span serviceSpan = context.createSpan("/serviceA");
Span dbSpan = context.createSpan("db/preparedStatement/execute");
Tags.PEER_HOST.set(dbSpan, "127.0.0.1:8080");
ContextCarrier carrier = new ContextCarrier();
context.inject(carrier);
Assert.assertTrue(carrier.isValid());
Assert.assertEquals("127.0.0.1:8080", carrier.getPeerHost());
Assert.assertEquals(1, carrier.getSpanId());
}
......@@ -69,6 +71,8 @@ public class TracerContextTestCase {
ContextCarrier carrier = new ContextCarrier();
carrier.setTraceSegmentId("trace_id_1");
carrier.setSpanId(5);
carrier.setApplicationCode("REMOTE_APP");
carrier.setPeerHost("10.2.3.16:8080");
Assert.assertTrue(carrier.isValid());
......
package com.a.eye.skywalking.api.plugin;
public class BeInterceptedClass {
public BeInterceptedClass(){
System.out.println("BeInterceptedClass constructor.");
}
public void printabc(){
System.out.println("printabc");
}
public static void call(){
System.out.println("static call");
}
}
package com.a.eye.skywalking.api.plugin;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
public class PluginMainTest {
@Test
public void testMain() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, PluginException {
TracingBootstrap.main(new String[] {"PluginMainTest"});
}
public static void main(String[] args)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException,
SecurityException {
long start = System.currentTimeMillis();
BeInterceptedClass inst = (BeInterceptedClass) Class.forName("BeInterceptedClass").newInstance();
inst.printabc();
long end = System.currentTimeMillis();
System.out.println(end - start + "ms");
BeInterceptedClass.call();
}
}
package com.a.eye.skywalking.api.plugin;
import java.io.IOException;
public class PluginResourceResoverTest {
public static void main(String[] args) throws IOException {
PluginResourcesResolver resolver = new PluginResourcesResolver();
resolver.getResources();
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
public class TestAroundInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) {
System.out.println("beforeMethod : " + context.get("test.key", String.class));
}
@Override
public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) {
System.out.println("afterMethod: " + context.get("test.key", String.class));
return ret;
}
@Override
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) {
// TODO Auto-generated method stub
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.StaticMethodsInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassEnhancePluginDefine;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import static net.bytebuddy.matcher.ElementMatchers.named;
public class TestInterceptorDefine extends ClassEnhancePluginDefine {
@Override
public String enhanceClassName() {
return "BeInterceptedClass";
}
@Override
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return null;
}
@Override
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("printabc");
}
@Override
public String getMethodsInterceptor() {
return "TestAroundInterceptor";
}
}};
}
@Override
protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
return new StaticMethodsInterceptPoint[] {new StaticMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("call");
}
@Override
public String getMethodsInterceptor() {
return "TestStaticAroundInterceptor";
}
}};
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
public class TestStaticAroundInterceptor implements StaticMethodsAroundInterceptor {
@Override
public void beforeMethod(StaticMethodInvokeContext interceptorContext, MethodInterceptResult result) {
System.out.println("beforeMethod : static");
}
@Override
public Object afterMethod(StaticMethodInvokeContext interceptorContext, Object ret) {
System.out.println("afterMethod: static");
return ret;
}
@Override
public void handleMethodException(Throwable t, MethodInvokeContext interceptorContext) {
// TODO Auto-generated method stub
}
}
package com.a.eye.skywalking.bytebuddy;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.This;
public class ConstructorInterceptor {
@RuntimeType
public void intercept(@AllArguments Object[] allArguments) {
System.out
.println("ConstructorInterceptor size:" + allArguments.length);
if(allArguments.length > 0){
System.out.println("ConstructorInterceptor param[0]=" + allArguments[0]);
}
}
}
package com.a.eye.skywalking.bytebuddy;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.implementation.bind.annotation.This;
public class MethodInterceptor{
@RuntimeType
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method, @SuperCall Callable<?> zuper){
try {
return method.getName() + ":intercept_" + zuper.call();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
package com.a.eye.skywalking.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.pool.TypePool;
public class SimulateMain {
public static void main(String[] args) throws NoSuchFieldException,
SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException {
TypePool typePool = TypePool.Default.ofClassPath();
System.out.println(typePool.describe("TestClass").isResolved());
Class<?> newClazz = new ByteBuddy()
.redefine(
typePool.describe("TestClass")
.resolve(),
ClassFileLocator.ForClassLoader.ofClassPath())
.name("TestClass$$Origin")
.make()
.load(ClassLoader.getSystemClassLoader(),
ClassLoadingStrategy.Default.INJECTION).getLoaded();
TestClass t22 = (TestClass) (new ByteBuddy()
.subclass(newClazz, ConstructorStrategy.Default.IMITATE_SUPER_CLASS)
.method(isMethod())
.intercept(MethodDelegation.to(new MethodInterceptor()))
.constructor(isConstructor())
.intercept(MethodDelegation.to(new ConstructorInterceptor()).andThen(SuperMethodCall.INSTANCE))
.name("TestClass")
.make()
.load(ClassLoader.getSystemClassLoader(),
ClassLoadingStrategy.Default.INJECTION).getLoaded()
.newInstance());
// System.out.println(t22.testA("1"));
TestClass t = new TestClass("abc");
System.out.println(t.testA("1"));
t = new TestClass("abc");
System.out.println(t.testA("1"));
// TestClass t2 = null;
// try {
// t2 = (TestClass) Class.forName("TestClass")
// .newInstance();
// } catch (ClassNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// System.out.println(t2.testA("1"));
}
}
package com.a.eye.skywalking.bytebuddy;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.pool.TypePool;
public class SimulateMain2 {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException {
TypePool typePool = TypePool.Default.ofClassPath();
new ByteBuddy()
.rebase(typePool.describe("TestClass")
.resolve(),
ClassFileLocator.ForClassLoader.ofClassPath())
.method(named("testA"))
.intercept(MethodDelegation.to(new MethodInterceptor()))
.method(named("testB"))
.intercept(MethodDelegation.to(new MethodInterceptor()))
.constructor(isConstructor())
.intercept(
MethodDelegation.to(new ConstructorInterceptor())
.andThen(SuperMethodCall.INSTANCE))
.make()
.load(ClassLoader.getSystemClassLoader(),
ClassLoadingStrategy.Default.INJECTION).getLoaded();
TestClass t = new TestClass("abc");
System.out.println(t.testA("1"));
}
}
package com.a.eye.skywalking.bytebuddy;
public class TestClass {
public TestClass(){
//System.out.println("init:" + this.getClass().getName());
}
public TestClass(String tmp){
//System.out.println("init:" + this.getClass().getName());
}
public String testA(String aa){
// throw new RuntimeException("adfasdfas");
return "TestClass.testA";
}
}
package com.a.eye.skywalking.toolkit.activation.log.log4j.v1.x;
import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint;
import com.a.eye.skywalking.plugin.interceptor.StaticMethodsInterceptPoint;
import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
......
package com.a.eye.skywalking.toolkit.activation.trace;
import com.a.eye.skywalking.plugin.interceptor.StaticMethodsInterceptPoint;
import com.a.eye.skywalking.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
import com.a.eye.skywalking.api.plugin.interceptor.StaticMethodsInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
......
package com.a.eye.skywalking.toolkit.activation.trace;
import com.a.eye.skywalking.api.Tracing;
import com.a.eye.skywalking.api.context.ContextCarrier;
import com.a.eye.skywalking.api.context.ContextManager;
import com.a.eye.skywalking.api.logging.api.ILog;
import com.a.eye.skywalking.api.logging.api.LogManager;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
import com.a.eye.skywalking.plugin.interceptor.enhance.MethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
/**
*
*
* Created by xin on 2016/12/15.
*/
......@@ -24,7 +24,9 @@ public class TraceContextInterceptor implements StaticMethodsAroundInterceptor {
@Override
public Object afterMethod(StaticMethodInvokeContext interceptorContext, Object ret) {
return Tracing.getTraceId();
ContextCarrier carrier = new ContextCarrier();
ContextManager.INSTANCE.inject(carrier);
return carrier.getTraceSegmentId();
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册