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