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