s2_api/v1/
metrics.rs

1use compact_str::CompactString;
2use s2_common::types;
3use serde::{Deserialize, Serialize};
4
5#[rustfmt::skip]
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
8#[serde(rename_all = "kebab-case")]
9pub enum TimeseriesInterval {
10    Minute,
11    Hour,
12    Day,
13}
14
15impl From<TimeseriesInterval> for types::metrics::TimeseriesInterval {
16    fn from(value: TimeseriesInterval) -> Self {
17        match value {
18            TimeseriesInterval::Minute => types::metrics::TimeseriesInterval::Minute,
19            TimeseriesInterval::Hour => types::metrics::TimeseriesInterval::Hour,
20            TimeseriesInterval::Day => types::metrics::TimeseriesInterval::Day,
21        }
22    }
23}
24
25impl From<types::metrics::TimeseriesInterval> for TimeseriesInterval {
26    fn from(value: types::metrics::TimeseriesInterval) -> Self {
27        match value {
28            types::metrics::TimeseriesInterval::Minute => Self::Minute,
29            types::metrics::TimeseriesInterval::Hour => Self::Hour,
30            types::metrics::TimeseriesInterval::Day => Self::Day,
31        }
32    }
33}
34
35#[rustfmt::skip]
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema, utoipa::IntoParams))]
38#[cfg_attr(feature = "utoipa", into_params(parameter_in = Query))]
39pub struct AccountMetricSetRequest {
40    /// Metric set to return.
41    pub set: AccountMetricSet,
42    /// Start timestamp as Unix epoch seconds, if applicable for the metric set.
43    pub start: Option<u32>,
44    /// End timestamp as Unix epoch seconds, if applicable for the metric set.
45    pub end: Option<u32>,
46    /// Interval to aggregate over for timeseries metric sets.
47    pub interval: Option<TimeseriesInterval>,
48}
49
50impl From<AccountMetricSetRequest> for types::metrics::AccountMetricsRequest {
51    fn from(value: AccountMetricSetRequest) -> Self {
52        Self {
53            set: match value.set {
54                AccountMetricSet::ActiveBasins => types::metrics::AccountMetricSet::ActiveBasins,
55                AccountMetricSet::AccountOps => types::metrics::AccountMetricSet::AccountOps,
56            },
57            start: value.start,
58            end: value.end,
59            interval: value.interval.map(Into::into),
60        }
61    }
62}
63
64#[rustfmt::skip]
65#[derive(Debug, Clone, Serialize, Deserialize)]
66#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
67#[serde(rename_all = "kebab-case")]
68pub enum AccountMetricSet {
69    /// Set of all basins that had at least one stream during the specified period.
70    ActiveBasins,
71    /// Count of append RPC operations, per interval.
72    AccountOps,
73}
74
75#[rustfmt::skip]
76#[derive(Debug, Clone, Serialize, Deserialize)]
77#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema, utoipa::IntoParams))]
78#[cfg_attr(feature = "utoipa", into_params(parameter_in = Query))]
79pub struct BasinMetricSetRequest {
80    /// Metric set to return.
81    pub set: BasinMetricSet,
82    /// Start timestamp as Unix epoch seconds, if applicable for the metric set.
83    pub start: Option<u32>,
84    /// End timestamp as Unix epoch seconds, if applicable for the metric set.
85    pub end: Option<u32>,
86    /// Interval to aggregate over for timeseries metric sets.
87    pub interval: Option<TimeseriesInterval>,
88}
89
90impl From<BasinMetricSetRequest> for types::metrics::BasinMetricsRequest {
91    fn from(value: BasinMetricSetRequest) -> Self {
92        Self {
93            set: match value.set {
94                BasinMetricSet::AppendOps => types::metrics::BasinMetricSet::AppendOps,
95                BasinMetricSet::AppendThroughput => {
96                    types::metrics::BasinMetricSet::AppendThroughput
97                }
98                BasinMetricSet::BasinOps => types::metrics::BasinMetricSet::BasinOps,
99                BasinMetricSet::ReadOps => types::metrics::BasinMetricSet::ReadOps,
100                BasinMetricSet::ReadThroughput => types::metrics::BasinMetricSet::ReadThroughput,
101                BasinMetricSet::Storage => types::metrics::BasinMetricSet::Storage,
102            },
103            start: value.start,
104            end: value.end,
105            interval: value.interval.map(Into::into),
106        }
107    }
108}
109
110#[rustfmt::skip]
111#[derive(Debug, Clone, Serialize, Deserialize)]
112#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
113#[serde(rename_all = "kebab-case")]
114pub enum BasinMetricSet {
115    /// Amount of stored data, per hour, aggregated over all streams in a basin.
116    Storage,
117    /// Append operations, per interval.
118    AppendOps,
119    /// Read operations, per interval.
120    ReadOps,
121    /// Read bytes, per interval.
122    ReadThroughput,
123    /// Appended bytes, per interval.
124    AppendThroughput,
125    /// Count of basin RPC operations, per interval.
126    BasinOps,
127}
128
129#[rustfmt::skip]
130#[derive(Debug, Clone, Serialize, Deserialize)]
131#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema, utoipa::IntoParams))]
132#[cfg_attr(feature = "utoipa", into_params(parameter_in = Query))]
133pub struct StreamMetricSetRequest {
134    /// Metric set to return.
135    pub set: StreamMetricSet,
136    /// Start timestamp as Unix epoch seconds, if applicable for the metric set.
137    pub start: Option<u32>,
138    /// End timestamp as Unix epoch seconds, if applicable for metric set.
139    pub end: Option<u32>,
140    /// Interval to aggregate over for timeseries metric sets.
141    pub interval: Option<TimeseriesInterval>,
142}
143
144impl From<StreamMetricSetRequest> for types::metrics::StreamMetricsRequest {
145    fn from(value: StreamMetricSetRequest) -> Self {
146        Self {
147            set: match value.set {
148                StreamMetricSet::Storage => types::metrics::StreamMetricSet::Storage,
149            },
150            start: value.start,
151            end: value.end,
152            interval: value.interval.map(Into::into),
153        }
154    }
155}
156
157#[rustfmt::skip]
158#[derive(Debug, Clone, Serialize, Deserialize)]
159#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
160#[serde(rename_all = "kebab-case")]
161pub enum StreamMetricSet {
162    /// Amount of stored data, per minute, for a specific stream.
163    Storage,
164}
165
166#[rustfmt::skip]
167#[derive(Clone, Debug, Serialize, Deserialize)]
168#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
169#[serde(rename_all = "kebab-case")]
170pub enum MetricUnit {
171    Bytes,
172    Operations,
173}
174
175impl From<types::metrics::MetricUnit> for MetricUnit {
176    fn from(value: types::metrics::MetricUnit) -> Self {
177        match value {
178            types::metrics::MetricUnit::Bytes => MetricUnit::Bytes,
179            types::metrics::MetricUnit::Operations => MetricUnit::Operations,
180        }
181    }
182}
183
184#[rustfmt::skip]
185#[derive(Debug, Clone, Serialize, Deserialize)]
186#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
187pub struct ScalarMetric {
188    /// Metric name.
189    #[cfg_attr(feature = "utoipa", schema(value_type = String))]
190    pub name: CompactString,
191    /// Unit of the metric.
192    pub unit: MetricUnit,
193    /// Metric value.
194    pub value: f64,
195}
196
197impl From<types::metrics::ScalarMetric> for ScalarMetric {
198    fn from(value: types::metrics::ScalarMetric) -> Self {
199        Self {
200            name: value.name,
201            unit: value.unit.into(),
202            value: value.value,
203        }
204    }
205}
206
207#[rustfmt::skip]
208#[derive(Debug, Clone, Serialize, Deserialize)]
209#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
210pub struct AccumulationMetric {
211    /// Timeseries name.
212    #[cfg_attr(feature = "utoipa", schema(value_type = String))]
213    pub name: CompactString,
214    /// Unit of the metric.
215    pub unit: MetricUnit,
216    /// The interval at which data points are accumulated.
217    pub interval: TimeseriesInterval,
218    /// Timeseries values.
219    /// Each element is a tuple of a timestamp in Unix epoch seconds and a data point.
220    /// The data point represents the accumulated value for the time period starting at the timestamp, spanning one `interval`.
221    pub values: Vec<(u32, f64)>,
222}
223
224impl From<types::metrics::AccumulationMetric> for AccumulationMetric {
225    fn from(value: types::metrics::AccumulationMetric) -> Self {
226        Self {
227            name: value.name,
228            unit: value.unit.into(),
229            interval: value.interval.into(),
230            values: value.values,
231        }
232    }
233}
234
235#[rustfmt::skip]
236#[derive(Debug, Clone, Serialize, Deserialize)]
237#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
238pub struct GaugeMetric {
239    /// Timeseries name.
240    #[cfg_attr(feature = "utoipa", schema(value_type = String))]
241    pub name: CompactString,
242    /// Unit of the metric.
243    pub unit: MetricUnit,
244    /// Timeseries values.
245    /// Each element is a tuple of a timestamp in Unix epoch seconds and a data point.
246    /// The data point represents the value at the instant of the timestamp.
247    pub values: Vec<(u32, f64)>,
248}
249
250impl From<types::metrics::GaugeMetric> for GaugeMetric {
251    fn from(value: types::metrics::GaugeMetric) -> Self {
252        Self {
253            name: value.name,
254            unit: value.unit.into(),
255            values: value.values,
256        }
257    }
258}
259
260#[rustfmt::skip]
261#[derive(Debug, Clone, Serialize, Deserialize)]
262#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
263pub struct LabelMetric {
264    /// Label name.
265    #[cfg_attr(feature = "utoipa", schema(value_type = String))]
266    pub name: CompactString,
267    /// Label values.
268    pub values: Vec<String>,
269}
270
271impl From<types::metrics::LabelMetric> for LabelMetric {
272    fn from(value: types::metrics::LabelMetric) -> Self {
273        Self {
274            name: value.name,
275            values: value.values,
276        }
277    }
278}
279
280#[rustfmt::skip]
281#[derive(Debug, Clone, Serialize, Deserialize)]
282#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
283#[serde(rename_all = "kebab-case")]
284pub enum Metric {
285    /// Single named value.
286    Scalar(ScalarMetric),
287    /// Named series of `(timestamp, value)` points representing an accumulation over a specified interval.
288    Accumulation(AccumulationMetric),
289    /// Named series of `(timestamp, value)` points each representing an instantaneous value.
290    Gauge(GaugeMetric),
291    /// Set of string labels.
292    Label(LabelMetric),
293}
294
295impl From<types::metrics::Metric> for Metric {
296    fn from(value: types::metrics::Metric) -> Self {
297        match value {
298            types::metrics::Metric::Scalar(scalar) => Metric::Scalar(scalar.into()),
299            types::metrics::Metric::Accumulation(timeseries) => {
300                Metric::Accumulation(timeseries.into())
301            }
302            types::metrics::Metric::Gauge(timeseries) => Metric::Gauge(timeseries.into()),
303            types::metrics::Metric::Label(label) => Metric::Label(label.into()),
304        }
305    }
306}
307
308#[rustfmt::skip]
309#[derive(Debug, Clone, Serialize, Deserialize)]
310#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
311pub struct MetricSetResponse {
312    /// Metrics comprising the set.
313    pub values: Vec<Metric>,
314}
315
316impl From<types::metrics::MetricsResponse> for MetricSetResponse {
317    fn from(value: types::metrics::MetricsResponse) -> Self {
318        Self {
319            values: value.values.into_iter().map(Into::into).collect(),
320        }
321    }
322}