/proc/self/cwd/source/extensions/tracers/xray/tracer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <string> |
4 | | #include <utility> |
5 | | #include <vector> |
6 | | |
7 | | #include "envoy/common/time.h" |
8 | | #include "envoy/tracing/tracer.h" |
9 | | |
10 | | #include "source/common/common/empty_string.h" |
11 | | #include "source/common/common/hex.h" |
12 | | #include "source/common/common/random_generator.h" |
13 | | #include "source/common/http/codes.h" |
14 | | #include "source/common/protobuf/utility.h" |
15 | | #include "source/common/tracing/common_values.h" |
16 | | #include "source/common/tracing/trace_context_impl.h" |
17 | | #include "source/extensions/tracers/xray/daemon_broker.h" |
18 | | #include "source/extensions/tracers/xray/sampling_strategy.h" |
19 | | #include "source/extensions/tracers/xray/xray_configuration.h" |
20 | | |
21 | | #include "absl/container/flat_hash_map.h" |
22 | | #include "absl/strings/string_view.h" |
23 | | |
24 | | namespace Envoy { |
25 | | namespace Extensions { |
26 | | namespace Tracers { |
27 | | namespace XRay { |
28 | | |
29 | | constexpr absl::string_view SpanClientIp = "client_ip"; |
30 | | constexpr absl::string_view SpanXForwardedFor = "x_forwarded_for"; |
31 | | constexpr absl::string_view Subsegment = "subsegment"; |
32 | | |
33 | | const Tracing::TraceContextHandler& xRayTraceHeader(); |
34 | | const Tracing::TraceContextHandler& xForwardedForHeader(); |
35 | | |
36 | | class Span : public Tracing::Span, Logger::Loggable<Logger::Id::config> { |
37 | | public: |
38 | | /** |
39 | | * Creates a new Span. |
40 | | * |
41 | | * @param time_source A time source to get the span end time |
42 | | * @param random random generator for generating unique child span ids |
43 | | * @param broker Facilitates communication with the X-Ray daemon. |
44 | | */ |
45 | | Span(TimeSource& time_source, Random::RandomGenerator& random, DaemonBroker& broker) |
46 | | : time_source_(time_source), random_(random), broker_(broker), |
47 | 0 | id_(Hex::uint64ToHex(random_.random())) {} |
48 | | |
49 | | /** |
50 | | * Sets the Span's trace ID. |
51 | | */ |
52 | 0 | void setTraceId(absl::string_view trace_id) { trace_id_ = std::string(trace_id); }; |
53 | | |
54 | | /** |
55 | | * Gets the Span's trace ID. |
56 | | */ |
57 | 0 | const std::string& traceId() const { return trace_id_; } |
58 | | |
59 | | /** |
60 | | * Completes the current span, serialize it and send it to the X-Ray daemon. |
61 | | */ |
62 | | void finishSpan() override; |
63 | | |
64 | | /** |
65 | | * Sets the current operation name on the Span. |
66 | | * This information will be included in the X-Ray span's metadata. |
67 | | */ |
68 | 0 | void setOperation(absl::string_view operation) override { |
69 | 0 | operation_name_ = std::string(operation); |
70 | 0 | } |
71 | | |
72 | | /** |
73 | | * Sets the current direction on the Span. |
74 | | * This information will be included in the X-Ray span's annotation. |
75 | | */ |
76 | 0 | void setDirection(absl::string_view direction) { direction_ = std::string(direction); } |
77 | | |
78 | | /** |
79 | | * Sets the name of the Span. |
80 | | */ |
81 | 0 | void setName(absl::string_view name) { name_ = std::string(name); } |
82 | | |
83 | | /** |
84 | | * Sets the origin of the Span. |
85 | | */ |
86 | 0 | void setOrigin(absl::string_view origin) { origin_ = std::string(origin); } |
87 | | |
88 | | /** |
89 | | * Gets the origin of the Span. |
90 | | */ |
91 | 0 | const std::string& origin() { return origin_; } |
92 | | |
93 | | /** |
94 | | * Adds a key-value pair to either the Span's annotations or metadata. |
95 | | * An allowlist of keys are added to the annotations, everything else is added to the metadata. |
96 | | */ |
97 | | void setTag(absl::string_view name, absl::string_view value) override; |
98 | | |
99 | | /** |
100 | | * Sets the ID of the parent segment. This is different from the Trace ID. |
101 | | * The parent ID is used if the request originated from an instrumented application. |
102 | | * For more information see: |
103 | | * https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader |
104 | | */ |
105 | 0 | void setParentId(absl::string_view parent_segment_id) { |
106 | 0 | parent_segment_id_ = std::string(parent_segment_id); |
107 | 0 | } |
108 | | |
109 | | /** |
110 | | * Sets the type of the Span. In X-Ray, an independent subsegment has a type of "subsegment". |
111 | | * https://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html#api-segmentdocuments-subsegments |
112 | | */ |
113 | 0 | void setType(absl::string_view type) { type_ = std::string(type); } |
114 | | |
115 | | /** |
116 | | * Sets the aws metadata field of the Span. |
117 | | */ |
118 | 0 | void setAwsMetadata(const absl::flat_hash_map<std::string, ProtobufWkt::Value>& aws_metadata) { |
119 | 0 | aws_metadata_ = aws_metadata; |
120 | 0 | } |
121 | | |
122 | | /* |
123 | | * Adds to the http request annotation field of the Span. |
124 | | */ |
125 | 0 | void addToHttpRequestAnnotations(absl::string_view key, const ProtobufWkt::Value& value) { |
126 | 0 | http_request_annotations_.emplace(std::string(key), value); |
127 | 0 | } |
128 | | |
129 | | /* |
130 | | * Check if key is set in http request annotation field of a Span. |
131 | | */ |
132 | 0 | bool hasKeyInHttpRequestAnnotations(absl::string_view key) { |
133 | 0 | return http_request_annotations_.find(key) != http_request_annotations_.end(); |
134 | 0 | } |
135 | | |
136 | | /* |
137 | | * Adds to the http response annotation field of the Span. |
138 | | */ |
139 | 0 | void addToHttpResponseAnnotations(absl::string_view key, const ProtobufWkt::Value& value) { |
140 | 0 | http_response_annotations_.emplace(std::string(key), value); |
141 | 0 | } |
142 | | |
143 | | /** |
144 | | * Sets the recording start time of the traced operation/request. |
145 | | */ |
146 | 0 | void setStartTime(Envoy::SystemTime start_time) { start_time_ = start_time; } |
147 | | |
148 | | /** |
149 | | * Marks the span as either "sampled" or "not-sampled". |
150 | | * By default, Spans are "sampled". |
151 | | * This is handy in cases where the sampling decision has already been determined either by Envoy |
152 | | * or by a downstream service. |
153 | | */ |
154 | 0 | void setSampled(bool sampled) override { sampled_ = sampled; }; |
155 | | |
156 | | /** |
157 | | * Sets the server error as true for the traced operation/request. |
158 | | */ |
159 | 0 | void setServerError() { server_error_ = true; }; |
160 | | |
161 | | /** |
162 | | * Sets the http response status code for the traced operation/request. |
163 | | */ |
164 | 0 | void setResponseStatusCode(uint64_t status_code) { response_status_code_ = status_code; }; |
165 | | |
166 | | /** |
167 | | * Adds X-Ray trace header to the set of outgoing headers. |
168 | | */ |
169 | | void injectContext(Tracing::TraceContext& trace_context, |
170 | | const Tracing::UpstreamContext&) override; |
171 | | |
172 | | /** |
173 | | * Gets the start time of this Span. |
174 | | */ |
175 | 0 | Envoy::SystemTime startTime() const { return start_time_; } |
176 | | |
177 | | /** |
178 | | * Gets this Span's ID. |
179 | | */ |
180 | 0 | const std::string& id() const { return id_; } |
181 | | |
182 | | /** |
183 | | * Gets this Span's parent ID. |
184 | | */ |
185 | 0 | const std::string& parentId() const { return parent_segment_id_; } |
186 | | |
187 | | /** |
188 | | * Gets this Span's direction. |
189 | | */ |
190 | 0 | const std::string& direction() const { return direction_; } |
191 | | |
192 | | /** |
193 | | * Gets this Span's type. |
194 | | */ |
195 | 0 | const std::string& type() const { return type_; } |
196 | | |
197 | | /** |
198 | | * Gets this Span's name. |
199 | | */ |
200 | 0 | const std::string& name() const { return name_; } |
201 | | |
202 | | /** |
203 | | * Determines whether this span is sampled. |
204 | | */ |
205 | 0 | bool sampled() const { return sampled_; } |
206 | | |
207 | | /** |
208 | | * Determines if a server error occurred (response status code was 5XX Server Error). |
209 | | */ |
210 | 0 | bool serverError() const { return server_error_; } |
211 | | |
212 | | /** |
213 | | * Determines if a client error occurred (response status code was 4XX Client Error). |
214 | | */ |
215 | 0 | bool clientError() const { return Http::CodeUtility::is4xx(response_status_code_); } |
216 | | |
217 | | /** |
218 | | * Determines if a request was throttled (response status code was 429 Too Many Requests). |
219 | | */ |
220 | 0 | bool isThrottled() const { |
221 | 0 | return Http::Code::TooManyRequests == static_cast<Http::Code>(response_status_code_); |
222 | 0 | } |
223 | | |
224 | | /** |
225 | | * Not used by X-Ray because the Spans are "logged" (serialized) to the X-Ray daemon. |
226 | | */ |
227 | 0 | void log(Envoy::SystemTime, const std::string&) override {} |
228 | | |
229 | | // X-Ray doesn't support baggage, so noop these OpenTracing functions. |
230 | 0 | void setBaggage(absl::string_view, absl::string_view) override {} |
231 | 0 | std::string getBaggage(absl::string_view) override { return EMPTY_STRING; } |
232 | | |
233 | 0 | std::string getTraceId() const override { return trace_id_; }; |
234 | | |
235 | | // TODO(#34412): This method is unimplemented for X-Ray. |
236 | 0 | std::string getSpanId() const override { return EMPTY_STRING; }; |
237 | | |
238 | | /** |
239 | | * Creates a child span. |
240 | | * In X-Ray terms this creates a sub-segment and sets its parent ID to the current span's ID. |
241 | | * @param operation_name The span of the child span. |
242 | | * @param start_time The time at which this child span started. |
243 | | */ |
244 | | Tracing::SpanPtr spawnChild(const Tracing::Config&, const std::string& operation_name, |
245 | | Envoy::SystemTime start_time) override; |
246 | | |
247 | | private: |
248 | | Envoy::TimeSource& time_source_; |
249 | | Random::RandomGenerator& random_; |
250 | | DaemonBroker& broker_; |
251 | | Envoy::SystemTime start_time_; |
252 | | std::string operation_name_; |
253 | | std::string direction_; |
254 | | std::string id_; |
255 | | std::string trace_id_; |
256 | | std::string parent_segment_id_; |
257 | | std::string name_; |
258 | | std::string origin_; |
259 | | std::string type_; |
260 | | absl::flat_hash_map<std::string, ProtobufWkt::Value> aws_metadata_; |
261 | | absl::flat_hash_map<std::string, ProtobufWkt::Value> http_request_annotations_; |
262 | | absl::flat_hash_map<std::string, ProtobufWkt::Value> http_response_annotations_; |
263 | | absl::flat_hash_map<std::string, std::string> custom_annotations_; |
264 | | bool server_error_{false}; |
265 | | uint64_t response_status_code_{0}; |
266 | | bool sampled_{true}; |
267 | | }; |
268 | | |
269 | | using SpanPtr = std::unique_ptr<Span>; |
270 | | |
271 | | class Tracer { |
272 | | public: |
273 | | Tracer(absl::string_view segment_name, absl::string_view origin, |
274 | | const absl::flat_hash_map<std::string, ProtobufWkt::Value>& aws_metadata, |
275 | | DaemonBrokerPtr daemon_broker, TimeSource& time_source, Random::RandomGenerator& random) |
276 | | : segment_name_(segment_name), origin_(origin), aws_metadata_(aws_metadata), |
277 | 0 | daemon_broker_(std::move(daemon_broker)), time_source_(time_source), random_(random) {} |
278 | | /** |
279 | | * Starts a tracing span for X-Ray |
280 | | */ |
281 | | Tracing::SpanPtr startSpan(const Tracing::Config&, const std::string& operation_name, |
282 | | Envoy::SystemTime start_time, |
283 | | const absl::optional<XRayHeader>& xray_header, |
284 | | const absl::optional<absl::string_view> client_ip); |
285 | | /** |
286 | | * Creates a Span that is marked as not-sampled. |
287 | | * This is useful when the sampling decision is done in Envoy's X-Ray and we want to avoid |
288 | | * overruling that decision in the upstream service in case that service itself uses X-Ray for |
289 | | * tracing. Also at the same time if X-Ray header is set then preserve its value. |
290 | | */ |
291 | | XRay::SpanPtr createNonSampledSpan(const absl::optional<XRayHeader>& xray_header) const; |
292 | | |
293 | | private: |
294 | | const std::string segment_name_; |
295 | | const std::string origin_; |
296 | | const absl::flat_hash_map<std::string, ProtobufWkt::Value> aws_metadata_; |
297 | | const DaemonBrokerPtr daemon_broker_; |
298 | | Envoy::TimeSource& time_source_; |
299 | | Random::RandomGenerator& random_; |
300 | | }; |
301 | | |
302 | | using TracerPtr = std::unique_ptr<Tracer>; |
303 | | |
304 | | } // namespace XRay |
305 | | } // namespace Tracers |
306 | | } // namespace Extensions |
307 | | } // namespace Envoy |