use modkit_canonical_errors::Problem;
pub trait CanonicalProblemMigrationExt: Sized {
#[must_use]
fn with_temporary_request_context(self, instance: impl Into<String>) -> Self;
}
impl CanonicalProblemMigrationExt for Problem {
fn with_temporary_request_context(self, instance: impl Into<String>) -> Self {
let mut problem = self.with_instance(instance);
if let Some(id) = tracing::Span::current().id() {
problem = problem.with_trace_id(id.into_u64().to_string());
}
problem
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
use modkit_canonical_errors::CanonicalError;
#[test]
fn sets_instance() {
let problem: Problem = CanonicalError::internal("boom").create().into();
let problem = problem.with_temporary_request_context("/api/v1/widgets/42");
assert_eq!(problem.instance.as_deref(), Some("/api/v1/widgets/42"));
}
#[test]
fn sets_trace_id_when_in_span() {
use tracing_subscriber::fmt;
let subscriber = fmt().with_test_writer().finish();
tracing::subscriber::with_default(subscriber, || {
let span = tracing::info_span!("trace_id_test");
let _enter = span.enter();
let problem: Problem = CanonicalError::internal("boom").create().into();
let problem = problem.with_temporary_request_context("/");
assert!(
problem.trace_id.is_some(),
"expected span-id fallback to populate trace_id"
);
});
}
#[test]
fn no_trace_id_outside_any_span() {
let problem: Problem = CanonicalError::internal("boom").create().into();
let problem = problem.with_temporary_request_context("/");
assert!(problem.trace_id.is_none());
}
}