Coverage Report

Created: 2023-11-12 09:30

/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