Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/extensions/tracers/datadog/span.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/tracers/datadog/span.h"
2
3
#include <utility>
4
5
#include "source/common/tracing/common_values.h"
6
#include "source/common/tracing/null_span_impl.h"
7
#include "source/extensions/tracers/datadog/time_util.h"
8
9
#include "absl/strings/str_cat.h"
10
#include "absl/strings/string_view.h"
11
#include "datadog/dict_writer.h"
12
#include "datadog/sampling_priority.h"
13
#include "datadog/span_config.h"
14
#include "datadog/trace_segment.h"
15
16
namespace Envoy {
17
namespace Extensions {
18
namespace Tracers {
19
namespace Datadog {
20
namespace {
21
22
class TraceContextWriter : public datadog::tracing::DictWriter {
23
public:
24
0
  explicit TraceContextWriter(Tracing::TraceContext& context) : context_(context) {}
25
26
0
  void set(datadog::tracing::StringView key, datadog::tracing::StringView value) override {
27
0
    context_.set(key, value);
28
0
  }
29
30
private:
31
  Tracing::TraceContext& context_;
32
};
33
34
} // namespace
35
36
0
Span::Span(datadog::tracing::Span&& span) : span_(std::move(span)) {}
37
38
0
const datadog::tracing::Optional<datadog::tracing::Span>& Span::impl() const { return span_; }
39
40
0
void Span::setOperation(absl::string_view operation) {
41
0
  if (!span_) {
42
0
    return;
43
0
  }
44
45
  // What Envoy calls the operation name more closely corresponds to what
46
  // Datadog calls the resource name.
47
0
  span_->set_resource_name(operation);
48
0
}
49
50
0
void Span::setTag(absl::string_view name, absl::string_view value) {
51
0
  if (!span_) {
52
0
    return;
53
0
  }
54
55
0
  const auto& Tags = Envoy::Tracing::Tags::get();
56
57
0
  if (name == "resource.name") {
58
    // The special "resource.name" tag is a holdover from when the Datadog
59
    // tracer was OpenTracing-based, and so there was no way to set the Datadog
60
    // resource name directly.
61
    // In Envoy, it's still the case that there's no way to set the Datadog
62
    // resource name directly; so, here if the tag name is "resource.name", we
63
    // actually set the resource name instead of setting a tag.
64
0
    span_->set_resource_name(value);
65
0
  } else if (name == Tags.Error) {
66
    // Envoy marks spans as containing errors by setting the "error" tag.
67
    // Here we translate into the dd-trace-cpp equivalent.
68
0
    if (value == Tags.True) {
69
0
      span_->set_error(true);
70
0
    }
71
0
  } else if (name == Tags.ErrorReason) {
72
    // Envoy conveys information about an error by setting the "error.reason"
73
    // tag.
74
    // Here we translate into the dd-trace-cpp equivalent.
75
0
    span_->set_error_message(value);
76
0
    span_->set_tag(name, value);
77
0
  } else {
78
0
    span_->set_tag(name, value);
79
0
  }
80
0
}
81
82
0
void Span::log(SystemTime, const std::string&) {
83
  // Datadog spans don't have in-bound "events" or "logs".
84
0
}
85
86
0
void Span::finishSpan() { span_.reset(); }
87
88
0
void Span::injectContext(Tracing::TraceContext& trace_context, const Tracing::UpstreamContext&) {
89
0
  if (!span_) {
90
0
    return;
91
0
  }
92
93
0
  TraceContextWriter writer{trace_context};
94
0
  span_->inject(writer);
95
0
}
96
97
Tracing::SpanPtr Span::spawnChild(const Tracing::Config&, const std::string& name,
98
0
                                  SystemTime start_time) {
99
0
  if (!span_) {
100
    // I don't expect this to happen. This means that `spawnChild` was called
101
    // after `finishSpan`.
102
0
    return std::make_unique<Tracing::NullSpan>();
103
0
  }
104
105
  // The OpenTracing implementation ignored the `Tracing::Config` argument,
106
  // so we will as well.
107
  // The `name` parameter to this function more closely matches Datadog's
108
  // concept of "resource name." Datadog's "span name," or "operation name,"
109
  // instead describes the category of operation being performed, which here
110
  // we hard-code.
111
0
  datadog::tracing::SpanConfig config;
112
0
  config.name = "envoy.proxy";
113
0
  config.resource = name;
114
0
  config.start = estimateTime(start_time);
115
116
0
  return std::make_unique<Span>(span_->create_child(config));
117
0
}
118
119
0
void Span::setSampled(bool sampled) {
120
0
  if (!span_) {
121
0
    return;
122
0
  }
123
124
0
  auto priority = static_cast<int>(sampled ? datadog::tracing::SamplingPriority::USER_KEEP
125
0
                                           : datadog::tracing::SamplingPriority::USER_DROP);
126
0
  span_->trace_segment().override_sampling_priority(priority);
127
0
}
128
129
0
std::string Span::getBaggage(absl::string_view) {
130
  // not implemented
131
0
  return EMPTY_STRING;
132
0
}
133
134
0
void Span::setBaggage(absl::string_view, absl::string_view) {
135
  // not implemented
136
0
}
137
138
0
std::string Span::getTraceId() const {
139
0
  if (!span_) {
140
0
    return EMPTY_STRING;
141
0
  }
142
0
  return absl::StrCat(absl::Hex(span_->id()));
143
0
}
144
145
0
std::string Span::getSpanId() const {
146
  // TODO(#34412): This method is not yet implemented for Datadog.
147
0
  return EMPTY_STRING;
148
0
}
149
150
} // namespace Datadog
151
} // namespace Tracers
152
} // namespace Extensions
153
} // namespace Envoy