// Copyright 2025 David Weikersdorfer
syntax = "proto3";
package nodo;
// Report about the status of a NODO app
message Report {
// Metadata information about the app and its node and monitors. Might be sent less frequently
// to reduce bandwidth.
AppMeta meta = 1;
// Current version of the app info. Can be used to detect if previously received app info is
// still up to date.
uint64 app_info_version = 2;
// Status information for each node in the app
AppStatus status = 3;
// Statistics for each node in the app
AppStatistics statistics = 4;
// Signals of each node in the app
AppSignals signals = 5;
// Monitors observing app signals
AppMonitors monitors = 6;
}
message AppMeta {
repeated NodeMeta nodes = 1;
repeated MonitorMeta monitors = 2;
repeated ScheduleMeta schedules = 3;
}
// Immutable metadata about a node
message NodeMeta {
// Unique identifier of a node in the app
uint32 id = 1;
// The name of the schedule in which the node is executed. There is one schedule per worker.
string schedule_name = 2;
// The name of the sequence in which the node is executed. A schedule consists of multiple
// sequences.
string sequence_name = 3;
// The name of the node. The name is guaranteed to be unique across the app
string node_name = 4;
// The typename of the codelet used for this node.
string typename = 5;
// Names of all RX (receiving) channels of this node.
repeated string rx_names = 6;
// Names of all TX (transmitting) channels of this node.
repeated string tx_names = 7;
// Names of all signals of this node.
repeated string signal_names = 8;
}
// Immutable metadata about a monitor
message MonitorMeta {
// Helpful information text for this monitor
string info = 1;
// ID of the node this monitor observes
uint32 node_id = 2;
// Gauge this monitor observes
GaugeKey key = 3;
}
// Immutable metadata about a schedule
message ScheduleMeta {
uint32 id = 1;
// The name of the schedule (same as used by NodeMeta)
string name = 2;
// Schedule execution period (in seconds). If None than the schedule executes as fast as
// possible.
optional float period = 3;
}
message AppStatus {
repeated NodeStatus nodes = 1;
repeated ScheduleStatus schedules = 2;
}
// Execution status of a node
message NodeStatus {
LifecycleStatus lifecycle_status = 3;
// A textual description of the status returned by the last node execution. This can be a
// start, step, stop, etc. function.
string label = 1;
// Indicates whether the last node execution was considered a skipped execution.
bool is_skipped = 2;
}
enum LifecycleStatus {
UNSPECIFIED = 0;
INACTIVE = 1;
STARTING = 2;
RUNNING = 3;
PAUSING = 4;
PAUSED = 5;
RESUMING = 6;
STOPPING = 7;
ERROR = 8;
}
// Execution status of a schedule
message ScheduleStatus {
uint32 id = 1;
LifecycleStatus lifecycle_status = 2;
optional float last_period = 3;
optional string last_error = 4;
bool has_panicked = 5;
bool has_finished = 6;
}
message AppStatistics {
repeated NodeStatistics nodes = 1;
}
// Execution statistics of a node
message NodeStatistics {
// Various statistics for each node transition function. Node transition function are (in this
// order): start, step, stop
repeated TransitionStatistics transitions = 1;
// Number of currently available messages on each RX channel.
// Same order as NodeMeta::rx_names
repeated uint32 rx_available_messages_count = 2;
// Number of total published messages for each TX channel.
// Same order as NodeMeta::tx_names
repeated uint32 tx_published_message_count = 3;
// Time of last transmitted message since app started
repeated Duration tx_last_pubtime = 4;
}
// Time elapsed between two time points. Note that Duration is used for pubtime and acqtime which
// are monotonic clocks measuring the time since the app and system booted resp. uint32 can
// represent a duration of more than 100 years which is sufficient for this purpose.
message Duration {
uint32 secs = 1;
uint32 nanos = 2;
}
message TransitionStatistics {
// Statistics about the duration of the execution (begin to end)
StatisticsSamples duration = 1;
// Statistics about the period of the execution (begin to begin)
StatisticsSamples period = 2;
// Number of executions which are considered skipped.
uint64 skipped_count = 3;
}
message StatisticsSamples {
// Total number of samples
uint64 count = 1;
// Total duration over all samples
float total = 2;
// Minimum duration of all samples. This value is None iff count is 0.
optional float min_ms = 3;
// Maximum duration of all samples. This value is None iff count is 0.
optional float max_ms = 4;
}
message AppSignals {
repeated NodeSignals nodes = 1;
}
// Signal values for of a node
message NodeSignals {
repeated NodeSignal signals = 1;
}
// Time and value of a signal
message NodeSignal {
// Time at which the value was last changed. May be None if value was never set or when the
// node has not executed yet.
Duration pubtime = 1;
// Current value set by the codelet. May be None if value was never set or if the value was
// explicitely cleared.
oneof value {
bool bool = 2;
int64 int64 = 3;
uint64 usize = 4;
double float64 = 5;
string string = 6;
}
}
message AppMonitors {
repeated Monitor monitors = 1;
}
// Information about a monitor observing node gauges (i.e. signals)
message Monitor {
// Last time the gauge value was changed
Duration pubtime = 1;
// Current value of the gauge. Note that the gauge value may not be set in which case this
// field is None. In case an error occurred when retreiving the gauge value this value is
// None and the `value_error` is a non-empty string.
GaugeValue value = 2;
// Error message in case an error occurred when retreiving the gauge value
string value_error = 3;
// Current status of the monitor after evaluating it on the gauge value. If an error occurred
// while evaluating the monitor the status is set to UNSPECIFIED and `status_error` is a non-
// -empty string describing the error.
MonitorStatus status = 4;
// Error message in case an error occurred while evaluating the monitor
string status_error = 5;
}
// Key which unique identifies a gauge in the scope of a node. Gauges are observable quantities
// which can be used be monitors.
message GaugeKey {
// The kind of gauge
GaugeKeyKind kind = 1;
// Name of the gauge
string name = 2;
}
enum GaugeKeyKind {
GAUGE_KEY_KIND_UNSPECIFIED = 0;
// Value of a node signal
GAUGE_KEY_KIND_SIGNAL_VALUE = 1;
// Last time a node signal was changed
GAUGE_KEY_KIND_SIGNAL_PUBTIME = 2;
// Number of messages available on an RX channel (receiver)
GAUGE_KEY_KIND_RX_AVAILABLE = 3;
// Number of messages a TX channel (transmitter) has published since the last node start
GAUGE_KEY_KIND_TX_TOTAL = 4;
// Last time a TX channel (transmitter) published a message as a pubtime (time elapssed since
// the app launched).
GAUGE_KEY_KIND_TX_PUBTIME = 5;
}
message GaugeValue {
oneof value {
bool bool = 1;
int64 int64 = 2;
uint64 usize = 3;
double float64 = 4;
string string = 5;
Duration pubtime = 6;
Duration acqtime = 7;
}
}
enum MonitorStatus {
MONITOR_STATUS_UNSPECIFIED = 0;
// The monitored gauge has a nominal value (OK)
MONITOR_STATUS_NOMINAL = 1;
// The monitored gauge is out of bounds, but not yet critical
MONITOR_STATUS_WARNING = 2;
// The monitored gauge has taken a critical value (error)
MONITOR_STATUS_CRITICAL = 3;
}