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