Skip to main content

mpl_lang/
types.rs

1//! Generic datatypes for `MPL`
2use std::ops::Deref;
3
4use miette::SourceSpan;
5use serde::{Deserialize, Serialize};
6pub use strumbra::Error as StrumbraError;
7use strumbra::SharedString;
8
9use crate::{
10    linker::{Arg, ArgType, FunctionTrait},
11    query::ParamDeclaration,
12};
13
14/// A dataset identifier
15#[derive(
16    Debug,
17    Clone,
18    PartialEq,
19    Eq,
20    Hash,
21    // needed for the axum path extractor
22    serde::Serialize,
23    serde::Deserialize,
24)]
25#[cfg_attr(feature = "bincode", derive(bincode::Decode, bincode::Encode))]
26pub struct Dataset(String);
27
28impl From<&str> for Dataset {
29    fn from(value: &str) -> Self {
30        Dataset(value.to_string())
31    }
32}
33impl PartialEq<str> for Dataset {
34    fn eq(&self, other: &str) -> bool {
35        self.0 == *other
36    }
37}
38
39impl PartialEq<&str> for Dataset {
40    fn eq(&self, other: &&str) -> bool {
41        &*self.0 == *other
42    }
43}
44
45impl Dataset {
46    /// Creates a new dataset.
47    #[must_use]
48    pub fn new(name: String) -> Self {
49        Self(name)
50    }
51}
52
53impl Deref for Dataset {
54    type Target = String;
55
56    fn deref(&self) -> &Self::Target {
57        &self.0
58    }
59}
60
61impl std::fmt::Display for Dataset {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        self.0.fmt(f)
64    }
65}
66
67/// A type that can either be concrete or a param.
68#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
69pub enum Parameterized<T> {
70    /// A concrete type
71    Concrete(T),
72    /// A parameter and the location where it's used (for type checking)
73    Param {
74        /// The location where the param is used
75        span: SourceSpan,
76        /// The param
77        param: ParamDeclaration,
78    },
79}
80
81impl<T> std::fmt::Display for Parameterized<T>
82where
83    T: std::fmt::Display,
84{
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        match self {
87            Parameterized::Concrete(inner) => write!(f, "{inner}"),
88            Parameterized::Param { span: _, param } => write!(f, "${}", param.name),
89        }
90    }
91}
92
93impl<T> Parameterized<T> {
94    /// Map the concrete value.
95    pub fn map_concrete<O, F: Fn(T) -> O>(self, f: F) -> Parameterized<O> {
96        match self {
97            Parameterized::Concrete(inner) => Parameterized::Concrete(f(inner)),
98            Parameterized::Param { span, param } => Parameterized::Param { span, param },
99        }
100    }
101
102    /// Try to map the concrete value.
103    pub fn try_map_concrete<O, E, F: Fn(T) -> Result<O, E>>(
104        self,
105        f: F,
106    ) -> Result<Parameterized<O>, E> {
107        Ok(match self {
108            Parameterized::Concrete(inner) => Parameterized::Concrete(f(inner)?),
109            Parameterized::Param { span, param } => Parameterized::Param { span, param },
110        })
111    }
112
113    /// Returns true if the type is a param.
114    pub fn is_param(&self) -> bool {
115        matches!(self, Parameterized::Param { .. })
116    }
117
118    /// Returns true if the type is a concrete value.
119    pub fn is_concrete(&self) -> bool {
120        matches!(self, Parameterized::Concrete(_))
121    }
122}
123
124/// A metric identifier
125#[derive(
126    Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Deserialize, serde::Serialize,
127)]
128#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
129pub struct Metric(#[cfg_attr(feature = "bincode", bincode(with_serde))] SharedString);
130
131impl std::fmt::Display for Metric {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        self.0.fmt(f)
134    }
135}
136
137impl PartialEq<str> for Metric {
138    fn eq(&self, other: &str) -> bool {
139        &*self.0 == other
140    }
141}
142
143impl Deref for Metric {
144    type Target = str;
145
146    fn deref(&self) -> &Self::Target {
147        &self.0
148    }
149}
150
151impl Metric {
152    /// Creates a new metric.
153    pub fn new(name: &str) -> Result<Self, StrumbraError> {
154        Ok(Self(SharedString::try_from(name)?))
155    }
156}
157
158impl TryFrom<String> for Metric {
159    type Error = StrumbraError;
160
161    fn try_from(s: String) -> Result<Self, Self::Error> {
162        Ok(Metric(SharedString::try_from(s)?))
163    }
164}
165
166impl TryFrom<&'_ str> for Metric {
167    type Error = StrumbraError;
168
169    fn try_from(s: &str) -> Result<Self, Self::Error> {
170        Ok(Metric(SharedString::try_from(s)?))
171    }
172}
173
174impl PartialEq<&str> for Metric {
175    fn eq(&self, other: &&str) -> bool {
176        &*self.0 == *other
177    }
178}
179
180/// The method for cumulative-to-delta conversion
181#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
182#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
183pub enum ConversionMethod {
184    /// Use rate to convert cumulative to delta
185    #[default]
186    Rate,
187    /// Use increase to convert cumulative to delta
188    Increase,
189}
190
191impl std::fmt::Display for ConversionMethod {
192    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193        match self {
194            ConversionMethod::Rate => write!(f, "rate"),
195            ConversionMethod::Increase => write!(f, "increase"),
196        }
197    }
198}
199
200/// Aggregation type
201#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
202pub enum BucketType {
203    /// Histogram
204    Histogram,
205    /// Interpolate delta histogram based on histogram data in the store
206    InterpolateDeltaHistogram,
207    /// Interpolate cumulative histogram with a specified conversion mode
208    InterpolateCumulativeHistogram(ConversionMethod),
209}
210
211impl FunctionTrait for BucketType {
212    fn doc(&self) -> &str {
213        match self {
214            BucketType::Histogram => {
215                "Aggregates non-histogram input series using the provided bucket specs (including histogram quantile calculation)."
216            }
217            BucketType::InterpolateDeltaHistogram => {
218                "Aggregates delta-temporality histogram input series using the provided bucket specs (including histogram quantile calculation via interpolation)."
219            }
220            BucketType::InterpolateCumulativeHistogram(_) => {
221                "Aggregates cumulative-temporality histogram input series after converting to delta using a conversion mode (including histogram quantile calculation via interpolation)."
222            }
223        }
224    }
225
226    fn args(&self) -> Vec<Arg> {
227        match self {
228            BucketType::InterpolateCumulativeHistogram(_) => vec![
229                Arg::new("mode", ArgType::Enum(&["rate", "increase"])),
230                Arg::new(
231                    "specs",
232                    ArgType::Repeated {
233                        typ: Box::new(ArgType::OneOf(vec![
234                            // cumulative does not support min/max as bucket spec
235                            ArgType::Enum(&["count", "avg", "sum"]),
236                            ArgType::Float,
237                        ])),
238                        min: 1,
239                        max: None,
240                    },
241                ),
242            ],
243            BucketType::Histogram | BucketType::InterpolateDeltaHistogram => vec![Arg::new(
244                "specs",
245                ArgType::Repeated {
246                    typ: Box::new(ArgType::OneOf(vec![
247                        ArgType::Enum(&["count", "avg", "sum", "min", "max"]),
248                        ArgType::Float,
249                    ])),
250                    min: 1,
251                    max: None,
252                },
253            )],
254        }
255    }
256}
257
258impl std::fmt::Display for BucketType {
259    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260        match self {
261            BucketType::Histogram => write!(f, "histogram"),
262            BucketType::InterpolateDeltaHistogram => write!(f, "interpolate_delta_histogram"),
263            BucketType::InterpolateCumulativeHistogram(_) => {
264                write!(f, "interpolate_cumulative_histogram")
265            }
266        }
267    }
268}
269
270/// Aggregation type
271#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
272pub enum MapType {
273    /// Min
274    Min,
275    /// Max
276    Max,
277    /// Rate
278    Rate,
279    /// Add
280    Add,
281    /// Sub
282    Sub,
283    /// Mul
284    Mul,
285    /// Div
286    Div,
287    /// Abs
288    Abs,
289    /// fill with constant
290    FillConst,
291    /// fill with previous value
292    FillPrev,
293    /// Increase between points
294    Increase,
295    /// lesser than
296    FilterLt,
297    /// greater than
298    FilterGt,
299    /// equal to
300    FilterEq,
301    /// not equal to
302    FilterNe,
303    /// greater than or equal to
304    FilterGe,
305    /// less than or equal to
306    FilterLe,
307    /// lesser than
308    IsLt,
309    /// greater than
310    IsGt,
311    /// equal to
312    IsEq,
313    /// not equal to
314    IsNe,
315    /// greater than or equal to
316    IsGe,
317    /// less than or equal to
318    IsLe,
319    /// Linear interpolation
320    InterpolateLinear,
321}
322
323impl FunctionTrait for MapType {
324    fn doc(&self) -> &str {
325        match self {
326            MapType::Min => "Minimum between the argument and the datapoint",
327            MapType::Max => "Maximum between the argument and the datapoint",
328            MapType::Add => "Adds the argument to the datapoint",
329            MapType::Sub => "Subtracts the argument from the datapoint",
330            MapType::Mul => "Multiplies the argument with the datapoint",
331            MapType::Div => "Divides the datapoint by the argument",
332            MapType::Abs => "Absolute value of the datapoint",
333            MapType::Rate => {
334                "Per second rate of change between the datapoint and the previous datapoint"
335            }
336            MapType::FillConst => "Fills unset datapoints with the given constant",
337            MapType::FillPrev => "Fills unset datapoints with the previous datapoint",
338            MapType::Increase => {
339                "Calculates the increase between the datapoint and the previous datapoint"
340            }
341            MapType::FilterLt => {
342                "Filters for datapoints that are less than the argument all datapoints not less than the argument are removed"
343            }
344            MapType::FilterGt => {
345                "Filters for datapoints that are greater than the argument all datapoints not greater than the argument are removed"
346            }
347            MapType::FilterEq => {
348                "Filters for datapoints that are equal to the argument all datapoints not equal to the argument are removed"
349            }
350            MapType::FilterNe => {
351                "Filters for datapoints that are not equal to the argument all datapoints equal to the argument are removed"
352            }
353            MapType::FilterGe => {
354                "Filters for datapoints that are greater than or equal to the argument all datapoints not greater than or equal to the argument are removed"
355            }
356            MapType::FilterLe => {
357                "Filters for datapoints that are less than or equal to the argument all datapoints not less than or equal to the argument are removed"
358            }
359            MapType::IsLt => {
360                "Sets the datapoint to 1.0 if the datapoint is less than the argument otherwise sets it to 0.0"
361            }
362            MapType::IsGt => {
363                "Sets the datapoint to 1.0 if the datapoint is greater than the argument otherwise sets it to 0.0"
364            }
365            MapType::IsEq => {
366                "Sets the datapoint to 1.0 if the datapoint is equal to the argument otherwise sets it to 0.0"
367            }
368            MapType::IsNe => {
369                "Sets the datapoint to 1.0 if the datapoint is not equal to the argument otherwise sets it to 0.0"
370            }
371            MapType::IsLe => {
372                "Sets the datapoint to 1.0 if the datapoint is less than or equal to the argument otherwise sets it to 0.0"
373            }
374            MapType::IsGe => {
375                "Sets the datapoint to 1.0 if the datapoint is greater than or equal to the argument otherwise sets it to 0.0"
376            }
377            MapType::InterpolateLinear => {
378                "Performs linear interpolation between two datapoints filling unset values with the interpolated value"
379            }
380        }
381    }
382    fn args(&self) -> Vec<Arg> {
383        match self {
384            MapType::FilterLt
385            | MapType::FilterGt
386            | MapType::FilterEq
387            | MapType::FilterNe
388            | MapType::FilterGe
389            | MapType::FilterLe
390            | MapType::IsLt
391            | MapType::IsGt
392            | MapType::IsEq
393            | MapType::IsNe
394            | MapType::IsGe
395            | MapType::IsLe
396            | MapType::Add
397            | MapType::Sub
398            | MapType::Mul
399            | MapType::Div
400            | MapType::FillConst => vec![Arg::new("value", ArgType::Float)],
401            MapType::Min => vec![Arg::new("min", ArgType::Float)],
402            MapType::Max => vec![Arg::new("max", ArgType::Float)],
403            MapType::Abs
404            | MapType::Rate
405            | MapType::FillPrev
406            | MapType::Increase
407            | MapType::InterpolateLinear => {
408                vec![]
409            }
410        }
411    }
412}
413
414impl std::fmt::Display for MapType {
415    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
416        match self {
417            MapType::Min => write!(f, "min"),
418            MapType::Max => write!(f, "max"),
419            MapType::Rate => write!(f, "rate"),
420            MapType::Add => write!(f, "+"),
421            MapType::Sub => write!(f, "-"),
422            MapType::Mul => write!(f, "*"),
423            MapType::Div => write!(f, "/"),
424            MapType::Abs => write!(f, "abs"),
425            MapType::FillConst => write!(f, "fill::const"),
426            MapType::FillPrev => write!(f, "fill::prev"),
427            MapType::Increase => write!(f, "increase"),
428            MapType::FilterLt => write!(f, "filter::lt"),
429            MapType::FilterGt => write!(f, "filter::gt"),
430            MapType::FilterEq => write!(f, "filter::eq"),
431            MapType::FilterNe => write!(f, "filter::ne"),
432            MapType::FilterGe => write!(f, "filter::ge"),
433            MapType::FilterLe => write!(f, "filter::le"),
434            MapType::IsLt => write!(f, "Is::lt"),
435            MapType::IsGt => write!(f, "Is::gt"),
436            MapType::IsEq => write!(f, "Is::eq"),
437            MapType::IsNe => write!(f, "Is::ne"),
438            MapType::IsGe => write!(f, "Is::ge"),
439            MapType::IsLe => write!(f, "Is::le"),
440            MapType::InterpolateLinear => write!(f, "linear"),
441        }
442    }
443}
444
445/// Aggregation type
446#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
447pub enum TimeType {
448    /// Count
449    Count,
450    /// Sum
451    Sum,
452    /// Average
453    Avg,
454    /// Min
455    Min,
456    /// Max
457    Max,
458    /// average rate over time
459    Rate,
460    /// Last observed
461    Last,
462}
463impl FunctionTrait for TimeType {
464    fn doc(&self) -> &str {
465        match self {
466            TimeType::Count => "Count the number of elements",
467            TimeType::Sum => "Sum the elements",
468            TimeType::Avg => "Average the elements",
469            TimeType::Min => "Minimum of the elements",
470            TimeType::Max => "Maximum of the elements",
471            TimeType::Rate => "Average per second rate over a time window",
472            TimeType::Last => "Last observed value",
473        }
474    }
475
476    fn args(&self) -> Vec<Arg> {
477        vec![]
478    }
479}
480
481impl std::fmt::Display for TimeType {
482    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
483        match self {
484            TimeType::Count => write!(f, "count"),
485            TimeType::Sum => write!(f, "sum"),
486            TimeType::Avg => write!(f, "avg"),
487            TimeType::Min => write!(f, "min"),
488            TimeType::Max => write!(f, "max"),
489            TimeType::Rate => write!(f, "prom::rate"),
490            TimeType::Last => write!(f, "last"),
491        }
492    }
493}
494
495/// Aggregation type
496#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
497pub enum TagsType {
498    /// Count
499    Count,
500    /// Sum
501    Sum,
502    /// Average
503    Avg,
504    /// Min
505    Min,
506    /// Max
507    Max,
508}
509
510impl FunctionTrait for TagsType {
511    fn doc(&self) -> &str {
512        match self {
513            TagsType::Count => "Counts the number of set values",
514            TagsType::Sum => "Sums the datapoints",
515            TagsType::Avg => "Averages the datapoints",
516            TagsType::Min => "The minimum value",
517            TagsType::Max => "The maximum value",
518        }
519    }
520    fn args(&self) -> Vec<Arg> {
521        match self {
522            TagsType::Count | TagsType::Sum | TagsType::Avg | TagsType::Min | TagsType::Max => {
523                vec![]
524            }
525        }
526    }
527}
528
529impl std::fmt::Display for TagsType {
530    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
531        match self {
532            TagsType::Count => write!(f, "count"),
533            TagsType::Sum => write!(f, "sum"),
534            TagsType::Avg => write!(f, "avg"),
535            TagsType::Min => write!(f, "min"),
536            TagsType::Max => write!(f, "max"),
537        }
538    }
539}
540
541/// Aggregation type used in Compute
542#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
543pub enum ComputeType {
544    /// Average
545    Avg,
546    /// Min
547    Min,
548    /// Max
549    Max,
550    /// Add
551    Add,
552    /// Subtraction
553    Sub,
554    /// Multiplication
555    Mul,
556    /// Division
557    Div,
558}
559
560impl FunctionTrait for ComputeType {
561    fn doc(&self) -> &str {
562        match self {
563            ComputeType::Add => "Sums the datapoints",
564            ComputeType::Avg => "Averages the datapoints",
565            ComputeType::Min => "The minimum value",
566            ComputeType::Max => "The maximum value",
567            ComputeType::Div => "Divides the datapoints, removes datapoints if the divisor is zero",
568            ComputeType::Mul => "Multiplies the datapoints",
569            ComputeType::Sub => "Subtracts the datapoints",
570        }
571    }
572    fn args(&self) -> Vec<Arg> {
573        match self {
574            ComputeType::Add
575            | ComputeType::Avg
576            | ComputeType::Min
577            | ComputeType::Max
578            | ComputeType::Div
579            | ComputeType::Mul
580            | ComputeType::Sub => vec![],
581        }
582    }
583}
584
585impl std::fmt::Display for ComputeType {
586    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
587        match self {
588            ComputeType::Avg => write!(f, "avg"),
589            ComputeType::Min => write!(f, "min"),
590            ComputeType::Max => write!(f, "max"),
591            ComputeType::Div => write!(f, "/"),
592            ComputeType::Mul => write!(f, "*"),
593            ComputeType::Add => write!(f, "+"),
594            ComputeType::Sub => write!(f, "-"),
595        }
596    }
597}
598
599/// Bucket aggregation Histogram bucket sepcification
600#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
601#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
602pub enum BucketSpec {
603    /// Number of elements
604    #[default]
605    Count,
606    /// Average of elemetns
607    Avg,
608    /// Sum of all elements
609    Sum,
610    /// Minimal value
611    Min,
612    /// Maximal value
613    Max,
614    /// Percentile
615    Percentile(f64),
616}
617
618impl std::fmt::Display for BucketSpec {
619    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
620        match self {
621            BucketSpec::Count => write!(f, "count"),
622            BucketSpec::Avg => write!(f, "avg"),
623            BucketSpec::Sum => write!(f, "sum"),
624            BucketSpec::Min => write!(f, "min"),
625            BucketSpec::Max => write!(f, "max"),
626            BucketSpec::Percentile(p) => write!(f, "{p}"),
627        }
628    }
629}