/proc/self/cwd/source/extensions/tracers/datadog/tracer.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/extensions/tracers/datadog/tracer.h" |
2 | | |
3 | | #include <memory> |
4 | | #include <utility> |
5 | | |
6 | | #include "envoy/tracing/trace_context.h" |
7 | | |
8 | | #include "source/common/common/assert.h" |
9 | | #include "source/common/config/utility.h" |
10 | | #include "source/common/tracing/null_span_impl.h" |
11 | | #include "source/extensions/tracers/datadog/agent_http_client.h" |
12 | | #include "source/extensions/tracers/datadog/dict_util.h" |
13 | | #include "source/extensions/tracers/datadog/event_scheduler.h" |
14 | | #include "source/extensions/tracers/datadog/logger.h" |
15 | | #include "source/extensions/tracers/datadog/span.h" |
16 | | #include "source/extensions/tracers/datadog/time_util.h" |
17 | | |
18 | | #include "datadog/dict_reader.h" |
19 | | #include "datadog/error.h" |
20 | | #include "datadog/sampling_priority.h" |
21 | | #include "datadog/span_config.h" |
22 | | #include "datadog/trace_segment.h" |
23 | | #include "datadog/tracer_config.h" |
24 | | |
25 | | namespace Envoy { |
26 | | namespace Extensions { |
27 | | namespace Tracers { |
28 | | namespace Datadog { |
29 | | namespace { |
30 | | |
31 | | std::shared_ptr<Tracer::ThreadLocalTracer> makeThreadLocalTracer( |
32 | | datadog::tracing::TracerConfig config, Upstream::ClusterManager& cluster_manager, |
33 | | const std::string& collector_cluster, const std::string& collector_reference_host, |
34 | | TracerStats& tracer_stats, Event::Dispatcher& dispatcher, spdlog::logger& logger, |
35 | 0 | TimeSource& time_source) { |
36 | 0 | config.logger = std::make_shared<Logger>(logger); |
37 | 0 | config.agent.event_scheduler = std::make_shared<EventScheduler>(dispatcher); |
38 | 0 | config.agent.http_client = std::make_shared<AgentHTTPClient>( |
39 | 0 | cluster_manager, collector_cluster, collector_reference_host, tracer_stats, time_source); |
40 | |
|
41 | 0 | datadog::tracing::Expected<datadog::tracing::FinalizedTracerConfig> maybe_config = |
42 | 0 | datadog::tracing::finalize_config(config); |
43 | 0 | if (datadog::tracing::Error* error = maybe_config.if_error()) { |
44 | 0 | datadog::tracing::StringView prefix = |
45 | 0 | "Unable to configure Datadog tracer. Tracing is now disabled. Error: "; |
46 | 0 | config.logger->log_error(error->with_prefix(prefix)); |
47 | 0 | return std::make_shared<Tracer::ThreadLocalTracer>(); |
48 | 0 | } |
49 | | |
50 | 0 | return std::make_shared<Tracer::ThreadLocalTracer>(*maybe_config); |
51 | 0 | } |
52 | | |
53 | | } // namespace |
54 | | |
55 | | Tracer::ThreadLocalTracer::ThreadLocalTracer(const datadog::tracing::FinalizedTracerConfig& config) |
56 | 0 | : tracer(config) {} |
57 | | |
58 | | Tracer::Tracer(const std::string& collector_cluster, const std::string& collector_reference_host, |
59 | | const datadog::tracing::TracerConfig& config, |
60 | | Upstream::ClusterManager& cluster_manager, Stats::Scope& scope, |
61 | | ThreadLocal::SlotAllocator& thread_local_slot_allocator, TimeSource& time_source) |
62 | | : tracer_stats_(makeTracerStats(scope)), |
63 | | thread_local_slot_( |
64 | 0 | ThreadLocal::TypedSlot<ThreadLocalTracer>::makeUnique(thread_local_slot_allocator)) { |
65 | 0 | const bool allow_added_via_api = true; |
66 | 0 | THROW_IF_NOT_OK_REF(Config::Utility::checkCluster("envoy.tracers.datadog", collector_cluster, |
67 | 0 | cluster_manager, allow_added_via_api) |
68 | 0 | .status()); |
69 | | |
70 | 0 | thread_local_slot_->set([&logger = ENVOY_LOGGER(), collector_cluster, collector_reference_host, |
71 | 0 | config, &tracer_stats = tracer_stats_, &cluster_manager, |
72 | 0 | &time_source](Event::Dispatcher& dispatcher) { |
73 | 0 | return makeThreadLocalTracer(config, cluster_manager, collector_cluster, |
74 | 0 | collector_reference_host, tracer_stats, dispatcher, logger, |
75 | 0 | time_source); |
76 | 0 | }); |
77 | 0 | } |
78 | | |
79 | | // Tracer::TracingDriver |
80 | | |
81 | | Tracing::SpanPtr Tracer::startSpan(const Tracing::Config&, Tracing::TraceContext& trace_context, |
82 | | const StreamInfo::StreamInfo& stream_info, |
83 | | const std::string& operation_name, |
84 | 0 | Tracing::Decision tracing_decision) { |
85 | 0 | ThreadLocalTracer& thread_local_tracer = **thread_local_slot_; |
86 | 0 | if (!thread_local_tracer.tracer) { |
87 | 0 | return std::make_unique<Tracing::NullSpan>(); |
88 | 0 | } |
89 | | |
90 | | // The OpenTracing implementation ignored the `Tracing::Config` argument, |
91 | | // so we will as well. |
92 | 0 | datadog::tracing::SpanConfig span_config; |
93 | | // The `operation_name` parameter to this function more closely matches |
94 | | // Datadog's concept of "resource name." Datadog's "span name," or "operation |
95 | | // name," instead describes the category of operation being performed, which |
96 | | // here we hard-code. |
97 | 0 | span_config.name = "envoy.proxy"; |
98 | 0 | span_config.resource = operation_name; |
99 | 0 | span_config.start = estimateTime(stream_info.startTime()); |
100 | |
|
101 | 0 | TraceContextReader reader{trace_context}; |
102 | 0 | datadog::tracing::Span span = |
103 | 0 | extractOrCreateSpan(*thread_local_tracer.tracer, span_config, reader); |
104 | | |
105 | | // If we did not extract a sampling decision, and if Envoy is telling us to |
106 | | // drop the trace, then we treat that as a "user drop" (manual override). |
107 | | // |
108 | | // If Envoy is telling us to keep the trace, then we leave it up to the |
109 | | // tracer's internal sampler (which might decide to drop the trace anyway). |
110 | 0 | if (!span.trace_segment().sampling_decision().has_value() && !tracing_decision.traced) { |
111 | 0 | span.trace_segment().override_sampling_priority( |
112 | 0 | int(datadog::tracing::SamplingPriority::USER_DROP)); |
113 | 0 | } |
114 | |
|
115 | 0 | return std::make_unique<Span>(std::move(span)); |
116 | 0 | } |
117 | | |
118 | | datadog::tracing::Span Tracer::extractOrCreateSpan(datadog::tracing::Tracer& tracer, |
119 | | const datadog::tracing::SpanConfig& span_config, |
120 | 0 | const datadog::tracing::DictReader& reader) { |
121 | 0 | datadog::tracing::Expected<datadog::tracing::Span> maybe_span = |
122 | 0 | tracer.extract_span(reader, span_config); |
123 | 0 | if (datadog::tracing::Error* error = maybe_span.if_error()) { |
124 | | // We didn't extract a span. Either there's no span to extract, or an |
125 | | // error occurred during extraction. |
126 | | // |
127 | | // Either way, we're going to create a new root span, but if an error |
128 | | // occurred we're going to log the error. |
129 | 0 | if (error->code != datadog::tracing::Error::NO_SPAN_TO_EXTRACT) { |
130 | 0 | ENVOY_LOG( |
131 | 0 | error, |
132 | 0 | "Unable to extract span context. Creating a new trace instead. Error [error {}]: {}", |
133 | 0 | int(error->code), error->message); |
134 | 0 | } |
135 | |
|
136 | 0 | return tracer.create_span(span_config); |
137 | 0 | } |
138 | | |
139 | 0 | return std::move(*maybe_span); |
140 | 0 | } |
141 | | |
142 | | } // namespace Datadog |
143 | | } // namespace Tracers |
144 | | } // namespace Extensions |
145 | | } // namespace Envoy |