Skip to main content

ic_query/ic/model/requests/
metrics.rs

1//! Module: ic::model::requests::metrics
2//!
3//! Responsibility: bounded official Dashboard Metrics API request contracts.
4//! Does not own: network resources, canister discovery, transport, or reports.
5//! Boundary: captures one selected aggregate metric and its explicit observation window.
6
7use super::IcDashboardRequest;
8
9use serde::Serialize;
10use std::{fmt, str::FromStr};
11
12///
13/// IcMetricKind
14///
15/// One bounded network metric exposed by the official Dashboard Metrics API.
16///
17
18#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize)]
19#[serde(rename_all = "kebab-case")]
20pub enum IcMetricKind {
21    /// Network instruction execution rate.
22    InstructionRate,
23    /// Network message execution rate.
24    MessageExecutionRate,
25    /// Network cycle burn rate.
26    CycleBurnRate,
27    /// Network block ingestion rate.
28    BlockRate,
29    /// Total and currently up node counts.
30    IcNodeCount,
31    /// Total Subnet count.
32    IcSubnetTotal,
33    /// Running and stopped canister counts.
34    RegisteredCanistersCount,
35    /// Total estimated IC energy-consumption rate in kWh.
36    TotalIcEnergyConsumptionRateKwh,
37    /// Active boundary-node count.
38    BoundaryNodesCount,
39}
40
41impl IcMetricKind {
42    /// Return every metric supported by the bounded report adapter.
43    #[must_use]
44    pub const fn all() -> [Self; 9] {
45        [
46            Self::InstructionRate,
47            Self::MessageExecutionRate,
48            Self::CycleBurnRate,
49            Self::BlockRate,
50            Self::IcNodeCount,
51            Self::IcSubnetTotal,
52            Self::RegisteredCanistersCount,
53            Self::TotalIcEnergyConsumptionRateKwh,
54            Self::BoundaryNodesCount,
55        ]
56    }
57
58    /// Return the official Dashboard Metrics API path name.
59    #[must_use]
60    pub const fn as_str(self) -> &'static str {
61        match self {
62            Self::InstructionRate => "instruction-rate",
63            Self::MessageExecutionRate => "message-execution-rate",
64            Self::CycleBurnRate => "cycle-burn-rate",
65            Self::BlockRate => "block-rate",
66            Self::IcNodeCount => "ic-node-count",
67            Self::IcSubnetTotal => "ic-subnet-total",
68            Self::RegisteredCanistersCount => "registered-canisters-count",
69            Self::TotalIcEnergyConsumptionRateKwh => "total-ic-energy-consumption-rate-kwh",
70            Self::BoundaryNodesCount => "boundary-nodes-count",
71        }
72    }
73
74    #[cfg(feature = "dashboard-host")]
75    pub(crate) const fn series_names(self) -> &'static [&'static str] {
76        match self {
77            Self::InstructionRate => &["instruction_rate"],
78            Self::MessageExecutionRate => &["message_execution_rate"],
79            Self::CycleBurnRate => &["cycle_burn_rate"],
80            Self::BlockRate => &["block_rate"],
81            Self::IcNodeCount => &["total_nodes", "up_nodes"],
82            Self::IcSubnetTotal => &["ic_subnet_total"],
83            Self::RegisteredCanistersCount => &["running_canisters", "stopped_canisters"],
84            Self::TotalIcEnergyConsumptionRateKwh => &["energy_consumption_rate"],
85            Self::BoundaryNodesCount => &["boundary_nodes_count"],
86        }
87    }
88}
89
90impl fmt::Display for IcMetricKind {
91    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
92        formatter.write_str(self.as_str())
93    }
94}
95
96impl FromStr for IcMetricKind {
97    type Err = String;
98
99    fn from_str(value: &str) -> Result<Self, Self::Err> {
100        Self::all()
101            .into_iter()
102            .find(|metric| metric.as_str() == value)
103            .ok_or_else(|| format!("unsupported IC Dashboard metric {value:?}"))
104    }
105}
106
107///
108/// IcMetricQuery
109///
110/// One explicitly bounded official Dashboard metric time-series query.
111///
112
113#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
114pub struct IcMetricQuery {
115    /// Official Dashboard metric to retrieve.
116    pub metric: IcMetricKind,
117    /// Inclusive query start as Unix seconds.
118    pub start_unix_secs: u64,
119    /// Inclusive query end as Unix seconds.
120    pub end_unix_secs: u64,
121    /// Requested observation interval in seconds.
122    pub step_secs: u32,
123}
124
125impl IcMetricQuery {
126    /// Construct one explicit metric query window.
127    #[must_use]
128    pub const fn new(
129        metric: IcMetricKind,
130        start_unix_secs: u64,
131        end_unix_secs: u64,
132        step_secs: u32,
133    ) -> Self {
134        Self {
135            metric,
136            start_unix_secs,
137            end_unix_secs,
138            step_secs,
139        }
140    }
141}
142
143///
144/// IcMetricRequest
145///
146/// Request accepted by the bounded official Dashboard metric report builder.
147///
148
149#[derive(Clone, Debug, Eq, PartialEq)]
150pub struct IcMetricRequest {
151    /// Explicit Dashboard endpoint and caller collection clock.
152    pub dashboard: IcDashboardRequest,
153    /// Explicitly bounded metric query.
154    pub query: IcMetricQuery,
155}
156
157impl IcMetricRequest {
158    /// Construct one bounded live Dashboard metric request.
159    #[must_use]
160    pub const fn new(dashboard: IcDashboardRequest, query: IcMetricQuery) -> Self {
161        Self { dashboard, query }
162    }
163}