nv_runtime/provenance.rs
1//! Provenance types — audit trail for stage and view-system decisions.
2
3use nv_core::id::StageId;
4use nv_core::timestamp::{Duration, MonotonicTs};
5use nv_view::view_state::{ViewEpoch, ViewVersion};
6use nv_view::{EpochDecision, MotionSource, TransitionPhase};
7
8/// Full provenance for one processed frame.
9///
10/// Every output carries this, making production debugging tractable.
11///
12/// # Timing semantics
13///
14/// All timestamps are [`MonotonicTs`] values — they share the same monotonic
15/// clock domain as [`FrameEnvelope::ts()`](nv_frame::FrameEnvelope::ts).
16///
17/// - `frame_receive_ts` — when the frame was dequeued from the bounded queue.
18/// - `pipeline_complete_ts` — when all stages finished and output was constructed.
19/// - Per-stage `start_ts` / `end_ts` — real wall-clock offsets converted to
20/// monotonic nanoseconds from the pipeline epoch for ordering consistency.
21#[derive(Debug, Clone)]
22pub struct Provenance {
23 /// Per-stage provenance records, in execution order.
24 pub stages: Vec<StageProvenance>,
25 /// View-system provenance for this frame.
26 pub view_provenance: ViewProvenance,
27 /// Timestamp when the frame was dequeued from the bounded queue
28 /// (start of pipeline processing for this frame).
29 pub frame_receive_ts: MonotonicTs,
30 /// Timestamp when the pipeline completed processing this frame.
31 pub pipeline_complete_ts: MonotonicTs,
32 /// Total pipeline latency (receive → complete).
33 pub total_latency: Duration,
34 /// Wall-clock age of the frame at processing time.
35 ///
36 /// Computed as `WallTs::now() - frame.wall_ts()` when the frame
37 /// enters pipeline processing. A large value indicates the frame
38 /// was stale before the executor even touched it — typically due
39 /// to buffer-pool starvation, TCP backlog, or slow decode.
40 ///
41 /// `None` if wall-clock age could not be determined (e.g., if the
42 /// frame's wall timestamp is in the future due to clock skew).
43 pub frame_age: Option<Duration>,
44 /// Time the frame spent waiting in the bounded queue.
45 ///
46 /// Measured from `push()` to `pop()` using `Instant`. A
47 /// consistently low value combined with high `frame_age` proves
48 /// that staleness originates upstream of the queue (e.g., in the
49 /// decoder or TCP receive buffer), not from queue backlog.
50 pub queue_hold_time: std::time::Duration,
51 /// Whether this output includes the source frame.
52 ///
53 /// Always `true` for `FrameInclusion::Always`, always `false` for
54 /// `FrameInclusion::Never`, and periodic for
55 /// `FrameInclusion::Sampled`.
56 pub frame_included: bool,
57}
58
59/// Per-stage provenance record.
60#[derive(Debug, Clone)]
61pub struct StageProvenance {
62 /// Which stage.
63 pub stage_id: StageId,
64 /// When the stage started processing (monotonic nanos from pipeline epoch).
65 pub start_ts: MonotonicTs,
66 /// When the stage finished processing.
67 pub end_ts: MonotonicTs,
68 /// Stage processing latency.
69 pub latency: Duration,
70 /// Whether the stage succeeded, failed, or skipped.
71 pub result: StageResult,
72}
73
74/// Outcome of a stage's processing for one frame.
75#[derive(Debug, Clone, PartialEq)]
76pub enum StageResult {
77 /// Stage completed successfully.
78 Ok,
79 /// Stage failed on this frame.
80 Error(StageOutcomeCategory),
81 /// Stage opted out for this frame.
82 Skipped,
83}
84
85/// Typed failure category for stage provenance.
86///
87/// A summary for programmatic filtering and dashboarding.
88/// Full diagnostic detail remains in tracing logs.
89#[derive(Debug, Clone, PartialEq)]
90pub enum StageOutcomeCategory {
91 /// Inference or computation failed.
92 ProcessingFailed,
93 /// Stage ran out of a resource (GPU OOM, buffer limit, etc.).
94 ResourceExhausted,
95 /// Model or external dependency unavailable.
96 DependencyUnavailable,
97 /// Stage panicked (caught by executor).
98 Panic,
99 /// Uncategorized — carries a short, stable tag chosen by the stage author.
100 Other {
101 /// A static tag for filtering (e.g., `"calibration_stale"`).
102 tag: &'static str,
103 },
104}
105
106/// Per-frame provenance of the view system's decisions.
107///
108/// Consumers can audit exactly why the view system made the choices
109/// it did for any given frame.
110#[derive(Debug, Clone)]
111pub struct ViewProvenance {
112 /// The motion source used for this frame.
113 pub motion_source: MotionSource,
114 /// The epoch decision made this frame.
115 /// `None` if the view system was not consulted (no motion detected,
116 /// or `CameraMode::Fixed`).
117 pub epoch_decision: Option<EpochDecision>,
118 /// Transition phase at this frame.
119 pub transition: TransitionPhase,
120 /// Stability score at this frame.
121 pub stability_score: f32,
122 /// View epoch at this frame.
123 pub epoch: ViewEpoch,
124 /// View version at this frame.
125 pub version: ViewVersion,
126}