use opentelemetry::global; use opentelemetry_http::HeaderInjector; use tracing::{Instrument as _, Span}; use tracing_opentelemetry::OpenTelemetrySpanExt; /// Client span for an outbound HTTP call; the trace context of this span is /// what gets injected into the request, so the remote hop parents to it. pub fn http_client_span(method: &str, url: &str) -> Span { let name = format!("{method} {url}"); tracing::info_span!( "http.client", "otel.name" = %name, "otel.kind" = "client", "http.request.method" = %method, "url.full" = %url, "http.response.status_code" = tracing::field::Empty, ) } /// Sends a request inside `span` with `traceparent` injected into its headers. pub async fn send( span: Span, request: reqwest::RequestBuilder, ) -> Result { let mut headers = http::HeaderMap::new(); global::get_text_map_propagator(|propagator| { propagator.inject_context(&span.context(), &mut HeaderInjector(&mut headers)); }); if let Some(request_id) = envelope::context::request_id() && let Ok(value) = request_id.parse() { headers.insert( http::header::HeaderName::from_static(envelope::REQUEST_ID_HEADER), value, ); } let result = request .headers(headers) .send() .instrument(span.clone()) .await; match &result { Ok(response) => { span.record( "http.response.status_code", i64::from(response.status().as_u16()), ); } Err(_) => { span.record("otel.status_code", "error"); } } result }