@@ -24,180 +24,128 @@ namespace datadog {
2424namespace tracing {
2525namespace {
2626
27- class ExtractionPolicy {
28- public:
29- virtual Expected<Optional<std::uint64_t >> trace_id (
30- const DictReader& headers) = 0;
31- virtual Expected<Optional<std::uint64_t >> parent_id (
32- const DictReader& headers) = 0;
33- virtual Expected<Optional<int >> sampling_priority (
34- const DictReader& headers) = 0;
35- virtual Optional<std::string> origin (const DictReader& headers) = 0;
36- virtual Optional<std::string> trace_tags (const DictReader&) = 0;
27+ Expected<Optional<std::uint64_t >> extract_id_header (const DictReader& headers,
28+ StringView header,
29+ StringView header_kind,
30+ StringView style_name,
31+ int base) {
32+ auto found = headers.lookup (header);
33+ if (!found) {
34+ return nullopt ;
35+ }
36+ auto result = parse_uint64 (*found, base);
37+ if (auto * error = result.if_error ()) {
38+ std::string prefix;
39+ prefix += " Could not extract " ;
40+ append (prefix, style_name);
41+ prefix += " -style " ;
42+ append (prefix, header_kind);
43+ prefix += " ID from " ;
44+ append (prefix, header);
45+ prefix += " : " ;
46+ append (prefix, *found);
47+ prefix += ' ' ;
48+ return error->with_prefix (prefix);
49+ }
50+ return *result;
51+ }
52+
53+ struct ExtractedData {
54+ Optional<std::uint64_t > trace_id;
55+ Optional<std::uint64_t > parent_id;
56+ Optional<std::string> origin;
57+ Optional<std::string> trace_tags;
58+ Optional<int > sampling_priority;
3759};
3860
39- class DatadogExtractionPolicy : public ExtractionPolicy {
40- Expected<Optional<std::uint64_t >> id (const DictReader& headers,
41- StringView header, StringView kind) {
42- auto found = headers.lookup (header);
43- if (!found) {
44- return nullopt ;
45- }
46- auto result = parse_uint64 (*found, 10 );
47- if (auto * error = result.if_error ()) {
48- std::string prefix;
49- prefix += " Could not extract Datadog-style " ;
50- append (prefix, kind);
51- prefix += " ID from " ;
52- append (prefix, header);
53- prefix += " : " ;
54- append (prefix, *found);
55- prefix += ' ' ;
56- return error->with_prefix (prefix);
57- }
58- return *result;
59- }
61+ Expected<ExtractedData> extract_datadog (const DictReader& headers) {
62+ ExtractedData result;
6063
61- public:
62- Expected<Optional<std:: uint64_t >> trace_id (
63- const DictReader& headers) override {
64- return id (headers, " x-datadog-trace-id " , " trace " );
64+ auto trace_id =
65+ extract_id_header (headers, " x-datadog-trace-id " , " trace " , " Datadog " , 10 );
66+ if ( auto * error = trace_id. if_error ()) {
67+ return std::move (*error );
6568 }
69+ result.trace_id = *trace_id;
6670
67- Expected<Optional<std::uint64_t >> parent_id (
68- const DictReader& headers) override {
69- return id (headers, " x-datadog-parent-id" , " parent span" );
71+ auto parent_id = extract_id_header (headers, " x-datadog-parent-id" ,
72+ " parent span" , " Datadog" , 10 );
73+ if (auto * error = parent_id.if_error ()) {
74+ return std::move (*error);
7075 }
76+ result.parent_id = *parent_id;
7177
72- Expected<Optional<int >> sampling_priority (
73- const DictReader& headers) override {
74- const StringView header = " x-datadog-sampling-priority" ;
75- auto found = headers.lookup (header);
76- if (!found) {
77- return nullopt ;
78- }
79- auto result = parse_int (*found, 10 );
80- if (auto * error = result.if_error ()) {
78+ const StringView sampling_priority_header = " x-datadog-sampling-priority" ;
79+ if (auto found = headers.lookup (sampling_priority_header)) {
80+ auto sampling_priority = parse_int (*found, 10 );
81+ if (auto * error = sampling_priority.if_error ()) {
8182 std::string prefix;
8283 prefix += " Could not extract Datadog-style sampling priority from " ;
83- append (prefix, header );
84+ append (prefix, sampling_priority_header );
8485 prefix += " : " ;
8586 append (prefix, *found);
8687 prefix += ' ' ;
8788 return error->with_prefix (prefix);
8889 }
89- return *result ;
90+ result. sampling_priority = *sampling_priority ;
9091 }
9192
92- Optional<std::string> origin (const DictReader& headers) override {
93- auto found = headers.lookup (" x-datadog-origin" );
94- if (found) {
95- return std::string (*found);
96- }
97- return nullopt ;
93+ auto origin = headers.lookup (" x-datadog-origin" );
94+ if (origin) {
95+ result.origin = *origin;
9896 }
9997
100- Optional<std::string> trace_tags (const DictReader& headers) override {
101- auto found = headers.lookup (" x-datadog-tags" );
102- if (found) {
103- return std::string (*found);
104- }
105- return nullopt ;
98+ auto trace_tags = headers.lookup (" x-datadog-tags" );
99+ if (trace_tags) {
100+ result.trace_tags = *trace_tags;
106101 }
107- };
108102
109- class B3ExtractionPolicy : public DatadogExtractionPolicy {
110- Expected<Optional<std::uint64_t >> id (const DictReader& headers,
111- StringView header, StringView kind) {
112- auto found = headers.lookup (header);
113- if (!found) {
114- return nullopt ;
115- }
116- auto result = parse_uint64 (*found, 16 );
117- if (auto * error = result.if_error ()) {
118- std::string prefix;
119- prefix += " Could not extract B3-style " ;
120- append (prefix, kind);
121- prefix += " ID from " ;
122- append (prefix, header);
123- prefix += " : " ;
124- append (prefix, *found);
125- prefix += ' ' ;
126- return error->with_prefix (prefix);
127- }
128- return *result;
129- }
103+ return result;
104+ }
105+
106+ Expected<ExtractedData> extract_b3 (const DictReader& headers) {
107+ ExtractedData result;
130108
131- public:
132- Expected<Optional<std::uint64_t >> trace_id (
133- const DictReader& headers) override {
134- return id (headers, " x-b3-traceid" , " trace" );
109+ auto trace_id = extract_id_header (headers, " x-b3-traceid" , " trace" , " B3" , 16 );
110+ if (auto * error = trace_id.if_error ()) {
111+ return std::move (*error);
135112 }
113+ result.trace_id = *trace_id;
136114
137- Expected<Optional<std::uint64_t >> parent_id (
138- const DictReader& headers) override {
139- return id (headers, " x-b3-spanid" , " parent span" );
115+ auto parent_id =
116+ extract_id_header (headers, " x-b3-spanid" , " parent span" , " B3" , 16 );
117+ if (auto * error = parent_id.if_error ()) {
118+ return std::move (*error);
140119 }
120+ result.parent_id = *parent_id;
141121
142- Expected<Optional<int >> sampling_priority (
143- const DictReader& headers) override {
144- const StringView header = " x-b3-sampled" ;
145- auto found = headers.lookup (header);
146- if (!found) {
147- return nullopt ;
148- }
149- auto result = parse_int (*found, 10 );
150- if (auto * error = result.if_error ()) {
122+ const StringView sampling_priority_header = " x-b3-sampled" ;
123+ if (auto found = headers.lookup (sampling_priority_header)) {
124+ auto sampling_priority = parse_int (*found, 10 );
125+ if (auto * error = sampling_priority.if_error ()) {
151126 std::string prefix;
152127 prefix += " Could not extract B3-style sampling priority from " ;
153- append (prefix, header );
128+ append (prefix, sampling_priority_header );
154129 prefix += " : " ;
155130 append (prefix, *found);
156131 prefix += ' ' ;
157132 return error->with_prefix (prefix);
158133 }
159- return *result ;
134+ result. sampling_priority = *sampling_priority ;
160135 }
161- };
162136
163- struct ExtractedData {
164- Optional<std::uint64_t > trace_id;
165- Optional<std::uint64_t > parent_id;
166- Optional<std::string> origin;
167- Optional<std::string> trace_tags;
168- Optional<int > sampling_priority;
169- };
170-
171- Expected<ExtractedData> extract_data (ExtractionPolicy& extract,
172- const DictReader& reader) {
173- ExtractedData extracted_data;
174-
175- auto & [trace_id, parent_id, origin, trace_tags, sampling_priority] =
176- extracted_data;
177-
178- auto maybe_trace_id = extract.trace_id (reader);
179- if (auto * error = maybe_trace_id.if_error ()) {
180- return std::move (*error);
137+ // Origin and trace tags are still extracted, but from the Datadog headers.
138+ auto origin = headers.lookup (" x-datadog-origin" );
139+ if (origin) {
140+ result.origin = *origin;
181141 }
182- trace_id = *maybe_trace_id;
183142
184- origin = extract.origin (reader);
185-
186- auto maybe_parent_id = extract.parent_id (reader);
187- if (auto * error = maybe_parent_id.if_error ()) {
188- return std::move (*error);
189- }
190- parent_id = *maybe_parent_id;
191-
192- auto maybe_sampling_priority = extract.sampling_priority (reader);
193- if (auto * error = maybe_sampling_priority.if_error ()) {
194- return std::move (*error);
143+ auto trace_tags = headers.lookup (" x-datadog-tags" );
144+ if (trace_tags) {
145+ result.trace_tags = *trace_tags;
195146 }
196- sampling_priority = *maybe_sampling_priority;
197-
198- trace_tags = extract.trace_tags (reader);
199147
200- return extracted_data ;
148+ return result ;
201149}
202150
203151void log_startup_message (Logger& logger, StringView tracer_version_string,
@@ -299,9 +247,8 @@ Expected<Span> Tracer::extract_span(const DictReader& reader,
299247 ExtractedData extracted_data;
300248
301249 for (const auto style : extraction_styles_) {
302- DatadogExtractionPolicy extract_datadog;
303- B3ExtractionPolicy extract_b3;
304- ExtractionPolicy* extract;
250+ using Extractor = decltype (&extract_datadog); // function pointer
251+ Extractor extract;
305252 switch (style) {
306253 case PropagationStyle::DATADOG:
307254 extract = &extract_datadog;
@@ -314,11 +261,14 @@ Expected<Span> Tracer::extract_span(const DictReader& reader,
314261 extracted_data = ExtractedData{};
315262 continue ;
316263 }
317- auto data = extract_data (* extract, reader);
264+ auto data = extract ( reader);
318265 if (auto * error = data.if_error ()) {
319266 return std::move (*error);
320267 }
321268 extracted_data = *data;
269+ // If the extractor produced a non-null trace ID, then we consider this
270+ // extraction style the one "chosen" for this trace.
271+ // Otherwise, we loop around to the next configured extraction style.
322272 if (extracted_data.trace_id ) {
323273 break ;
324274 }
0 commit comments