use std::time::Duration;
use reqwest::{Client, Request, Response};
use tracing::{field::Empty, Instrument, Span};
pub async fn tracing_send(client: &Client, req: Request) -> reqwest::Result<Response> {
let span = span_for(&req);
let started = std::time::Instant::now();
let res = client.execute(req).instrument(span.clone()).await;
let elapsed = started.elapsed();
record_outcome(&span, elapsed, &res);
res
}
fn span_for(req: &Request) -> Span {
tracing::info_span!(
"http.client.request",
otel.kind = "client",
http.method = %req.method(),
http.url = %req.url(),
http.status_code = Empty,
http.duration_ms = Empty,
error.type = Empty,
)
}
fn record_outcome(span: &Span, elapsed: Duration, res: &reqwest::Result<Response>) {
span.record("http.duration_ms", elapsed.as_millis() as u64);
match res {
Ok(r) => span.record("http.status_code", r.status().as_u16()),
Err(e) => span.record("error.type", classify_error(e)),
};
}
fn classify_error(e: &reqwest::Error) -> &'static str {
if e.is_timeout() {
"timeout"
} else if e.is_connect() {
"connect"
} else if e.is_decode() {
"decode"
} else {
"other"
}
}