1 module hunt.trace.Span;
2
3 import hunt.trace.Endpoint;
4 import hunt.trace.Constrants;
5 import hunt.trace.Annotation;
6 import hunt.trace.Helpers;
7
8 import hunt.logging;
9 import hunt.serialization.JsonSerializer;
10 import hunt.serialization.Common;
11
12 import std.json;
13 import std.range;
14 import std.socket;
15 import std.string;
16
17 /**
18 *
19 */
20 class Span {
21
22 /// 16bytes
23 string traceId;
24 string name;
25 @Ignore string parentId;
26 /// 8bytes
27 string id;
28 string kind;
29 long timestamp;
30 long duration;
31 @Ignore bool debug_;
32 @Ignore bool shared_;
33
34 EndPoint localEndpoint;
35 EndPoint remoteEndpoint;
36 Annotation[] annotations;
37 string[string] tags;
38
39 string samplingState = "1";
40
41 string defaultId() {
42 // b3={TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
43 if(parentId.empty) {
44 return traceId ~ "-" ~ id ~ "-" ~ samplingState;
45 } else {
46 return traceId ~ "-" ~ id ~ "-" ~ samplingState ~ "-" ~ parentId;
47 }
48 }
49
50 void addTag(string key, string value) {
51 tags[key] = value;
52 }
53
54 void addAnnotation(string value, long timestamp = 0) {
55 auto anno = new Annotation();
56 anno.value = value;
57 if (timestamp == 0)
58 timestamp = usecs;
59 anno.timestamp = timestamp;
60 annotations ~= anno;
61 }
62
63 void start(long timestamp = 0) {
64 if (timestamp != 0)
65 this.timestamp = timestamp;
66 else
67 this.timestamp = usecs;
68 }
69
70 void finish(long timestamp = 0) {
71 if (timestamp != 0)
72 this.duration = timestamp - this.timestamp;
73 else
74 this.duration = usecs - this.timestamp;
75
76 }
77
78 static EndPoint buildLocalEndPoint(string name) {
79 EndPoint endpoint = new EndPoint();
80 endpoint.serviceName = name;
81
82 try {
83 auto addresses = getAddress("localhost");
84 foreach (address; addresses) {
85 // writefln(" IP: %s", address.toAddrString());
86 string ip = address.toAddrString();
87 if(ip.startsWith("::")) {
88 // localEndpoint.ipv6 = ip; // todo
89 } else {
90 endpoint.ipv4 = ip;
91 }
92 }
93 } catch(Exception ex) {
94 warning(ex.msg);
95 }
96
97 return endpoint;
98 }
99
100 override string toString() {
101 auto json = toJson(this);
102 json["debug"] = (debug_);
103 json["shared"] = (shared_);
104
105 // import hunt.logging;
106 // warning("parentId: ", parentId);
107 // warning("traceId: ", traceId);
108 if (parentId.length != 0)
109 json["parentId"] = parentId;
110 return json.toString;
111 }
112 }
113
114
115
116 void traceSpanAfter(Span span, string[string] tags, string error = "") {
117 assert(span !is null);
118
119 foreach (k, v; tags) {
120 span.addTag(k, v);
121 }
122
123 if (error != "") {
124 span.addTag(SPAN_ERROR, error);
125 }
126 span.finish();
127
128 // warning(span.toString());
129 }