ExporterHealth
An out-of-band health signal for a durable exporter.
Why this exists
An exporter reports a failed durable write by returning ExportResult.Failure — but on the logging path every caller discards it. LogCapture.capture() hands the result back to per-platform appenders whose framework signatures return void, so the failure has nowhere to go. A component whose whole purpose is post-hoc diagnosis was therefore unable to report its own death: a device silently stopped accepting telemetry and stayed that way for hours, with nothing written and nothing logged (#1860).
These counters answer the question that could not be answered at the time: "has this exporter accepted anything since process start?" They are cumulative and monotonic (except consecutiveFailures, which resets), so a monitor can read them at any moment, or collect the owning kotlinx.coroutines.flow.StateFlow and alarm on a stall.
No timestamp, deliberately
There is no lastSuccessAt/deadSince field. Time is an injected dependency in this repo and an exporter holds no Clock; adding one to carry a diagnostic field would put a wall-clock read on the export hot path. Counters are sufficient — accepted == 0 with failed > 0 is "dead since process start", and an observer that needs wall-clock timing can stamp its own observations of the flow.
Constructors
Properties
Log records durably taken by WarpLogRecordExporter.export, cumulative. Counts records, not calls and not store writes: one batched export of 256 records moves this by 256, and one export of a record whose id was already taken moves it by zero — a dedup no-op returns ExportResult.Success without touching the store, so an all-dedup state cannot masquerade as a healthy climbing count. A record refused by the buffer cap under BufferPolicy.DROP_NEWEST is not counted either, for the same reason. A successful merge does not move this at all — it takes no records through admission — but does clear consecutiveFailures, because the store accepting it is evidence the store is up.
Failed writes since the last successful one. Resets to zero on any success — distinguishes "currently down" from "recovered after some trouble".
Records evicted by the buffer cap under BufferPolicy.DROP_OLDEST, cumulative.
The most recent failure cause, from either a write or a recovery. Retained after a subsequent success, as forensics.
Whether recover() could not read or decode the persisted state, so the exporter started empty and the previously buffered telemetry is unrecoverable. Sticky for the life of the exporter.
Records refused by the buffer cap under BufferPolicy.DROP_NEWEST, cumulative.