Skip to main content

EventLog

Struct EventLog 

Source
pub struct EventLog { /* private fields */ }
Expand description

Append-only event log with optional JSONL journal.

Implementations§

Source§

impl EventLog

Source

pub fn new() -> EventLog

Source

pub fn with_journal(path: PathBuf) -> EventLog

Source

pub fn with_journal_failure_injector( path: PathBuf, failures: JournalFailureInjector, ) -> EventLog

Test/embedder seam for deterministic journal write/flush/fsync faults.

Source

pub fn with_private_path_failure_injector( path: PathBuf, failures: PrivatePathDurabilityFailureInjector, ) -> EventLog

Test/embedder seam for deterministic first-use directory-entry faults.

Source

pub fn bind_run(&mut self, run_id: &str, client_id: &str) -> Result<(), String>

Bind this log to one authenticated active run. Exact repeat binding is idempotent; a different run/client is rejected instead of silently re-attributing later action events.

Source

pub fn bind_policy_session( &mut self, policy_session_id: &str, ) -> Result<(), String>

Attach a CAR-minted policy session to the currently bound proposal.

Source

pub fn clear_policy_session( &mut self, policy_session_id: &str, ) -> Result<(), String>

Source

pub fn clear_run_binding( &mut self, run_id: &str, client_id: &str, ) -> Result<(), String>

Source

pub fn active_run_binding(&self) -> Option<(&str, &str, Option<&str>)>

Source

pub fn with_hash_chaining(self) -> EventLog

Enable tamper-evident hash chaining for events appended from now on (EPIC A / A9). The chain continues from the last already-appended event’s hash if one exists (re-enabling after a load), else from the genesis link. Returns self for builder-style use.

Source

pub fn enable_hash_chaining(&mut self)

Turn on hash chaining in place. Idempotent.

Source

pub fn hash_chaining_enabled(&self) -> bool

Whether hash chaining is currently enabled.

Source

pub fn append( &mut self, kind: EventKind, action_id: Option<&str>, proposal_id: Option<&str>, data: HashMap<String, Value>, ) -> &Event

Source

pub fn append_critical( &mut self, kind: EventKind, action_id: Option<&str>, proposal_id: Option<&str>, data: HashMap<String, Value>, ) -> Result<&Event, String>

Append a lifecycle-critical event and return only after its exact JSONL row and all earlier queued rows have been flushed and fsynced. If a write/flush/fsync attempt fails, the exact event remains pending in memory so an identical retry finishes the same row rather than minting a second terminal with a new timestamp.

This compatibility API performs an unbounded blocking acknowledgement wait and is intended only for genuinely synchronous callers. Async callers must use Self::append_critical_async so a stalled filesystem cannot occupy an executor worker indefinitely.

Source

pub fn append_critical_bounded( &mut self, kind: EventKind, action_id: Option<&str>, proposal_id: Option<&str>, data: HashMap<String, Value>, acknowledgement_timeout: Duration, ) -> Result<&Event, CriticalAppendError>

Synchronous critical append with a hard acknowledgement bound.

This is the startup-thread counterpart of Self::append_critical_async. The exact serialized row is installed in critical_pending before the bounded wait begins, so timeout cannot claim success or authorize a different lifecycle event. An identical later startup replay safely reconciles the row whether or not the writer completed before timeout.

Source

pub async fn append_critical_async( &mut self, kind: EventKind, action_id: Option<&str>, proposal_id: Option<&str>, data: HashMap<String, Value>, acknowledgement_timeout: Duration, ) -> Result<&Event, CriticalAppendError>

Append a lifecycle-critical event without blocking an async executor worker on filesystem acknowledgement.

The acknowledgement wait is bounded by acknowledgement_timeout. Once the writer accepts the message, the exact serialized row is marked pending before this future can yield. Timeout, cancellation by an outer request deadline, writer failure, and acknowledgement-coordinator shutdown therefore leave an identical retry safe: it reuses the original event timestamp/hash and the writer suppresses a duplicate row. Until that exact retry reconciles the pending row, a different critical event is rejected before enqueue.

Source

pub fn verify_chain(&self) -> Result<usize, usize>

Verify the tamper-evidence hash chain over the currently-loaded events (EPIC A / A9). Walks every event that carries a hash, recomputing it from its content + the running prev_hash and checking the links join up. Returns Ok(n) with the number of chained events verified, or Err(index) naming the first event whose hash or linkage doesn’t match — i.e. the point at which a chained event was edited, or an interior event was deleted or reordered.

Scope of the guarantee: the chain detects interior edits/reorderings/deletions only. It cannot detect truncation at either end: there is no anchored head hash, so the first chained event’s prev_hash is taken on trust (dropping a prefix goes unnoticed), and nothing pins the tail (dropping a suffix goes unnoticed). Detecting head/tail truncation requires anchoring the chain head (and a trusted latest-hash witness), which is out of scope until that anchor exists.

Events without a hash (appended before chaining was enabled) are skipped, so a partially-chained log verifies its chained suffix.

Source

pub fn append_metered( &mut self, kind: EventKind, action_id: Option<&str>, proposal_id: Option<&str>, data: HashMap<String, Value>, metrics: Metrics, ) -> &Event

Append an event with cross-cutting Metrics (duration, tokens, cost) merged into its data under metric_keys. Use this for any event whose latency or token cost should feed trajectory-level aggregation (metrics_totals) — the deep-telemetry substrate of §3.5.1. Metric keys present in both data and metrics take the metrics value (the metrics argument wins).

