Line data Source code
1 : #include "source/extensions/tracers/zipkin/tracer.h" 2 : 3 : #include <chrono> 4 : 5 : #include "source/common/common/utility.h" 6 : #include "source/common/tracing/http_tracer_impl.h" 7 : #include "source/extensions/tracers/zipkin/util.h" 8 : #include "source/extensions/tracers/zipkin/zipkin_core_constants.h" 9 : 10 : namespace Envoy { 11 : namespace Extensions { 12 : namespace Tracers { 13 : namespace Zipkin { 14 : 15 : SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name, 16 0 : SystemTime timestamp) { 17 : // Build the endpoint 18 0 : Endpoint ep(service_name_, address_); 19 : 20 : // Build the CS annotation 21 0 : Annotation cs; 22 0 : cs.setEndpoint(std::move(ep)); 23 0 : if (split_spans_for_request_) { 24 : // No previous context then this must be span created for downstream request. Server span will 25 : // be created for downstream request when split_spans_for_request is set to true 26 0 : cs.setValue(SERVER_RECV); 27 0 : } else { 28 0 : cs.setValue(config.operationName() == Tracing::OperationName::Egress ? CLIENT_SEND 29 0 : : SERVER_RECV); 30 0 : } 31 : // Create an all-new span, with no parent id 32 0 : SpanPtr span_ptr = std::make_unique<Span>(time_source_); 33 0 : span_ptr->setName(span_name); 34 0 : uint64_t random_number = random_generator_.random(); 35 0 : span_ptr->setId(random_number); 36 0 : span_ptr->setTraceId(random_number); 37 0 : if (trace_id_128bit_) { 38 0 : span_ptr->setTraceIdHigh(random_generator_.random()); 39 0 : } 40 0 : int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>( 41 0 : time_source_.monotonicTime().time_since_epoch()) 42 0 : .count(); 43 0 : span_ptr->setStartTime(start_time_micro); 44 : 45 : // Set the timestamp globally for the span and also for the CS annotation 46 0 : uint64_t timestamp_micro = 47 0 : std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count(); 48 0 : cs.setTimestamp(timestamp_micro); 49 0 : span_ptr->setTimestamp(timestamp_micro); 50 : 51 : // Add CS annotation to the span 52 0 : span_ptr->addAnnotation(std::move(cs)); 53 : 54 0 : span_ptr->setTracer(this); 55 : 56 0 : return span_ptr; 57 0 : } 58 : 59 : SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name, 60 0 : SystemTime timestamp, const SpanContext& previous_context) { 61 0 : SpanPtr span_ptr = std::make_unique<Span>(time_source_); 62 0 : Annotation annotation; 63 0 : uint64_t timestamp_micro; 64 : 65 0 : timestamp_micro = 66 0 : std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count(); 67 : 68 0 : span_ptr->setName(span_name); 69 : 70 : // Set the span's kind (client or server) 71 0 : if (split_spans_for_request_) { 72 : // If the previous context is an inner context then this span must be a span created for an 73 : // upstream request. A client span will be created for an upstream request. 74 0 : if (previous_context.innerContext()) { 75 0 : annotation.setValue(CLIENT_SEND); 76 0 : } else { 77 0 : annotation.setValue(SERVER_RECV); 78 0 : } 79 0 : } else { 80 0 : if (config.operationName() == Tracing::OperationName::Egress) { 81 0 : annotation.setValue(CLIENT_SEND); 82 0 : } else { 83 0 : annotation.setValue(SERVER_RECV); 84 0 : } 85 0 : } 86 : 87 : // Set the span's id and parent id 88 0 : if (annotation.value() == CLIENT_SEND || !shared_span_context_) { 89 : // We need to create a new span that is a child of the previous span; no shared context 90 : 91 : // Create a new span id 92 0 : uint64_t random_number = random_generator_.random(); 93 0 : span_ptr->setId(random_number); 94 : 95 : // Set the parent id to the id of the previous span 96 0 : span_ptr->setParentId(previous_context.id()); 97 : 98 : // Set the timestamp globally for the span 99 0 : span_ptr->setTimestamp(timestamp_micro); 100 0 : } else if (annotation.value() == SERVER_RECV) { 101 : // We need to create a new span that will share context with the previous span 102 : 103 : // Initialize the shared context for the new span 104 0 : span_ptr->setId(previous_context.id()); 105 0 : if (previous_context.parentId()) { 106 0 : span_ptr->setParentId(previous_context.parentId()); 107 0 : } 108 0 : } else { 109 0 : return span_ptr; // return an empty span 110 0 : } 111 : 112 : // Build the endpoint 113 0 : Endpoint ep(service_name_, address_); 114 : 115 : // Add the newly-created annotation to the span 116 0 : annotation.setEndpoint(std::move(ep)); 117 0 : annotation.setTimestamp(timestamp_micro); 118 0 : span_ptr->addAnnotation(std::move(annotation)); 119 : 120 : // Keep the same trace id 121 0 : span_ptr->setTraceId(previous_context.traceId()); 122 0 : if (previous_context.is128BitTraceId()) { 123 0 : span_ptr->setTraceIdHigh(previous_context.traceIdHigh()); 124 0 : } 125 : 126 : // Keep the same sampled flag 127 0 : span_ptr->setSampled(previous_context.sampled()); 128 : 129 0 : int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>( 130 0 : time_source_.monotonicTime().time_since_epoch()) 131 0 : .count(); 132 0 : span_ptr->setStartTime(start_time_micro); 133 : 134 0 : span_ptr->setTracer(this); 135 : 136 0 : return span_ptr; 137 0 : } 138 : 139 0 : void Tracer::reportSpan(Span&& span) { 140 0 : if (reporter_ && span.sampled()) { 141 0 : reporter_->reportSpan(std::move(span)); 142 0 : } 143 0 : } 144 : 145 0 : void Tracer::setReporter(ReporterPtr reporter) { reporter_ = std::move(reporter); } 146 : 147 : } // namespace Zipkin 148 : } // namespace Tracers 149 : } // namespace Extensions 150 : } // namespace Envoy