pub trait BatchCache: Send + Sync {
// Required methods
fn push(&self, id: &str, body: &[u8]) -> Result<Vec<String>>;
fn replace(
&self,
old: &str,
new: &[(String, Vec<u8>)],
) -> Result<Vec<String>>;
fn pending(&self) -> Vec<String>;
fn read(&self, id: &str) -> Result<Vec<u8>>;
fn remove(&self, id: &str) -> Result<()>;
fn clear(&self) -> Result<()>;
// Provided method
fn take_evicted(&self) -> Vec<String> { ... }
}Expand description
Queue of encoded OTLP batches between the exporter (Exporter) and the transport.
The exporter writes every batch here before trying the network (write-ahead), uploads
oldest-first, and removes what the collector accepted or rejected. Two implementations ship:
MemoryCache (default) and FileCache (survives crashes and restarts); anything else —
a database, a platform store — plugs in through Telemetry::with_cache.
Ids are chosen by the exporter as <unix ns>-<seq>-<records>-<l|t>-<session>-<project key>.
They hold digits, a and b (a split’s halves), hex or process, l or t, -, and a
routing key of lowercase letters, digits, ., -, _, +, and % followed by two uppercase
hex digits: characters every platform allows in a file name, Windows included. A batch without a
project ends with -, because its key is empty. Ids are sortable, so pending
is a plain sort, and prefixed with the creation time so an implementation can expire old batches
without touching file timestamps.
Implementations bound their own footprint by evicting the oldest batches and report what they
evicted, so every loss is counted. A failed write or delete is an Err and is never reported
as done, with one exception: FileCache counts an eviction once the file is gone, even when
the directory sync after it failed. A failed listing reads as empty, and the next pass tries
again.
Required Methods§
Sourcefn push(&self, id: &str, body: &[u8]) -> Result<Vec<String>>
fn push(&self, id: &str, body: &[u8]) -> Result<Vec<String>>
Store one encoded batch under id: once this returns Ok the batch is committed (for
FileCache, on disk). Returns the ids of older batches evicted to make room (the
exporter counts their events as dropped).
Sourcefn replace(&self, old: &str, new: &[(String, Vec<u8>)]) -> Result<Vec<String>>
fn replace(&self, old: &str, new: &[(String, Vec<u8>)]) -> Result<Vec<String>>
Replace the batch old with new (a split): all of new is committed before old
goes, and nothing is evicted in between, so a crash can duplicate records but never lose
them. A missing old returns io::ErrorKind::NotFound without storing children;
an error does not promise that a concurrently evicted parent still exists. Returns the
ids evicted afterwards, excluding any parent already reported as evicted.
Sourcefn read(&self, id: &str) -> Result<Vec<u8>>
fn read(&self, id: &str) -> Result<Vec<u8>>
The body stored under id: ErrorKind::NotFound when it is gone, another error when it
exists but cannot be read right now (e.g. a locked device’s file protection).
Provided Methods§
Sourcefn take_evicted(&self) -> Vec<String>
fn take_evicted(&self) -> Vec<String>
Ids evicted before the exporter could see them (over the bounds when the cache was opened), handed over once so they are counted as lost.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl BatchCache for FileCache
The durability boundary: a batch is committed once push returns Ok — its file was written
to a .tmp, fsynced, renamed into place and the directory fsynced; if any of that fails
the file is removed and push errs (the caller keeps the batch in memory instead). A crash
before that point loses only the batch being written (its .tmp is removed at the next
open). Deletes are fsynced the same way. A split (replace) is journaled: see
FileCache::recover.