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