1use std::{
2 collections::HashMap,
3 fmt::{self, Write},
4 sync::Arc,
5};
6
7use auto_ops::impl_op_ex;
8
9use crate::internal::{render_label_values, RenderableMetricValue};
10
11pub type Timestamp = f64;
12
13#[derive(Debug, Clone, PartialEq)]
21pub struct Exemplar {
22 pub labels: HashMap<String, String>,
23 pub timestamp: Option<f64>,
24 pub id: f64,
25}
26
27impl Exemplar {
28 pub fn new(labels: HashMap<String, String>, id: f64, timestamp: Option<f64>) -> Exemplar {
29 Exemplar {
30 labels,
31 id,
32 timestamp,
33 }
34 }
35}
36
37impl fmt::Display for Exemplar {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 let names: Vec<&str> = self.labels.keys().map(|s| s.as_str()).collect();
40 let values: Vec<&str> = self.labels.keys().map(|s| s.as_str()).collect();
41 write!(f, "# {} {}", render_label_values(&names, &values), self.id)?;
42 if let Some(timestamp) = self.timestamp {
43 write!(f, " {}", format_float(timestamp))?;
44 }
45
46 Ok(())
47 }
48}
49
50#[derive(Debug)]
55pub struct MetricFamily<TypeSet, ValueType> {
56 pub family_name: String,
57 label_names: Arc<Vec<String>>,
58 pub family_type: TypeSet,
59 pub help: String,
60 pub unit: String,
61 metrics: Vec<Sample<ValueType>>,
62}
63
64impl<TypeSet, ValueType> MetricFamily<TypeSet, ValueType>
65where
66 TypeSet: Clone,
67 ValueType: RenderableMetricValue + Clone,
68{
69 pub fn new(
70 family_name: String,
71 label_names: Vec<String>,
72 family_type: TypeSet,
73 help: String,
74 unit: String,
75 ) -> Self {
76 Self {
77 family_name,
78 label_names: Arc::new(label_names),
79 family_type,
80 help,
81 unit,
82 metrics: Vec::new(),
83 }
84 }
85
86 pub fn get_label_names(&self) -> &[String] {
87 return self.label_names.as_ref().as_slice();
88 }
89
90 pub fn clone_and_convert_type<T: RenderableMetricValue + Clone>(&self) -> MetricFamily<TypeSet, T> where T: From<ValueType> {
91 MetricFamily {
92 family_name: self.family_name.clone(),
93 label_names: Arc::new((*self.label_names).clone()),
94 family_type: self.family_type.clone(),
95 help: self.help.clone(),
96 unit: self.unit.clone(),
97 metrics: self
98 .metrics
99 .iter()
100 .map(|m| m.clone_with_new_value(m.value.clone().into()))
101 .collect(),
102 }
103 }
104
105 pub fn with_labels<'a, T>(&self, labels: T) -> Self
106 where
107 T: IntoIterator<Item = (&'a str, &'a str)>,
108 {
109 let mut label_names = self.label_names.as_ref().clone();
110 let mut samples = self.metrics.clone();
111 for (k, v) in labels {
112 match label_names.binary_search(&k.to_owned() ) {
113 Ok(idx) => {
114 for sample in samples.iter_mut() {
115 sample.label_values[idx] = v.to_owned();
116 }
117 }
118 Err(idx) => {
119 label_names.insert(idx, k.to_owned());
120 for sample in samples.iter_mut() {
121 sample.label_values.insert(idx,v.to_owned());
122 }
123 }
124 }
125 }
126
127 Self::new(
128 self.family_name.clone(),
129 label_names,
130 self.family_type.clone(),
131 self.help.clone(),
132 self.unit.clone(),
133 )
134 .with_samples(samples)
135 .unwrap()
136 }
137
138 pub fn without_label(&self, label_name: &str) -> Result<Self, ParseError> {
139 match self.label_names.iter().position(|n| n == label_name) {
140 Some(idx) => {
141 let mut label_names = self.label_names.as_ref().clone();
142 label_names.remove(idx);
143 let mut base = Self::new(
144 self.family_name.clone(),
145 label_names,
146 self.family_type.clone(),
147 self.help.clone(),
148 self.unit.clone(),
149 );
150
151 for sample in self.metrics.iter() {
152 let mut label_values = sample.label_values.clone();
153 label_values.remove(idx);
154 let new_sample =
155 Sample::new(label_values, sample.timestamp, sample.value.clone());
156 base.add_sample(new_sample)?;
157 }
158
159 Ok(base)
160 }
161 None => Err(ParseError::InvalidMetric(format!(
162 "No label `{}` in metric family",
163 label_name
164 ))),
165 }
166 }
167
168 pub fn into_iter_samples(self) -> impl Iterator<Item = Sample<ValueType>> {
169 self.metrics.into_iter()
170 }
171
172 pub fn iter_samples(&self) -> impl Iterator<Item = &Sample<ValueType>> {
173 self.metrics.iter()
174 }
175
176 pub fn iter_samples_mut(&mut self) -> impl Iterator<Item = &mut Sample<ValueType>> {
177 self.metrics.iter_mut()
178 }
179
180 pub fn with_samples<T>(mut self, samples: T) -> Result<Self, ParseError>
181 where
182 T: IntoIterator<Item = Sample<ValueType>>,
183 {
184 for sample in samples {
185 self.add_sample(sample)?;
186 }
187
188 Ok(self)
189 }
190
191 pub fn get_sample_matches(&self, sample: &Sample<ValueType>) -> Option<&Sample<ValueType>> {
192 return self
193 .metrics
194 .iter()
195 .find(|&s| s.label_values == sample.label_values);
196 }
197
198 pub fn get_sample_matches_mut(
199 &mut self,
200 sample: &Sample<ValueType>,
201 ) -> Option<&mut Sample<ValueType>> {
202 return self
203 .metrics
204 .iter_mut()
205 .find(|s| s.label_values == sample.label_values);
206 }
207
208 pub fn get_sample_by_label_values(
209 &self,
210 label_values: &[String],
211 ) -> Option<&Sample<ValueType>> {
212 return self.metrics.iter().find(|s| s.label_values == label_values);
213 }
214
215 pub fn get_sample_by_label_values_mut(
216 &mut self,
217 label_values: &[String],
218 ) -> Option<&mut Sample<ValueType>> {
219 return self
220 .metrics
221 .iter_mut()
222 .find(|s| s.label_values == label_values);
223 }
224
225 pub fn get_sample_by_labelset(&self, labelset: &LabelSet) -> Option<&Sample<ValueType>> {
226 return self.metrics.iter().find(|s| labelset.matches_sample(s));
227 }
228
229 pub fn get_sample_by_labelset_mut(
230 &mut self,
231 labelset: &LabelSet,
232 ) -> Option<&mut Sample<ValueType>> {
233 return self.metrics.iter_mut().find(|s| labelset.matches_sample(s));
234 }
235
236 pub fn set_label(&mut self, label_name: &str, label_value: &str) -> Result<(), ParseError> {
237 let index = match self.label_names.iter().position(|s| s == label_name) {
238 Some(position) => position,
239 None => {
240 return Err(ParseError::ParseError(format!(
241 "No Label {} on Metric Family",
242 label_name
243 )));
244 }
245 };
246
247 for metric in self.metrics.iter_mut() {
248 if index == metric.label_values.len() {
249 metric.label_values.push(label_value.to_owned());
250 } else {
251 metric.label_values[index] = label_value.to_owned();
252 }
253 }
254
255 Ok(())
256 }
257
258 pub fn add_sample(&mut self, mut s: Sample<ValueType>) -> Result<(), ParseError> {
259 if s.label_values.len() != self.label_names.len() {
260 return Err(ParseError::InvalidMetric(format!(
261 "Cannot add a sample with {} labels into a family with {}",
262 s.label_values.len(),
263 self.label_names.len()
264 )));
265 }
266
267 if self.get_sample_by_label_values(&s.label_values).is_some() {
268 return Err(ParseError::InvalidMetric(format!(
269 "Cannot add a duplicate metric to a MetricFamily (Label Values: {:?})",
270 s.label_values
271 )));
272 }
273
274 s.set_label_names(self.label_names.clone());
275 self.metrics.push(s);
276
277 Ok(())
278 }
279}
280
281impl<TypeSet, ValueType> fmt::Display for MetricFamily<TypeSet, ValueType>
282where
283 TypeSet: fmt::Display + Default + PartialEq,
284 ValueType: RenderableMetricValue + Clone,
285{
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 if !self.help.is_empty() {
288 writeln!(f, "# HELP {} {}", self.family_name, self.help)?;
289 }
290
291 if self.family_type != <TypeSet>::default() {
292 writeln!(f, "# TYPE {} {}", self.family_name, self.family_type)?;
293 }
294
295 if !self.unit.is_empty() {
296 writeln!(f, "# UNIT {} {}", self.family_name, self.unit)?;
297 }
298
299 let label_names: Vec<&str> = self.label_names.iter().map(|s| s.as_str()).collect();
300
301 for metric in self.metrics.iter() {
302 metric.render(f, &self.family_name, &label_names)?;
303 }
304
305 Ok(())
306 }
307}
308
309#[derive(Debug)]
311pub struct MetricsExposition<TypeSet, ValueType> {
312 pub families: HashMap<String, MetricFamily<TypeSet, ValueType>>,
313}
314
315impl<TypeSet, ValueType> fmt::Display for MetricsExposition<TypeSet, ValueType>
316where
317 TypeSet: fmt::Display + Default + PartialEq,
318 ValueType: RenderableMetricValue + Clone,
319{
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 for (i, (_, family)) in self.families.iter().enumerate() {
322 write!(f, "{}", family)?;
323 if i != self.families.len()-1 {
324 write!(f, "\n")?;
325 }
326 }
327
328 Ok(())
329 }
330}
331
332impl<TypeSet, ValueType> Default for MetricsExposition<TypeSet, ValueType> {
333 fn default() -> Self {
334 Self::new()
335 }
336}
337
338impl<TypeSet, ValueType> MetricsExposition<TypeSet, ValueType> {
339 pub fn new() -> MetricsExposition<TypeSet, ValueType> {
340 MetricsExposition {
341 families: HashMap::new(),
342 }
343 }
344}
345
346#[derive(Debug, Clone, PartialEq)]
347pub struct CounterValue {
348 pub value: MetricNumber,
349 pub created: Option<Timestamp>,
350 pub exemplar: Option<Exemplar>,
351}
352
353fn format_float(f: f64) -> String {
354 if f == f64::NEG_INFINITY {
355 String::from("-Inf")
356 }
357 else if f == f64::INFINITY {
358 String::from("+Inf")
359 }
360 else if f.is_nan() {
361 String::from("NaN")
362 }
363 else {
364 format!("{}", f)
365 }
366}
367
368#[derive(Debug, Clone, PartialEq)]
369pub struct HistogramBucket {
370 pub count: MetricNumber,
371 pub upper_bound: f64,
372 pub exemplar: Option<Exemplar>,
373}
374
375impl RenderableMetricValue for HistogramBucket {
376 fn render(
377 &self,
378 f: &mut fmt::Formatter<'_>,
379 metric_name: &str,
380 _: Option<&Timestamp>,
381 label_names: &[&str],
382 label_values: &[&str],
383 ) -> fmt::Result {
384 let upper_bound_str = format_float(self.upper_bound);
385 let label_names = {
386 let mut names = Vec::from(label_names);
387 names.push("le");
388 names
389 };
390
391 let label_values = {
392 let mut values = Vec::from(label_values);
393 values.push(&upper_bound_str);
394 values
395 };
396
397 write!(
398 f,
399 "{}_bucket{} {}",
400 metric_name,
401 render_label_values(&label_names, &label_values),
402 self.count
403 )?;
404
405 if let Some(ex) = self.exemplar.as_ref() {
406 write!(f, "{}", ex)?;
407 }
408
409 f.write_char('\n')?;
410
411 Ok(())
412 }
413}
414
415#[derive(Debug, Default, Clone, PartialEq)]
416pub struct HistogramValue {
417 pub sum: Option<MetricNumber>,
418 pub count: Option<u64>,
419 pub created: Option<Timestamp>,
420 pub buckets: Vec<HistogramBucket>,
421}
422
423impl RenderableMetricValue for HistogramValue {
424 fn render(
425 &self,
426 f: &mut fmt::Formatter<'_>,
427 metric_name: &str,
428 timestamp: Option<&Timestamp>,
429 label_names: &[&str],
430 label_values: &[&str],
431 ) -> fmt::Result {
432 for bucket in self.buckets.iter() {
433 bucket.render(f, metric_name, timestamp, label_names, label_values)?;
434 }
435
436 let labels = render_label_values(label_names, label_values);
437
438 if let Some(s) = self.sum {
439 writeln!(f, "{}_sum{} {}", metric_name, labels, s)?;
440 }
441
442 if let Some(c) = self.count {
443 writeln!(f, "{}_count{} {}", metric_name, labels, c)?;
444 }
445
446 if let Some(c) = self.created {
447 writeln!(f, "{}_created{} {}", metric_name, labels, c)?;
448 }
449
450 Ok(())
451 }
452}
453
454#[derive(Debug, Clone)]
455pub struct State {
456 pub name: String,
457 pub enabled: bool,
458}
459
460#[derive(Debug, Clone, PartialEq)]
461pub struct Quantile {
462 pub quantile: f64,
463 pub value: MetricNumber,
464}
465
466impl RenderableMetricValue for Quantile {
467 fn render(
468 &self,
469 f: &mut fmt::Formatter<'_>,
470 metric_name: &str,
471 _: Option<&Timestamp>,
472 label_names: &[&str],
473 label_values: &[&str],
474 ) -> fmt::Result {
475 let quantile_str = format_float(self.quantile);
476 let label_names = {
477 let mut names = Vec::from(label_names);
478 names.push("quantile");
479 names
480 };
481
482 let label_values = {
483 let mut values = Vec::from(label_values);
484 values.push(&quantile_str);
485 values
486 };
487
488 writeln!(
489 f,
490 "{}{} {}",
491 metric_name,
492 render_label_values(&label_names, &label_values),
493 self.value
494 )
495 }
496}
497
498#[derive(Debug, Default, Clone, PartialEq)]
499pub struct SummaryValue {
500 pub sum: Option<MetricNumber>,
501 pub count: Option<u64>,
502 pub created: Option<Timestamp>,
503 pub quantiles: Vec<Quantile>,
504}
505
506impl RenderableMetricValue for SummaryValue {
507 fn render(
508 &self,
509 f: &mut fmt::Formatter<'_>,
510 metric_name: &str,
511 timestamp: Option<&Timestamp>,
512 label_names: &[&str],
513 label_values: &[&str],
514 ) -> fmt::Result {
515 for q in self.quantiles.iter() {
516 q.render(f, metric_name, timestamp, label_names, label_values)?;
517 }
518
519 let labels = render_label_values(label_names, label_values);
520
521 if let Some(s) = self.sum {
522 writeln!(f, "{}_sum{} {}", metric_name, labels, s)?;
523 }
524
525 if let Some(s) = self.count {
526 writeln!(f, "{}_count{} {}", metric_name, labels, s)?;
527 }
528
529 if let Some(s) = self.created {
530 writeln!(f, "{}_created{} {}", metric_name, labels, s)?;
531 }
532
533 Ok(())
534 }
535}
536
537#[derive(Debug, PartialEq, Clone, Copy)]
538pub enum OpenMetricsType {
539 Counter,
548
549 Gauge,
559
560 Histogram,
577
578 GaugeHistogram,
589
590 StateSet,
596
597 Summary,
612
613 Info,
620
621 Unknown,
624}
625
626#[derive(Debug, Clone)]
627pub enum OpenMetricsValue {
628 Unknown(MetricNumber),
629 Gauge(MetricNumber),
630 Counter(CounterValue),
631 Histogram(HistogramValue),
632 StateSet(MetricNumber),
633 GaugeHistogram(HistogramValue),
634 Info,
635 Summary(SummaryValue),
636}
637
638impl RenderableMetricValue for OpenMetricsValue {
639 fn render(
640 &self,
641 f: &mut fmt::Formatter<'_>,
642 metric_name: &str,
643 timestamp: Option<&Timestamp>,
644 label_names: &[&str],
645 label_values: &[&str],
646 ) -> fmt::Result {
647 let timestamp_str = timestamp.map(|t| format!(" {}", format_float(*t))).unwrap_or_default();
648 match self {
649 OpenMetricsValue::Unknown(n)
650 | OpenMetricsValue::Gauge(n)
651 | OpenMetricsValue::StateSet(n) =>{
652 writeln!(
653 f,
654 "{}{} {}{}",
655 metric_name,
656 render_label_values(label_names, label_values),
657 n,
658 timestamp_str
659 )
660 },
661 OpenMetricsValue::Counter(c) => {
662 write!(
663 f,
664 "{}{} {}{}",
665 metric_name,
666 render_label_values(label_names, label_values),
667 c.value,
668 timestamp_str
669 )?;
670 if let Some(ex) = c.exemplar.as_ref() {
671 write!(f, "{}", ex)?;
672 }
673
674 f.write_char('\n')
675 }
676 OpenMetricsValue::Histogram(h) | OpenMetricsValue::GaugeHistogram(h) => {
677 h.render(f, metric_name, timestamp, label_names, label_values)
679 }
680 OpenMetricsValue::Summary(s) => {
681 s.render(f, metric_name, timestamp, label_names, label_values)
682 }
683 OpenMetricsValue::Info => {
684 writeln!(
685 f,
686 "{}{} {} {}",
687 metric_name,
688 render_label_values(label_names, label_values),
689 MetricNumber::Int(1),
690 timestamp_str
691 )
692 }
693 }
694 }
695}
696
697#[derive(Debug, PartialEq, Clone)]
698pub enum PrometheusType {
699 Counter,
700 Gauge,
701 Histogram,
702 Summary,
703 Unknown,
704}
705
706impl fmt::Display for PrometheusType {
707 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708 let out = match self {
709 PrometheusType::Counter => "counter",
710 PrometheusType::Gauge => "gauge",
711 PrometheusType::Histogram => "histogram",
712 PrometheusType::Summary => "summary",
713 PrometheusType::Unknown => "unknown",
714 };
715
716 f.write_str(out)
717 }
718}
719
720#[derive(Debug, Clone, PartialEq)]
721pub struct PrometheusCounterValue {
722 pub value: MetricNumber,
723 pub exemplar: Option<Exemplar>,
724}
725
726#[derive(Debug, Clone, PartialEq)]
727pub enum PrometheusValue {
728 Unknown(MetricNumber),
729 Gauge(MetricNumber),
730 Counter(PrometheusCounterValue),
731 Histogram(HistogramValue),
732 Summary(SummaryValue),
733}
734
735impl RenderableMetricValue for PrometheusValue {
736 fn render(
737 &self,
738 f: &mut fmt::Formatter<'_>,
739 metric_name: &str,
740 timestamp: Option<&Timestamp>,
741 label_names: &[&str],
742 label_values: &[&str],
743 ) -> fmt::Result {
744 let timestamp_str = timestamp.map(|t| format!(" {}", format_float(*t))).unwrap_or_default();
745 match self {
746 PrometheusValue::Unknown(n) | PrometheusValue::Gauge(n) => writeln!(
747 f,
748 "{}{} {}{}",
749 metric_name,
750 render_label_values(label_names, label_values),
751 n,
752 timestamp_str
753 ),
754 PrometheusValue::Counter(c) => {
755 write!(
756 f,
757 "{}{} {}{}",
758 metric_name,
759 render_label_values(label_names, label_values),
760 c.value,
761 timestamp_str
762 )?;
763 if let Some(ex) = c.exemplar.as_ref() {
764 write!(f, "{}", ex)?;
765 }
766
767 f.write_char('\n')
768 }
769 PrometheusValue::Histogram(h) => {
770 h.render(f, metric_name, timestamp, label_names, label_values)
771 }
772 PrometheusValue::Summary(s) => {
773 s.render(f, metric_name, timestamp, label_names, label_values)
774 }
775 }
776 }
777}
778
779#[derive(Debug, Clone)]
780pub struct Sample<ValueType> {
781 label_names: Option<Arc<Vec<String>>>,
782 label_values: Vec<String>,
783 pub timestamp: Option<Timestamp>,
784 pub value: ValueType,
785}
786
787impl<ValueType> Sample<ValueType>
788where
789 ValueType: RenderableMetricValue + Clone,
790{
791 pub fn new(label_values: Vec<String>, timestamp: Option<Timestamp>, value: ValueType) -> Self {
792 Self {
793 label_values,
794 timestamp,
795 value,
796 label_names: None,
797 }
798 }
799
800 fn clone_with_new_value<T>(&self, value: T) -> Sample<T> where T: RenderableMetricValue + Clone {
801 return Sample {
802 label_names: self.label_names.clone(),
803 label_values: self.label_values.clone(),
804 timestamp: self.timestamp.clone(),
805 value,
806 }
807 }
808
809 fn set_label_names(&mut self, label_names: Arc<Vec<String>>) {
810 self.label_names = Some(label_names);
811 }
812
813 pub fn without_label(&self, label_name: &str) -> Result<Self, ParseError> {
814 if let Some(labels) = &self.label_names {
815 if let Some(idx) = labels.iter().position(|name| name == label_name) {
816 let mut label_values = self.label_values.clone();
817 label_values.remove(idx);
818
819 return Ok(Self::new(label_values, self.timestamp.clone(), self.value.clone()));
820 }
821
822 return Err(ParseError::InvalidMetric(format!("Label {} doesn't existin in metric", label_name)));
823 }
824
825 return Err(ParseError::InvalidMetric(format!("Metric isn't bound to a family, so doesn't have names")));
826 }
827
828 pub fn get_labelset(&self) -> Result<LabelSet, ParseError> {
829 if let Some(label_names) = &self.label_names {
830 return LabelSet::new(label_names.clone(), self);
831 }
832
833 Err(ParseError::InvalidMetric(
834 "Metric has not been bound to a family yet, and thus doesn't have label names"
835 .to_string(),
836 ))
837 }
838
839 fn render(
840 &self,
841 f: &mut fmt::Formatter<'_>,
842 metric_name: &str,
843 label_names: &[&str],
844 ) -> fmt::Result {
845 let values: Vec<&str> = self.label_values.iter().map(|s| s.as_str()).collect();
846 self.value.render(
847 f,
848 metric_name,
849 self.timestamp.as_ref(),
850 label_names,
851 &values,
852 )
853 }
854}
855
856#[derive(Debug, Copy, Clone, PartialEq)]
857pub enum MetricNumber {
858 Float(f64),
859 Int(i64),
860}
861
862impl fmt::Display for MetricNumber {
863 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
864 match self {
865 MetricNumber::Float(n) => write!(f, "{}", format_float(*n)),
866 MetricNumber::Int(n) => write!(f, "{}", n),
867 }
868 }
869}
870
871impl MetricNumber {
872 pub fn as_f64(&self) -> f64 {
873 match self {
874 MetricNumber::Int(i) => *i as f64,
875 MetricNumber::Float(f) => *f,
876 }
877 }
878
879 pub fn as_i64(&self) -> Option<i64> {
880 match self {
881 MetricNumber::Int(i) => Some(*i),
882 MetricNumber::Float(f) if (f.round() - *f).abs() < f64::EPSILON => Some(*f as i64),
883 _ => None,
884 }
885 }
886}
887
888impl_op_ex!(+ |a: &MetricNumber, b: &MetricNumber| -> MetricNumber {
889 match (a, b) {
890 (MetricNumber::Float(f), MetricNumber::Float(f2)) => MetricNumber::Float(f + f2),
891 (MetricNumber::Float(f), MetricNumber::Int(i)) => MetricNumber::Float(f + *i as f64),
892 (MetricNumber::Int(i), MetricNumber::Float(f)) => MetricNumber::Float(f + *i as f64),
893 (MetricNumber::Int(i), MetricNumber::Int(i2)) => MetricNumber::Int(i + i2),
894 }
895});
896
897impl_op_ex!(+= |a: &mut MetricNumber, b: &MetricNumber| {
898 match (&a, b) {
899 (MetricNumber::Float(f), MetricNumber::Float(f2)) => *a = MetricNumber::Float(*f + f2),
900 (MetricNumber::Float(f), MetricNumber::Int(i)) => *a = MetricNumber::Float(*f + *i as f64),
901 (MetricNumber::Int(i), MetricNumber::Float(f)) => *a = MetricNumber::Float(*i as f64 + *f),
902 (MetricNumber::Int(i), MetricNumber::Int(i2)) => *a = MetricNumber::Int(*i + i2),
903 }
904});
905
906impl_op_ex!(-|a: &MetricNumber, b: &MetricNumber| -> MetricNumber {
907 match (a, b) {
908 (MetricNumber::Float(f), MetricNumber::Float(f2)) => MetricNumber::Float(f - f2),
909 (MetricNumber::Float(f), MetricNumber::Int(i)) => MetricNumber::Float(f - *i as f64),
910 (MetricNumber::Int(i), MetricNumber::Float(f)) => MetricNumber::Float(*i as f64 - f),
911 (MetricNumber::Int(i), MetricNumber::Int(i2)) => MetricNumber::Int(i - i2),
912 }
913});
914
915impl_op_ex!(-= |a: &mut MetricNumber, b: &MetricNumber| {
916 match (&a, b) {
917 (MetricNumber::Float(f), MetricNumber::Float(f2)) => *a = MetricNumber::Float(*f - f2),
918 (MetricNumber::Float(f), MetricNumber::Int(i)) => *a = MetricNumber::Float(*f - *i as f64),
919 (MetricNumber::Int(i), MetricNumber::Float(f)) => *a = MetricNumber::Float(*i as f64 - *f),
920 (MetricNumber::Int(i), MetricNumber::Int(i2)) => *a = MetricNumber::Int(*i - i2),
921 }
922});
923
924impl_op_ex!(*|a: &MetricNumber, b: &MetricNumber| -> MetricNumber {
925 match (a, b) {
926 (MetricNumber::Float(f), MetricNumber::Float(f2)) => MetricNumber::Float(f * f2),
927 (MetricNumber::Float(f), MetricNumber::Int(i)) => MetricNumber::Float(f * *i as f64),
928 (MetricNumber::Int(i), MetricNumber::Float(f)) => MetricNumber::Float(*i as f64 * *f),
929 (MetricNumber::Int(i), MetricNumber::Int(i2)) => MetricNumber::Int(i * i2),
930 }
931});
932
933impl_op_ex!(*= |a: &mut MetricNumber, b: &MetricNumber| {
934 match (&a, b) {
935 (MetricNumber::Float(f), MetricNumber::Float(f2)) => *a = MetricNumber::Float(*f * f2),
936 (MetricNumber::Float(f), MetricNumber::Int(i)) => *a = MetricNumber::Float(*f * *i as f64),
937 (MetricNumber::Int(i), MetricNumber::Float(f)) => *a = MetricNumber::Float(*i as f64 * *f),
938 (MetricNumber::Int(i), MetricNumber::Int(i2)) => *a = MetricNumber::Int(*i * i2),
939 }
940});
941
942impl_op_ex!(/ |a: &MetricNumber, b: &MetricNumber| -> MetricNumber {
943 match (a, b) {
944 (MetricNumber::Float(f), MetricNumber::Float(f2)) => MetricNumber::Float(f / f2),
945 (MetricNumber::Float(f), MetricNumber::Int(i)) => MetricNumber::Float(f / *i as f64),
946 (MetricNumber::Int(i), MetricNumber::Float(f)) => MetricNumber::Float(*i as f64 / f),
947 (MetricNumber::Int(i), MetricNumber::Int(i2)) => MetricNumber::Int(i / i2),
948 }
949});
950
951impl_op_ex!(/= |a: &mut MetricNumber, b: &MetricNumber| {
952 match (&a, b) {
953 (MetricNumber::Float(f), MetricNumber::Float(f2)) => *a = MetricNumber::Float(*f / f2),
954 (MetricNumber::Float(f), MetricNumber::Int(i)) => *a = MetricNumber::Float(*f / *i as f64),
955 (MetricNumber::Int(i), MetricNumber::Float(f)) => *a = MetricNumber::Float(*i as f64 / f),
956 (MetricNumber::Int(i), MetricNumber::Int(i2)) => *a = MetricNumber::Int(*i / i2),
957 }
958});
959
960#[derive(Debug)]
961pub enum ParseError {
962 ParseError(String),
963 DuplicateMetric,
964 InvalidMetric(String),
965}
966
967impl fmt::Display for ParseError {
968 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969 match self {
970 ParseError::ParseError(e) => e.fmt(f),
971 ParseError::DuplicateMetric => f.write_str("Found two metrics with the same labelset"),
972 ParseError::InvalidMetric(s) => f.write_str(s),
973 }
974 }
975}
976
977pub struct LabelSet<'a> {
978 label_names: Arc<Vec<String>>,
979 label_values: &'a [String],
980}
981
982impl<'a> LabelSet<'a> {
983 pub fn new<ValueType>(
984 label_names: Arc<Vec<String>>,
985 sample: &'a Sample<ValueType>,
986 ) -> Result<Self, ParseError> {
987 if label_names.len() != sample.label_values.len() {
988 return Err(ParseError::InvalidMetric(format!(
989 "Cannot create labelset from family with {} labels and sample with {}",
990 label_names.len(),
991 sample.label_values.len()
992 )));
993 }
994
995 Ok(Self {
996 label_names,
997 label_values: &sample.label_values,
998 })
999 }
1000
1001 pub fn matches_sample<ValueType>(&self, sample: &Sample<ValueType>) -> bool {
1002 self.matches_values(&sample.label_values)
1003 }
1004
1005 pub fn matches_values(&self, label_values: &[String]) -> bool {
1006 self.label_values == label_values
1007 }
1008
1009 pub fn iter(&self) -> impl Iterator<Item = (&String, &String)> {
1010 return self.label_names.iter().zip(self.label_values);
1011 }
1012
1013 pub fn iter_names(&self) -> impl Iterator<Item = &String> {
1014 self.label_names.iter()
1015 }
1016
1017 pub fn iter_values(&self) -> impl Iterator<Item = &String> {
1018 self.label_values.iter()
1019 }
1020
1021 pub fn get_label_value(&self, label_name: &str) -> Option<&str> {
1022 return self
1023 .label_names
1024 .iter()
1025 .position(|s| s == label_name)
1026 .map(|i| self.label_values[i].as_str());
1027 }
1028}