/proc/self/cwd/source/extensions/tracers/zipkin/tracer.cc
Line | Count | Source (jump to first uncovered line) |
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 | | /** |
16 | | * @param spawn_child_span whether the Envoy will spawn a child span for the request. This |
17 | | * means that the Envoy will be treated as an independent hop in the trace chain. |
18 | | * See |
19 | | * https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/observability/tracing#different-modes-of-envoy |
20 | | * for more details. |
21 | | * @param upstream whether the span is span for an upstream request. |
22 | | * @param direction the direction of the traffic that the span is for. Egress means |
23 | | * the span is for an outgoing request, and Ingress means the span is for an incoming request. |
24 | | */ |
25 | 0 | Annotation getAnnotation(bool spawn_child_span, bool upstream, Tracing::OperationName direction) { |
26 | 0 | Annotation annotation; |
27 | 0 | if (spawn_child_span) { |
28 | | // Spawn child span is set to true and Envoy should be treated as an independent hop in the |
29 | | // trace chain. Determine the span type based on the request type. |
30 | | |
31 | | // Create server span for downstream request and client span for upstream request. |
32 | 0 | annotation.setValue(upstream ? CLIENT_SEND : SERVER_RECV); |
33 | 0 | } else { |
34 | | // Spawn child span is set to false and Envoy should not be treated as an independent hop in the |
35 | | // trace chain. Determine the span type based on the traffic direction. |
36 | | |
37 | | // Create server span for inbound sidecar and client span for outbound sidecar. |
38 | 0 | annotation.setValue(direction == Tracing::OperationName::Egress ? CLIENT_SEND : SERVER_RECV); |
39 | 0 | } |
40 | |
|
41 | 0 | return annotation; |
42 | 0 | } |
43 | | |
44 | | SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name, |
45 | 0 | SystemTime timestamp) { |
46 | | // Build the endpoint |
47 | 0 | Endpoint ep(service_name_, address_); |
48 | | |
49 | | // Build the CS annotation. |
50 | | // No previous context then this must be span created for downstream request for now. |
51 | 0 | Annotation cs = getAnnotation(split_spans_for_request_ || config.spawnUpstreamSpan(), false, |
52 | 0 | config.operationName()); |
53 | 0 | cs.setEndpoint(std::move(ep)); |
54 | | |
55 | | // Create an all-new span, with no parent id |
56 | 0 | SpanPtr span_ptr = std::make_unique<Span>(time_source_); |
57 | 0 | span_ptr->setName(span_name); |
58 | 0 | uint64_t random_number = random_generator_.random(); |
59 | 0 | span_ptr->setId(random_number); |
60 | 0 | span_ptr->setTraceId(random_number); |
61 | 0 | if (trace_id_128bit_) { |
62 | 0 | span_ptr->setTraceIdHigh(random_generator_.random()); |
63 | 0 | } |
64 | 0 | int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>( |
65 | 0 | time_source_.monotonicTime().time_since_epoch()) |
66 | 0 | .count(); |
67 | 0 | span_ptr->setStartTime(start_time_micro); |
68 | | |
69 | | // Set the timestamp globally for the span and also for the CS annotation |
70 | 0 | uint64_t timestamp_micro = |
71 | 0 | std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count(); |
72 | 0 | cs.setTimestamp(timestamp_micro); |
73 | 0 | span_ptr->setTimestamp(timestamp_micro); |
74 | | |
75 | | // Add CS annotation to the span |
76 | 0 | span_ptr->addAnnotation(std::move(cs)); |
77 | |
|
78 | 0 | span_ptr->setTracer(this); |
79 | |
|
80 | 0 | return span_ptr; |
81 | 0 | } |
82 | | |
83 | | SpanPtr Tracer::startSpan(const Tracing::Config& config, const std::string& span_name, |
84 | 0 | SystemTime timestamp, const SpanContext& previous_context) { |
85 | 0 | SpanPtr span_ptr = std::make_unique<Span>(time_source_); |
86 | | // If the previous context is inner context then this span is span for upstream request. |
87 | 0 | Annotation annotation = getAnnotation(split_spans_for_request_ || config.spawnUpstreamSpan(), |
88 | 0 | previous_context.innerContext(), config.operationName()); |
89 | 0 | uint64_t timestamp_micro; |
90 | |
|
91 | 0 | timestamp_micro = |
92 | 0 | std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count(); |
93 | |
|
94 | 0 | span_ptr->setName(span_name); |
95 | | |
96 | | // Set the span's id and parent id |
97 | 0 | if (annotation.value() == CLIENT_SEND || !shared_span_context_) { |
98 | | // We need to create a new span that is a child of the previous span; no shared context |
99 | | |
100 | | // Create a new span id |
101 | 0 | uint64_t random_number = random_generator_.random(); |
102 | 0 | span_ptr->setId(random_number); |
103 | | |
104 | | // Set the parent id to the id of the previous span |
105 | 0 | span_ptr->setParentId(previous_context.id()); |
106 | | |
107 | | // Set the timestamp globally for the span |
108 | 0 | span_ptr->setTimestamp(timestamp_micro); |
109 | 0 | } else if (annotation.value() == SERVER_RECV) { |
110 | | // We need to create a new span that will share context with the previous span |
111 | | |
112 | | // Initialize the shared context for the new span |
113 | 0 | span_ptr->setId(previous_context.id()); |
114 | 0 | if (previous_context.parentId()) { |
115 | 0 | span_ptr->setParentId(previous_context.parentId()); |
116 | 0 | } |
117 | 0 | } else { |
118 | 0 | return span_ptr; // return an empty span |
119 | 0 | } |
120 | | |
121 | | // Build the endpoint |
122 | 0 | Endpoint ep(service_name_, address_); |
123 | | |
124 | | // Add the newly-created annotation to the span |
125 | 0 | annotation.setEndpoint(std::move(ep)); |
126 | 0 | annotation.setTimestamp(timestamp_micro); |
127 | 0 | span_ptr->addAnnotation(std::move(annotation)); |
128 | | |
129 | | // Keep the same trace id |
130 | 0 | span_ptr->setTraceId(previous_context.traceId()); |
131 | 0 | if (previous_context.is128BitTraceId()) { |
132 | 0 | span_ptr->setTraceIdHigh(previous_context.traceIdHigh()); |
133 | 0 | } |
134 | | |
135 | | // Keep the same sampled flag |
136 | 0 | span_ptr->setSampled(previous_context.sampled()); |
137 | |
|
138 | 0 | int64_t start_time_micro = std::chrono::duration_cast<std::chrono::microseconds>( |
139 | 0 | time_source_.monotonicTime().time_since_epoch()) |
140 | 0 | .count(); |
141 | 0 | span_ptr->setStartTime(start_time_micro); |
142 | |
|
143 | 0 | span_ptr->setTracer(this); |
144 | |
|
145 | 0 | return span_ptr; |
146 | 0 | } |
147 | | |
148 | 0 | void Tracer::reportSpan(Span&& span) { |
149 | 0 | if (reporter_ && span.sampled()) { |
150 | 0 | reporter_->reportSpan(std::move(span)); |
151 | 0 | } |
152 | 0 | } |
153 | | |
154 | 0 | void Tracer::setReporter(ReporterPtr reporter) { reporter_ = std::move(reporter); } |
155 | | |
156 | | } // namespace Zipkin |
157 | | } // namespace Tracers |
158 | | } // namespace Extensions |
159 | | } // namespace Envoy |