Skip to main content

EventLog

Struct EventLog 

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

Single-writer, append-only handle on a mission’s events.jsonl.

Constructed via EventLog::acquire; the lock file is released on drop.

Implementations§

Source§

impl EventLog

Source

pub fn acquire( paths: &MissionPaths, mission_id: &str, throttle: Duration, force: LockForce, ) -> Result<EventLog>

Acquire the single-writer lock for a mission and open its event log.

Creates the mission directory tree (mission dir, runs/, control/) if missing — no-follow: a symlinked .kranz/missions/mission dir or runtime file is refused (P1 mission-path-no-follow), never followed into another repository’s tree. If the lock file already exists, the holder’s liveness decides against the LockForce tier (see its matrix): a provably dead holder is always stolen; a live or indeterminate one fails with EngineError::LockHeld naming the holder’s pid unless the tier permits the steal. Existing events are loaded to resume the seq counter and to verify mission_id matches the log. Any torn final line left by a crash is repaired (truncated, or newline-terminated if the line itself is intact) before the append handle opens, so new events never glue onto a partial line.

The lock file records up to three lines — <pid>, the acquire time as unix epoch seconds (diagnostics only), and the holder’s own process identity token — so a later acquire can detect pid reuse: a holder whose CURRENT token differs from the recorded one is not the process that wrote the lock. Tokens are compared for raw equality (see [process_identity_token]) — never via clock arithmetic, which wall-clock steps would poison. The legacy one- and two-line formats are still accepted; they just forgo reuse detection.

Source

pub fn mission_id(&self) -> &str

Mission id this log was acquired for.

Source

pub fn last_seq(&self) -> u64

Seq of the last appended (or loaded) event; 0 for a fresh log.

Source

pub fn events_path(&self) -> &Path

Path of the underlying events.jsonl.

Source

pub fn append(&mut self, kind: EventKind) -> Result<Event>

Append one event: assigns the next seq and the current timestamp, serializes to a single JSON line, and returns a clone of the stored event so the caller can broadcast it. If this boundary redacts any string payload, secret.redacted audit events are appended immediately after the sanitized event.

Durability: lifecycle events drain any buffered deltas first (file order == append order), then write + flush + fsync. Stream deltas are buffered and drained once the oldest buffered delta exceeds the throttle age — checked here on each append, or on demand (without waiting for another append) via EventLog::flush_if_due.

Source

pub fn append_with_redaction_audits( &mut self, kind: EventKind, ) -> Result<(Event, Vec<Event>)>

Append one event and any required secret.redacted audit events. Returns the sanitized primary event plus the audit events that followed it, so callers that maintain snapshots can fold the same sequence.

Source

pub fn append_redacting( &mut self, kind: EventKind, ) -> Result<(Event, Vec<SecretFinding>)>

Append one event after scanning/redacting string payloads. Returns the sanitized event plus secret findings (fingerprints only, never values).

Source

pub fn flush(&mut self) -> Result<()>

Write any buffered deltas out to the file (no fsync — deltas are recoverable).

Source

pub fn buffer_age(&self) -> Option<Duration>

Elapsed time since the OLDEST buffered delta, or None when the buffer is empty.

Source

pub fn flush_if_due(&mut self) -> Result<bool>

Drain the buffer to the file, WITHOUT waiting for another append call, if it is non-empty and has aged past throttle. Gives idle missions (waiting on an approval gate, worker stopped) a wall-clock- driven flush instead of leaving deltas buffered indefinitely.

Source

pub fn read_events(path: &Path) -> Result<Vec<Event>>

Read and validate the full event log at path.

Seq must start at 1 and increase by exactly 1; any gap or duplicate is EngineError::LogCorruption. An unparseable FINAL line is a torn write from a crash and is dropped with a warning; an unparseable line anywhere else is corruption.

Source

pub fn read_events_and_log_bytes(path: &Path) -> Result<(Vec<Event>, Vec<u8>)>

Read the log at path ONCE and return the validated events together with the exact byte prefix they were parsed from (12th-pass review): the evidence bundle must ship events.jsonl bytes that reproduce the chain/cost/escalations it derived, so parsing one snapshot and then rereading the file for the raw copy is not allowed — a concurrent append between the two opens would ship bytes the folds never saw.

Torn-tail rule (the honest one): an unparseable FINAL line is dropped from the events AND excluded from the returned bytes — the shipped prefix is exactly what parsed, so the bundle’s log always re-folds to the bundle’s derived files. bytes-shipped == bytes-parsed.

Source

pub fn read_events_after(path: &Path, after_seq: u64) -> Result<Vec<Event>>

Read events with seq > after_seq (WS reconnect / tailing). The whole log is still validated — a corrupt prefix must not go unnoticed.

Source

pub fn read_tail_events(path: &Path, max_bytes: u64) -> Result<Vec<Event>>

Read the events on the last max_bytes of the log WITHOUT reading or validating the full file — O(tail) I/O for hot callers that only need trailing facts (e.g. “has a terminal lifecycle event been appended?”).

The window is aligned to the first complete line inside it, and unparseable lines (a torn final write) are skipped rather than treated as corruption — callers that need validation use EventLog::read_events. Returns the whole log when the file fits inside the window.

Trait Implementations§

Source§

impl Debug for EventLog

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for EventLog

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. 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<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> 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> 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<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