telemetry-safe 0.2.0

Compile-time safe telemetry formatting facade crate
Documentation
# telemetry-safe

`telemetry-safe` is the main facade crate for defining which values are allowed
to flow into telemetry.

It re-exports:

- `ToTelemetry`
- `telemetry(&value)`
- `telemetry_debug(&value)`
- `#[derive(ToTelemetry)]`

Use this crate when you want compile-time enforcement that only explicitly
approved representations can be emitted through logging, tracing, metrics, or
other observability paths.

## Why this crate exists

Plain `tracing`, logging, or metrics code makes it easy to accidentally send
PII through `Debug`, `Display`, or default instrumentation behavior.

`telemetry-safe` takes an opt-in, type-driven approach instead:

- values must implement `ToTelemetry` before they can be emitted
- raw `String` / `&str` are not blanket-approved
- unsafe paths fail at compile time rather than depending on review discipline

## Basic example

```rust
use telemetry_safe::{telemetry, ToTelemetry};
use std::fmt::{self, Formatter};

#[derive(ToTelemetry)]
struct UserId(u64);

struct OutcomeLabel(&'static str);

impl ToTelemetry for OutcomeLabel {
    fn fmt_telemetry(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str(self.0)
    }
}

#[derive(ToTelemetry)]
struct LoginAttempt {
    user_id: UserId,
    outcome: OutcomeLabel,
    #[telemetry(skip)]
    email: String,
}

let attempt = LoginAttempt {
    user_id: UserId(42),
    outcome: OutcomeLabel("accepted"),
    email: "user@example.com".to_owned(),
};

assert_eq!(
    telemetry(&attempt).to_string(),
    "LoginAttempt { user_id: UserId(42), outcome: accepted }",
);
```

## Related crates

- `telemetry-safe-core`
  - the minimal backend-agnostic core
- `telemetry-safe-tracing`
  - `tracing` integration, including `#[safe_instrument]`

For the full project overview and workspace-level documentation, see the
repository README at <https://github.com/milabo/telemetry-safe-rs>.