@@ -94,13 +94,6 @@ void RequestHandler::on_span_start(const httplib::Request& req,
9494 span_cfg.resource = *resource;
9595 }
9696
97- if (auto origin =
98- utils::get_if_exists<std::string_view>(request_json, " origin" )) {
99- logger_->log_info (
100- " [start_span] origin, but this can only be set via the "
101- " 'x-datadog-origin' header" );
102- }
103-
10497 auto success = [](const datadog::tracing::Span& span,
10598 httplib::Response& res) {
10699 // clang-format off
@@ -113,37 +106,50 @@ void RequestHandler::on_span_start(const httplib::Request& req,
113106 res.set_content (response_body.dump (), " application/json" );
114107 };
115108
116- if (auto parent_id =
117- utils::get_if_exists<uint64_t >(request_json, " parent_id" )) {
118- if (*parent_id != 0 ) {
119- auto parent_span_it = active_spans_.find (*parent_id);
120- if (parent_span_it == active_spans_.cend ()) {
121- const auto msg = " on_span_start: span not found for id " +
122- std::to_string (*parent_id);
123- VALIDATION_ERROR (res, msg);
124- }
109+ auto parent_id = utils::get_if_exists<uint64_t >(request_json, " parent_id" );
125110
126- auto span = parent_span_it->second .create_child (span_cfg);
127- success (span, res);
128- active_spans_.emplace (span.id (), std::move (span));
129- return ;
130- }
111+ // No `parent_id` field OR parent is `0` -> create a span.
112+ if (!parent_id || *parent_id == 0 ) {
113+ auto span = tracer_.create_span (span_cfg);
114+ success (span, res);
115+ active_spans_.emplace (span.id (), std::move (span));
116+ return ;
117+ }
118+
119+ // If there's a parent ID -> Extract using the tracing context stored earlier
120+ // OR -> Create a child span from the span.
121+ auto parent_span_it = active_spans_.find (*parent_id);
122+ if (parent_span_it != active_spans_.cend ()) {
123+ auto span = parent_span_it->second .create_child (span_cfg);
124+ success (span, res);
125+ active_spans_.emplace (span.id (), std::move (span));
126+ return ;
131127 }
132128
133- if (auto http_headers = utils::get_if_exists<nlohmann::json::array_t >(
134- request_json, " http_headers" )) {
135- if (!http_headers->empty ()) {
136- auto span = tracer_.extract_or_create_span (
137- utils::HeaderReader (*http_headers), span_cfg);
138- success (span, res);
139- active_spans_.emplace (span.id (), std::move (span));
129+ auto context_it = tracing_context_.find (*parent_id);
130+ if (context_it != tracing_context_.cend ()) {
131+ auto span =
132+ tracer_.extract_span (utils::HeaderReader (context_it->second ), span_cfg);
133+ if (!span) {
134+ const auto msg =
135+ " on_span_start: unable to create span from http_headers "
136+ " identified "
137+ " by parent_id " +
138+ std::to_string (*parent_id);
139+ VALIDATION_ERROR (res, msg);
140140 return ;
141141 }
142+ success (*span, res);
143+ active_spans_.emplace (span->id (), std::move (*span));
144+ return ;
142145 }
143146
144- auto span = tracer_.create_span (span_cfg);
145- success (span, res);
146- active_spans_.emplace (span.id (), std::move (span));
147+ // Safeguard
148+ if (*parent_id != 0 ) {
149+ const auto msg = " on_span_start: span or http_headers not found for id " +
150+ std::to_string (*parent_id);
151+ VALIDATION_ERROR (res, msg);
152+ }
147153}
148154
149155void RequestHandler::on_span_end (const httplib::Request& req,
@@ -162,7 +168,6 @@ void RequestHandler::on_span_end(const httplib::Request& req,
162168 VALIDATION_ERROR (res, msg);
163169 }
164170
165- active_spans_.erase (span_it);
166171 res.status = 200 ;
167172}
168173
@@ -240,9 +245,42 @@ void RequestHandler::on_inject_headers(const httplib::Request& req,
240245 res.set_content (response_json.dump (), " application/json" );
241246}
242247
248+ void RequestHandler::on_extract_headers (const httplib::Request& req,
249+ httplib::Response& res) {
250+ const auto request_json = nlohmann::json::parse (req.body );
251+ auto http_headers = utils::get_if_exists<nlohmann::json::array_t >(
252+ request_json, " http_headers" );
253+ if (!http_headers) {
254+ VALIDATION_ERROR (res, " on_extract_headers: missing `http_headers` field." );
255+ }
256+
257+ auto span = tracer_.extract_span (utils::HeaderReader (*http_headers));
258+
259+ if (span.if_error ()) {
260+ const auto response_body_fail = nlohmann::json{
261+ {" span_id" , nullptr },
262+ };
263+ res.set_content (response_body_fail.dump (), " application/json" );
264+ return ;
265+ }
266+
267+ const auto response_body = nlohmann::json{
268+ {" span_id" , span->parent_id ().value ()},
269+ };
270+
271+ tracing_context_[*span->parent_id ()] = std::move (*http_headers);
272+
273+ // The span below will not be finished and flushed.
274+ blackhole_.emplace_back (std::move (*span));
275+
276+ res.set_content (response_body.dump (), " application/json" );
277+ }
278+
243279void RequestHandler::on_span_flush (const httplib::Request& /* req */ ,
244280 httplib::Response& res) {
245281 scheduler_->flush_telemetry ();
282+ active_spans_.clear ();
283+ tracing_context_.clear ();
246284 res.status = 200 ;
247285}
248286
0 commit comments