Otel: dedupe LLM span error/status + traceparent helpers (#130 follow-up)
Addresses the P2 refactoring follow-ups parked on issue #130: - otel::with_traceparent(builder, &SpanContext) — one shared W3C traceparent injector. Replaces the 4-line inline header loop in llamacpp (3x) and openrouter (3x) and removes ollama's private inject_traceparent method (4 call sites now use the shared helper). Takes &SpanContext (not &dyn Span) because the Span trait is not dyn compatible in opentelemetry 0.31. - otel::record_http_failure(span, status, message) and otel::set_http_status(span, status) — collapse the repeated 'set http.status_code attribute + set_status(Status::error)' boilerplate across all three clients (~10 sites). Net -45 lines. The remaining if-let-Some(span.as_mut()) guards (token attributes, parse-failure status) stay inline rather than growing a SpanHandle wrapper type for a pattern that's already readable.
This commit is contained in:
1 parent
696d9fa8f3
commit
10ed84d7b4
4 files changed
+108
-153
No files matched your search
+35
-1
@@ -2,7 +2,9 @@ use actix_web::HttpRequest;
|
||||
use actix_web::http::header::HeaderMap;
|
||||
use opentelemetry::global::{BoxedSpan, BoxedTracer};
|
||||
use opentelemetry::propagation::TextMapPropagator;
|
||||
use opentelemetry::trace::{Span, SpanBuilder, SpanKind, Status, TraceContextExt, Tracer};
|
||||
use opentelemetry::trace::{
|
||||
Span, SpanBuilder, SpanContext, SpanKind, Status, TraceContextExt, Tracer,
|
||||
};
|
||||
use opentelemetry::{Context, KeyValue, global};
|
||||
use opentelemetry_appender_log::OpenTelemetryLogBridge;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
@@ -117,6 +119,38 @@ pub fn traceparent_headers(context: &Context) -> Vec<(String, String)> {
|
||||
headers.into_iter().filter(|(_, v)| !v.is_empty()).collect()
|
||||
}
|
||||
|
||||
/// Attach the W3C traceparent header to an outgoing request so a downstream
|
||||
/// service parents its own spans onto this trace. No-op when the span context
|
||||
/// is not valid — e.g. debug builds, where the global tracer is a no-op and an
|
||||
/// all-zero traceparent would produce garbage parent spans.
|
||||
pub fn with_traceparent(
|
||||
builder: reqwest::RequestBuilder,
|
||||
span_context: &SpanContext,
|
||||
) -> reqwest::RequestBuilder {
|
||||
let mut b = builder;
|
||||
for (k, v) in
|
||||
traceparent_headers(&Context::new().with_remote_span_context(span_context.clone()))
|
||||
{
|
||||
b = b.header(k, v);
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
/// Record the HTTP status code on the span (success or failure path).
|
||||
pub fn set_http_status(span: Option<&mut BoxedSpan>, status: u16) {
|
||||
if let Some(s) = span {
|
||||
s.set_attribute(KeyValue::new("http.status_code", status as i64));
|
||||
}
|
||||
}
|
||||
|
||||
/// Record an HTTP failure on the span: status code plus an error status.
|
||||
pub fn record_http_failure(span: Option<&mut BoxedSpan>, status: u16, message: &str) {
|
||||
if let Some(s) = span {
|
||||
s.set_attribute(KeyValue::new("http.status_code", status as i64));
|
||||
s.set_status(Status::error(message.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trace_db_call<F, O>(
|
||||
context: &Context,
|
||||
query_type: &str,
|
||||
|
||||
Reference in new issue
Block a user