Skip to main content

rill_core/queues/
telemetry.rs

1//! Telemetry types — event data from the signal processing world.
2
3use crate::traits::{NodeId, ParameterId, PortId};
4use std::fmt;
5use std::time::{SystemTime, UNIX_EPOCH};
6
7/// Event kind for clock tick telemetry.
8pub const CLOCK_TICK: &str = "clock_tick";
9/// Event kind for clock tempo telemetry.
10pub const CLOCK_TEMPO: &str = "clock_tempo";
11
12/// Telemetry type identifier.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum TelemetryKind {
15    /// Parameter value telemetry.
16    Parameter,
17    /// Signal data (signal processing, sensor readings).
18    Signal,
19    /// Peak value telemetry.
20    Peak,
21    /// Event telemetry.
22    Event,
23    /// Micro-control violation telemetry.
24    Violation,
25}
26
27impl fmt::Display for TelemetryKind {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            TelemetryKind::Parameter => write!(f, "parameter"),
31            TelemetryKind::Signal => write!(f, "signal"),
32            TelemetryKind::Peak => write!(f, "peak"),
33            TelemetryKind::Event => write!(f, "event"),
34            TelemetryKind::Violation => write!(f, "violation"),
35        }
36    }
37}
38
39/// Telemetry data emitted by signal graph nodes.
40#[derive(Debug, Clone)]
41pub enum Telemetry {
42    /// A parameter value change.
43    ParameterValue {
44        /// Target port.
45        port: PortId,
46        /// Target parameter.
47        parameter: ParameterId,
48        /// Current parameter value.
49        value: f32,
50        /// Unix timestamp (microseconds).
51        timestamp: u64,
52    },
53    /// Signal or sensor signal data.
54    SignalData {
55        /// Source node ID.
56        node_id: NodeId,
57        /// Channel index.
58        channel: usize,
59        /// Signal sample data.
60        data: Vec<f32>,
61        /// Unix timestamp (microseconds).
62        timestamp: u64,
63        /// Sample rate of the signal.
64        sample_rate: f32,
65    },
66    /// Peak value reading.
67    Peak {
68        /// Target port.
69        port: PortId,
70        /// Peak value.
71        value: f32,
72        /// Unix timestamp (microseconds).
73        timestamp: u64,
74        /// Optional hold time in milliseconds.
75        hold_time_ms: Option<u32>,
76    },
77    /// Named event with float payload.
78    Event {
79        /// Source component name.
80        source: String,
81        /// Event kind string.
82        kind: String,
83        /// Event data payload.
84        data: Vec<f32>,
85        /// Unix timestamp (microseconds).
86        timestamp: u64,
87        /// Optional human-readable description.
88        description: Option<String>,
89    },
90    /// Micro-control timing violation.
91    Violation {
92        /// Component that exceeded its time budget.
93        component: String,
94        /// Expected execution time (nanoseconds).
95        expected_ns: u64,
96        /// Actual execution time (nanoseconds).
97        actual_ns: u64,
98        /// Optional associated value.
99        value: Option<f32>,
100        /// Unix timestamp (microseconds).
101        timestamp: u64,
102    },
103}
104
105impl Telemetry {
106    /// Return the current Unix time in microseconds.
107    pub fn now() -> u64 {
108        SystemTime::now()
109            .duration_since(UNIX_EPOCH)
110            .unwrap_or_default()
111            .as_micros() as u64
112    }
113
114    /// Create a parameter value telemetry event.
115    pub fn parameter(port: PortId, parameter: ParameterId, value: f32) -> Self {
116        Telemetry::ParameterValue {
117            port,
118            parameter,
119            value,
120            timestamp: Self::now(),
121        }
122    }
123
124    /// Create an event telemetry event.
125    pub fn event(source: impl Into<String>, kind: impl Into<String>, data: Vec<f32>) -> Self {
126        Telemetry::Event {
127            source: source.into(),
128            kind: kind.into(),
129            data,
130            timestamp: Self::now(),
131            description: None,
132        }
133    }
134
135    /// Create an event telemetry event with a description.
136    pub fn event_with_description(
137        source: impl Into<String>,
138        kind: impl Into<String>,
139        data: Vec<f32>,
140        description: impl Into<String>,
141    ) -> Self {
142        Telemetry::Event {
143            source: source.into(),
144            kind: kind.into(),
145            data,
146            timestamp: Self::now(),
147            description: Some(description.into()),
148        }
149    }
150
151    /// Create a micro-control violation telemetry event.
152    pub fn violation(
153        component: impl Into<String>,
154        expected_ns: u64,
155        actual_ns: u64,
156        value: Option<f32>,
157    ) -> Self {
158        Telemetry::Violation {
159            component: component.into(),
160            expected_ns,
161            actual_ns,
162            value,
163            timestamp: Self::now(),
164        }
165    }
166
167    /// Return the telemetry type category.
168    pub fn kind(&self) -> TelemetryKind {
169        match self {
170            Telemetry::ParameterValue { .. } => TelemetryKind::Parameter,
171            Telemetry::SignalData { .. } => TelemetryKind::Signal,
172            Telemetry::Peak { .. } => TelemetryKind::Peak,
173            Telemetry::Event { .. } => TelemetryKind::Event,
174            Telemetry::Violation { .. } => TelemetryKind::Violation,
175        }
176    }
177}