main
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<reqwest::Response, reqwest::Error> {
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
}