package com.yirendai.infra.cicada.entity.trace;
import com.alibaba.fastjson.annotation.JSONField;
import com.yirendai.infra.cicada.constants.AnnotationType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Span implements Serializable, Comparable<Span> {
private static final long serialVersionUID = -527884689646021836L;
private String traceId;
private String id;
private String parentId;
private String appName;
private String serviceName;
private String methodName;
@JSONField(serialize = false)
private int subSpanNum;
private int durationServer;
private int durationClient;
private boolean hasException = false;
@JSONField(serialize = false)
private boolean sample;
private List<Annotation> annotations = new ArrayList<Annotation>();
private List<BinaryAnnotation> binaryAnnotations = new ArrayList<BinaryAnnotation>();
@JSONField(serialize = false)
public boolean isRootSpan() {
return (parentId == null);
}
public void addAnnotation(Annotation anno) {
annotations.add(anno);
}
public void addBinaryAnnotation(BinaryAnnotation anno) {
binaryAnnotations.add(anno);
}
@Override
public String toString() {
return "Span{" + "traceId=" + traceId + ", id=" + id + ", parentId=" + parentId + ", serviceName=" + serviceName
+ ", methodName='" + methodName + '\'' + ", annotations=" + annotations + ", binaryAnnotations="
+ binaryAnnotations + '}';
}
public int compareTo(Span other) {
int traceIdResult = traceId.compareTo(other.traceId);
if (traceIdResult != 0) {
return traceIdResult;
}
String[] thisSpanArr = id.split("\\.");
String[] otherSpanArr = other.id.split("\\.");
int shortLength = thisSpanArr.length;
if (thisSpanArr.length > otherSpanArr.length) {
shortLength = otherSpanArr.length;
if (this.id.startsWith(other.id)) {
return 1;
}
} else if (thisSpanArr.length < otherSpanArr.length) {
if (other.id.startsWith(this.id)) {
return -1;
}
}
for (int i = 0; i < shortLength; i++) {
String thisA = thisSpanArr[i];
String otherA = otherSpanArr[i];
if (!thisA.equals(otherA)) {
return (Integer.parseInt(thisA) - Integer.parseInt(otherA));
}
}
return 0;
}
@Override
public int hashCode() {
int result = 17;
result = result * 31 + id.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Span)) {
return false;
}
Span that = (Span) obj;
return this.traceId.equals(that.traceId) && this.id.equals(that.id);
}
@JSONField(serialize = false)
public boolean isConsumerSide() {
for (Annotation a : getAnnotations()) {
if (a.getType() == AnnotationType.CLIENT_SEND || a.getType() == AnnotationType.CLIENT_RECEIVE) {
return true;
}
}
return false;
}
@JSONField(serialize = false)
public Endpoint getEndpoint() {
if (!annotations.isEmpty()) {
return annotations.get(0).getEndpoint();
}
return null;
}
public boolean addException(String className, String methodName, Throwable ex, Endpoint endpoint) {
this.hasException = true;
BinaryAnnotation exAnnotation = new BinaryAnnotation();
exAnnotation.setThrowable(className, methodName, ex);
exAnnotation.setEndpoint(endpoint);
addBinaryAnnotation(exAnnotation);
return true;
}
}