Source

pub fn metrics_totals(&self) -> MetricsTotals

Sum the telemetry metrics across every event in the log — the trajectory-level totals (tokens, cost, wall-clock) that harness-level evaluation (§5.2.1) and the Evolution Agent (§3.5.2) reason over.

Contract: this sums every event carrying a metric_keys value, regardless of which append path emitted it. A duration recorded once per action (e.g. ActionSucceeded) is counted once; the standardized keys mean there is a single value per metric per event, so there is no double-count as long as each unit of work meters itself once. Token metrics from InferenceMetered and latency from action events sum into the same totals — that is intended (total cost = model + tools).

Source

pub fn cost_by_agent(&self) -> Vec<AgentCost>

Per-agent cost/token report (EPIC G / G3) — see cost_by_agent_of.

Source

pub fn events(&self) -> &[Event]

Source

pub fn len(&self) -> usize

Source

pub fn span_len(&self) -> usize

Source

pub fn is_empty(&self) -> bool

Source

pub fn stats(&self) -> EventLogStats

Source

pub fn truncate_events_keep_last(&mut self, keep_last: usize) -> usize

Source

pub fn truncate_spans_keep_last(&mut self, keep_last: usize) -> usize

Source

pub fn clear(&mut self) -> EventLogStats

Drop every retained event and span, releasing their memory. The JSONL journal is left untouched (it is the audit trail); the monotonic counters (trimmed_events, cumulative_cost_usd) are preserved — clear frees memory, it doesn’t reset the log’s history.

Source

pub fn trimmed_events(&self) -> u64

Total events ever dropped from the in-memory log (retention trims, manual truncation, clear). Monotonic; > 0 means the retained window is incomplete — consumers projecting over Self::events (e.g. the A6 tool-receipt verifier) must treat an absent event as possibly-evicted, not as never-happened.

Source

pub fn cumulative_cost_usd(&self) -> f64

Monotonic cumulative cost (USD) across every event ever appended (EPIC G / G1). Unlike folding cost_usd over Self::events — which slides backward when retention trims metered events — this counter only grows, so it is the correct denominator for a cumulative budget (AlertThresholds::max_cost_usd). Seeded from the journal on Self::load; survives trims and Self::clear.

Source

pub fn journal_size_bytes(&self) -> Option<u64>

Current size of the JSONL journal file in bytes, if a journal is configured and stat-able. The background writer batches, so this may momentarily lag the last few appends.

Source

pub fn compact_journal(&mut self) -> bool

Rewrite the JSONL journal to contain exactly the currently-retained events (G2 journal compaction — before this, retention trimmed the in-memory log only and the journal grew unbounded). Atomic: writes a sibling temp file and renames it over the journal. The background writer is joined first (draining its backlog and closing its handle — renaming under a live append-mode handle would orphan subsequent writes to the old inode), then respawned on the compacted file.

Hash chaining (A9) survives: Self::verify_chain anchors the first hashed event on its stored prev_hash, so the retained tail of a chained log still verifies after a compact + reload. Corollary: a head-trim by retention is indistinguishable from compaction — tamper evidence covers the retained tail only.

Returns true if the journal was rewritten. Failure is best-effort like the journal itself: a warning is logged, the old (uncompacted) journal stays in place, and appending resumes against it.

Source

pub fn query(&self, query: &EventQuery) -> Vec<&Event>

Run a structured audit EventQuery, returning matching events most-recent-first, capped at query.limit (EPIC G / G2).

Source

pub fn set_retention(&mut self, policy: Option<RetentionPolicy>)

Install an auto-retention policy (EPIC G / G2). max_events is then enforced on every append; call Self::enforce_retention to also apply the age bound.

Source

pub fn retention(&self) -> Option<&RetentionPolicy>

The active retention policy, if any.

Source

pub fn enforce_retention( &mut self, policy: &RetentionPolicy, now: DateTime<Utc>, ) -> usize

Apply a retention policy now: drop events older than max_age_secs and cap the count at max_events (keeping the most recent). Returns the number of events removed. Independent of the installed policy, so a caller can run a one-off sweep. When a journal is configured, a trim also triggers the throttled journal compaction (see Self::compact_journal) so the JSONL file tracks retention instead of growing unbounded.

Source

pub fn filter( &self, kind: Option<&EventKind>, action_id: Option<&str>, ) -> Vec<&Event>

Source

pub fn begin_span( &mut self, name: &str, trace_id: &str, parent_span_id: Option<&str>, attributes: HashMap<String, Value>, ) -> String

Begin a new trace span. Returns the generated span_id.

Source

pub fn end_span(&mut self, span_id: &str, status: SpanStatus)

End an open span by setting its status and end time.

Source

pub fn spans(&self) -> Vec<Span>

Return all spans.

Source

pub fn export_traces(&self) -> String

Export traces as OTLP-compatible JSON.

Source

pub fn load(path: &Path) -> Result<EventLog, Error>

Load an event log from a JSONL journal file.

Source

pub fn load_read_only(path: &Path) -> Result<EventLog, Error>

Load and validate an event log without attaching a writer or modifying the source journal. An unterminated final row is reported as std::io::ErrorKind::UnexpectedEof; callers that own live append recovery should use EventLog::load instead.

Trait Implementations§

Source§

impl Default for EventLog

Source§

fn default() -> EventLog

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more