Skip to content

Errors

Everything fallible in the crate returns Result<_, TelemetryError>.

The variants

Variant Message Diagnostic code Raised by
Io(std::io::Error) sink I/O error: {0} rtb::telemetry::io FileSink writes; consent::read, write, reset
Serde(String) serialisation error: {0} rtb::telemetry::serde Event JSON serialisation in FileSink / OtlpSink; malformed or wrong-version consent TOML
Http(String) HTTP telemetry sink error: {0} rtb::telemetry::http HttpSink — endpoint scheme, client build, transport, non-2xx
Otlp(String) OTLP telemetry sink error: {0} rtb::telemetry::otlp OtlpSink — endpoint scheme, exporter build, flush

TelemetryError is #[non_exhaustive], so a match over it needs a _ arm and new variants can appear in a minor release.

Io is the only variant carrying a typed cause; the rest carry a string, already formatted by the sink that produced it. Io has #[from] std::io::Error, so ? on a filesystem call inside a custom sink converts for free.

Diagnostics

TelemetryError derives miette::Diagnostic as well as thiserror::Error, so the codes above show up in a miette-rendered report. Any tool already returning miette::Result from main can propagate a telemetry error with ? and get the code in the rendered output.

Which failures reach the caller at all

  • TelemetryContext::record under Disabled: always Ok(()). The sink is never called, so it cannot fail.
  • FileSink and HttpSink: report their failure from emit, and record passes it straight back to you.
  • OtlpSink: emit returns Ok(()) even when the export fails. Export errors only appear from flush. See Sinks.
  • MemorySink: never fails. If its internal lock is poisoned it drops the event and still returns Ok(()).

What to do with a telemetry error

Recording usage is not the job the user asked for, so failing their command because a telemetry write failed is almost always the wrong call. Log it, or ignore it deliberately:

if let Err(err) = telemetry.record("command.invoke").await {
    tracing::debug!(%err, "telemetry record failed");
}

The exception is a tool whose purpose is shipping telemetry, where a failed export is the failure of the run.

Two things make these errors safer to log than they might look. The out-of-process sinks redact args and err_msg before serialising, so an error raised during the write is describing an already-redacted event. And SecretString keeps bearer tokens and OTLP header values out of Debug output. Attributes are not redacted anywhere, so an error string that ends up quoting your own attribute values is only as safe as what you put in them.