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