Skip to main content

telemetry_safe_tracing/
lib.rs

1//! `tracing` integration for `telemetry-safe`.
2//!
3//! This crate is intentionally thin so backend-specific macro work can evolve
4//! without pulling `tracing` into the core safety model.
5
6pub use telemetry_safe::{
7    TelemetryDebug, TelemetryDisplay, ToTelemetry, telemetry, telemetry_debug,
8};
9pub use telemetry_safe_tracing_macros::safe_instrument;
10pub use tracing;
11
12// Proc macros expand through this public path so downstream crates do not need
13// to know which helper crate owns the implementation details.
14extern crate self as telemetry_safe_tracing;
15
16#[doc(hidden)]
17pub mod __private {
18    use crate::tracing::{Span, field};
19    use crate::{ToTelemetry, telemetry};
20
21    /// Records return values through `ToTelemetry` so `safe_instrument(ret)`
22    /// never falls back to ambient `Debug` or `Display`.
23    pub fn record_ret<T: ToTelemetry>(span: &Span, value: &T) {
24        span.record("ret", field::display(telemetry(value)));
25    }
26
27    /// Records only the error side of a `Result`, keeping `err` tied to the
28    /// explicit telemetry boundary instead of `tracing`'s default formatting.
29    pub fn record_err<R: SafeInstrumentResult>(span: &Span, result: &R) {
30        result.record_err(span);
31    }
32
33    pub trait SafeInstrumentResult {
34        fn record_err(&self, span: &Span);
35    }
36
37    impl<T, E: ToTelemetry> SafeInstrumentResult for Result<T, E> {
38        fn record_err(&self, span: &Span) {
39            if let Err(err) = self {
40                span.record("err", field::display(telemetry(err)));
41            }
42        }
43    }
44}
45
46/// Marks a string literal as intentionally safe to emit from `safe_instrument`.
47///
48/// This helper is feature-gated because allowing literals is a product-level
49/// tradeoff. Requiring an explicit wrapper keeps that choice visible in call sites.
50#[cfg(feature = "trusted-literal")]
51#[must_use]
52pub fn trusted_literal(value: &'static str) -> TrustedLiteral {
53    TrustedLiteral(value)
54}
55
56/// A marker wrapper for compile-time string literals that a product has opted
57/// into treating as telemetry-safe.
58#[cfg(feature = "trusted-literal")]
59#[derive(Clone, Copy)]
60pub struct TrustedLiteral(&'static str);
61
62#[cfg(feature = "trusted-literal")]
63impl telemetry_safe::ToTelemetry for TrustedLiteral {
64    fn fmt_telemetry(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        f.write_str(self.0)
66    }
67}