/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 |