What this does not do¶
Things people reasonably expect from a telemetry crate that this one does not provide. Where there is a workaround it is named; where the answer is simply "no", it says so.
There is no batching, queueing or retry¶
record awaits the sink's emit and returns its result. HttpSink makes
one POST per event and waits for it. If the collector is slow, the caller
waits, bounded by the configured timeout. If the POST fails, the event is
gone — nothing is queued, retried or backed off.
Two workarounds, depending on what you need. Write to a FileSink and ship
the file with something built for the job. Or wrap a sink in your own
implementation that buffers and flushes on a schedule — the trait is small
enough that this is a short piece of code.
OtlpSink is the exception: the OpenTelemetry SDK batches behind it. That
is also why its emit cannot tell you whether the export worked.
There is no sampling or rate limiting¶
Every record call on an Enabled context produces an event. There is no
sample rate, no per-event budget and no de-duplication. A loop that records
per iteration will emit per iteration.
Nothing is collected automatically¶
The crate records what you tell it to record. It does not hook a CLI
framework, wrap a command dispatcher, capture panics, time anything, or
derive event names from the call site. Every event exists because a
record call was written.
That also means event naming is entirely yours. command.invoke and
tool.start are conventions used in the examples, not values the crate
knows about.
It does not read configuration or environment variables¶
TelemetryContext takes a CollectionPolicy from the caller. The crate
does not read a config file, an environment variable or a CLI flag, and the
consent module does not choose a path — you pass it one.
Tools built on rtb-cli get that layer
from the CLI runtime, which resolves a policy from the consent file and an
environment variable and ships telemetry status / enable / disable /
reset. Tools not built on it wire their own.
There is no consent prompt¶
The crate persists a decision. Asking for it — the wording, the timing, whether to prompt on first run at all — is the tool's job. Nothing here will interact with a user.
There is no data-deletion path¶
consent::reset deletes the decision, so the tool goes back to
"never asked". It does not delete events already written to a FileSink,
already POSTed to an endpoint, or already exported to a collector. There is
no "delete everything about me" call, because the crate has no idea where
the data ended up — that is the sink's business, and for remote sinks it is
the backend operator's.
A tool that promises a deletion path has to implement it against whatever it configured as a destination.
The policy cannot be changed on a built context¶
CollectionPolicy is fixed at build(). There is no setter, and nothing
watches the consent file for changes. A tool that lets a user opt out
mid-run rebuilds the context (or drops it) to make that take effect.
One context has exactly one sink¶
TelemetryContext holds a single Arc<dyn TelemetrySink>. You cannot
attach two, so "write to a file and POST to a collector" is not a
supported configuration out of the box. Implement a fan-out sink that owns
both and forwards emit to each — and decide there what happens when one
of them fails.
FileSink never rotates or prunes¶
The file grows for as long as the tool keeps recording. There is no size cap, no rotation, no retention window and no compression. If it is going to run for a long time on a machine you do not control, put it somewhere the operating system already manages, or rotate it yourself.
Line integrity is process-local¶
Concurrent emit calls within one process cannot interleave. Two processes
appending to the same file can, once an event exceeds 4 KiB. See
Why FileSink holds a lock. Give each process
its own file.
OTLP export is logs only, and OTLP/HTTP is broken in 0.7.3¶
OtlpSink emits OpenTelemetry log records. It does not produce traces
or metrics, and it is not a service-observability layer — this crate is
product analytics about a user's tool, not instrumentation of a running
service.
The OTLP/HTTP transport does not currently work: an endpoint that routes to
it panics inside the SDK's exporter thread and exports nothing. Use
grpc://, grpcs:// or a :4317 endpoint. The detail, with the exact
failure, is in Sinks.
Attributes are never redacted¶
Event::attrs values ship exactly as you set them, to every sink. Only
args and err_msg are scrubbed, and only by the sinks that write
off-process. See Where redaction applies.
There is no blocking API¶
record, record_with_attrs and flush are async and want a Tokio
runtime. There is no synchronous wrapper, and calling them from a
non-async context means providing a runtime yourself.
The event JSON is not a frozen schema¶
Event is #[non_exhaustive] and new fields can appear in a minor
release. Anything parsing the JSON should ignore unknown fields rather than
reject them. Attribute key order is not stable between runs either — it is
a HashMap.