Add a fresh-chain realtime seed to the directory writers

KT
8d ago
+566-29

Stacked on #15. Merge order: #13, #14, #15, then this. Completes SOW-0123 (.agents/sow/done/SOW-0123-20260624-event-time-lane-fresh-clock-seed.md).

Decisions for review

  • Agent-chosen: the Go pointer helper is named journal.FreshRealtimeSeed(uint64), following PublishEveryEntries and SyncOnArchive. The Rust names follow the plan reviewed in the SOW.
  • Needs your decision, not blocking this PR: with the option unset, a fresh Rust chain clamps a past realtime forward to now, while a fresh Go chain keeps it. This difference predates the PR; the PR keeps both defaults unchanged and documents the difference. It is tracked as SOW-0165, with options A (Rust follows Go), B (Go follows Rust) and C (keep it as an accepted exception).

Problem

Event-time writers, such as the Netdata netflow VPC lane, append past timestamps in increasing order. A fresh Rust chain started its realtime floor at wall-clock time, so those timestamps were clamped forward to now.

Changes

  • Rust: Config::fresh_realtime_seed_usec: Option<u64> and Config::with_fresh_realtime_seed_usec. Config::new is unchanged.
  • Go: LogConfig.FreshRealtimeSeedUsec *uint64 and journal.FreshRealtimeSeed.
  • In both languages:
    • an existing chain tail always wins over the seed;
    • the maximum uint64 seed is rejected;
    • omitted realtime still uses the wall clock;
    • duplicate and out-of-order realtime still clamp to previous + 1.
  • Docs: Rust-API.md, Go-API.md, Options-Reference.md, and the spec, including the lazy-open requirement for event-time filenames.

Validation

  • New tests in both languages: seed 0 keeps past times; the seed acts as a floor; the tail wins; clamping of duplicate and out-of-order times; wall-clock for omitted realtime; maximum rejected. Rust also covers the default clamping.
  • cargo test --workspace (45 suites) and CGO_ENABLED=0 go test ./... pass.
  • tests/docs/check_wiki_docs.py and tests/docs/verify_examples.py pass.

Summary by cubic

Adds a fresh-chain realtime seed to the directory writers so event-time lanes can append past, increasing timestamps without Rust clamping them forward to the wall clock.

  • Rust Config::with_fresh_realtime_seed_usec and Go LogConfig.FreshRealtimeSeedUsec (via the FreshRealtimeSeed helper) set the realtime floor for a chain with no existing tail.
  • Behavior changes only when the option is set; an existing tail always wins, seeds at or above 2^55 - 1 are rejected so seed + 1 stays valid systemd realtime, and omitted realtime still uses the wall clock. Defaults are unchanged.
  • Event-time filenames require lazy open; eager open names the file before any event exists.

SOW-0165 follow-up — with the option unset, fresh Rust chains clamp past realtime forward to now while fresh Go chains keep it. The user decided Rust will adopt Go's zero floor (option A), pending a check of Netdata's Rust Log callers; this PR changes neither default.