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 }