1use crate::{
2 internal::{
3 CounterValueMarshal, LabelNames, MarshalledMetric, MarshalledMetricFamily,
4 MetricFamilyMarshal, MetricMarshal, MetricProcesser, MetricValueMarshal, MetricsType,
5 unescape,
6 },
7 public::*,
8};
9use std::convert::TryFrom;
10
11use pest::Parser;
12
13#[derive(Parser)]
14#[grammar = "openmetrics/openmetrics.pest"]
15struct OpenMetricsParser;
16
17impl From<pest::error::Error<Rule>> for ParseError {
18 fn from(err: pest::error::Error<Rule>) -> Self {
19 ParseError::ParseError(err.to_string())
20 }
21}
22
23impl From<MetricValueMarshal> for OpenMetricsValue {
24 fn from(s: MetricValueMarshal) -> OpenMetricsValue {
25 match s {
26 MetricValueMarshal::Unknown(s) => OpenMetricsValue::Unknown(s.unwrap()),
27 MetricValueMarshal::Gauge(s) => OpenMetricsValue::Gauge(s.unwrap()),
28 MetricValueMarshal::Counter(s) => OpenMetricsValue::Counter(s.into()),
29 MetricValueMarshal::Histogram(s) => OpenMetricsValue::Histogram(s),
30 MetricValueMarshal::StateSet(s) => OpenMetricsValue::StateSet(s.unwrap()),
31 MetricValueMarshal::GaugeHistogram(s) => OpenMetricsValue::GaugeHistogram(s),
32 MetricValueMarshal::Info => OpenMetricsValue::Info,
33 MetricValueMarshal::Summary(s) => OpenMetricsValue::Summary(s),
34 }
35 }
36}
37
38impl MetricsType for OpenMetricsType {
39 fn can_have_exemplar(&self, metric_name: &str) -> bool {
40 match self {
41 OpenMetricsType::Counter => metric_name.ends_with("_total"),
42 OpenMetricsType::Histogram | OpenMetricsType::GaugeHistogram => {
43 metric_name.ends_with("_bucket")
44 }
45 _ => false,
46 }
47 }
48
49 fn get_ignored_labels(&self, metric_name: &str) -> &[&str] {
50 match self {
51 OpenMetricsType::Histogram | OpenMetricsType::GaugeHistogram
52 if metric_name.ends_with("bucket") =>
53 {
54 &["le"]
55 }
56 _ => &[],
57 }
58 }
59
60 fn get_type_value(&self) -> MetricValueMarshal {
61 match self {
62 OpenMetricsType::Histogram => MetricValueMarshal::Histogram(HistogramValue::default()),
63 OpenMetricsType::GaugeHistogram => {
64 MetricValueMarshal::GaugeHistogram(HistogramValue::default())
65 }
66 OpenMetricsType::Counter => MetricValueMarshal::Counter(CounterValueMarshal::default()),
67 OpenMetricsType::Unknown => MetricValueMarshal::Unknown(None),
68 OpenMetricsType::Gauge => MetricValueMarshal::Gauge(None),
69 OpenMetricsType::StateSet => MetricValueMarshal::StateSet(None),
70 OpenMetricsType::Summary => MetricValueMarshal::Summary(SummaryValue::default()),
71 OpenMetricsType::Info => MetricValueMarshal::Info,
72 }
73 }
74
75 fn can_have_units(&self) -> bool {
76 matches!(
77 self,
78 OpenMetricsType::Counter | OpenMetricsType::Unknown | OpenMetricsType::Gauge
79 )
80 }
81
82 fn can_have_multiple_lines(&self) -> bool {
83 matches!(
84 self,
85 OpenMetricsType::Counter
86 | OpenMetricsType::GaugeHistogram
87 | OpenMetricsType::Histogram
88 | OpenMetricsType::Summary
89 )
90 }
91}
92
93impl TryFrom<&str> for OpenMetricsType {
94 type Error = ParseError;
95
96 fn try_from(value: &str) -> Result<Self, Self::Error> {
97 match value {
98 "counter" => Ok(OpenMetricsType::Counter),
99 "gauge" => Ok(OpenMetricsType::Gauge),
100 "histogram" => Ok(OpenMetricsType::Histogram),
101 "gaugehistogram" => Ok(OpenMetricsType::GaugeHistogram),
102 "stateset" => Ok(OpenMetricsType::StateSet),
103 "summary" => Ok(OpenMetricsType::Summary),
104 "info" => Ok(OpenMetricsType::Info),
105 "unknown" => Ok(OpenMetricsType::Unknown),
106 _ => Err(ParseError::InvalidMetric(format!(
107 "Invalid metric type: {}",
108 value
109 ))),
110 }
111 }
112}
113
114impl Default for OpenMetricsType {
115 fn default() -> Self {
116 OpenMetricsType::Unknown
117 }
118}
119
120impl From<MetricMarshal> for Sample<OpenMetricsValue> {
121 fn from(s: MetricMarshal) -> Sample<OpenMetricsValue> {
122 Sample::new(s.label_values, s.timestamp, s.value.into())
123 }
124}
125
126impl MarshalledMetric<OpenMetricsType> for MetricMarshal {
127 fn validate(&self, family: &MetricFamilyMarshal<OpenMetricsType>) -> Result<(), ParseError> {
128 if family.label_names.is_none() && !self.label_values.is_empty()
130 || (family.label_names.as_ref().unwrap().names.len() != self.label_values.len())
131 {
132 return Err(ParseError::InvalidMetric(format!(
133 "Metrics in family have different label sets: {:?} {:?}",
134 &family.label_names, self.label_values
135 )));
136 }
137
138 if family.unit.is_some() && family.metrics.is_empty() {
139 return Err(ParseError::InvalidMetric(
140 "Can't have metric with unit and no samples".to_owned(),
141 ));
142 }
143
144 match &self.value {
145 MetricValueMarshal::Histogram(histogram_value)
146 | MetricValueMarshal::GaugeHistogram(histogram_value) => {
147 let gauge_histogram = matches!(&self.value, MetricValueMarshal::GaugeHistogram(_));
148
149 if histogram_value.buckets.is_empty() {
150 return Err(ParseError::InvalidMetric(
151 "Histograms must have at least one bucket".to_owned(),
152 ));
153 }
154
155 if !histogram_value
156 .buckets
157 .iter()
158 .any(|b| b.upper_bound == f64::INFINITY)
159 {
160 return Err(ParseError::InvalidMetric(format!(
161 "Histograms must have a +INF bucket: {:?}",
162 histogram_value.buckets
163 )));
164 }
165
166 let buckets = &histogram_value.buckets;
167
168 let has_negative_bucket = buckets.iter().any(|f| f.upper_bound < 0.);
169
170 if has_negative_bucket {
171 if histogram_value.sum.is_some() && !gauge_histogram {
172 return Err(ParseError::InvalidMetric(
173 "Histograms cannot have a sum with a negative bucket".to_owned(),
174 ));
175 }
176 } else if histogram_value.sum.is_some()
177 && histogram_value.sum.as_ref().unwrap().as_f64() < 0.
178 {
179 return Err(ParseError::InvalidMetric(
180 "Histograms cannot have a negative sum without a negative bucket"
181 .to_owned(),
182 ));
183 }
184
185 if histogram_value.sum.is_some() && histogram_value.count.is_none() {
186 return Err(ParseError::InvalidMetric(
187 "Count must be present if sum is present".to_owned(),
188 ));
189 }
190
191 if histogram_value.sum.is_none() && histogram_value.count.is_some() {
192 return Err(ParseError::InvalidMetric(
193 "Sum must be present if count is present".to_owned(),
194 ));
195 }
196
197 let mut last = f64::NEG_INFINITY;
198 for bucket in buckets {
199 if bucket.count.as_f64() < last {
200 return Err(ParseError::InvalidMetric(
201 "Histograms must be cumulative".to_owned(),
202 ));
203 }
204
205 last = bucket.count.as_f64();
206 }
207 }
208 MetricValueMarshal::Counter(counter_value) => {
209 if counter_value.value.is_none() {
210 return Err(ParseError::InvalidMetric(
211 "Counter is missing a _total".to_string(),
212 ));
213 }
214 }
215 _ => {}
216 }
217
218 Ok(())
219 }
220}
221
222impl MarshalledMetricFamily for MetricFamilyMarshal<OpenMetricsType> {
223 type Error = ParseError;
224
225 fn validate(&self) -> Result<(), ParseError> {
226 if self.name.is_none() {
227 return Err(ParseError::InvalidMetric(
228 "Metric didn't have a name".to_string(),
229 ));
230 }
231
232 if self.family_type == Some(OpenMetricsType::StateSet)
233 && self.label_names.is_some()
234 && !self
235 .label_names
236 .as_ref()
237 .unwrap()
238 .names
239 .contains(self.name.as_ref().unwrap())
240 {
241 return Err(ParseError::InvalidMetric(
242 "Stateset must not have a label with the same name as its MetricFamily".to_string(),
243 ));
244 }
245
246 for metric in self.metrics.iter() {
247 metric.validate(self)?;
248 }
249
250 Ok(())
251 }
252
253 fn process_new_metric(
254 &mut self,
255 metric_name: &str,
256 metric_value: MetricNumber,
257 label_names: Vec<String>,
258 label_values: Vec<String>,
259 timestamp: Option<Timestamp>,
260 exemplar: Option<Exemplar>,
261 ) -> Result<(), Self::Error> {
262 let handlers = vec![
263 (
264 vec![OpenMetricsType::Histogram],
265 vec![
266 (
267 "_bucket",
268 vec!["le"],
269 MetricProcesser::new(
270 |existing_metric: &mut MetricMarshal,
271 metric_value: MetricNumber,
272 label_names: Vec<String>,
273 label_values: Vec<String>,
274 exemplar: Option<Exemplar>,
275 _: bool| {
276 let bucket_bound: f64 = {
277 let bound_index =
278 label_names.iter().position(|s| s == "le").unwrap();
279
280 let bound = &label_values[bound_index];
281 match bound.parse() {
282 Ok(f) => f,
283 Err(_) => {
284 return Err(ParseError::InvalidMetric(format!(
285 "Invalid histogram bound: {}",
286 bound
287 )));
288 }
289 }
290 };
291
292 let bucket = HistogramBucket {
293 count: metric_value,
294 upper_bound: bucket_bound,
295 exemplar,
296 };
297
298 if let MetricValueMarshal::Histogram(value) =
299 &mut existing_metric.value
300 {
301 value.buckets.push(bucket);
302 } else {
303 unreachable!();
304 }
305
306 Ok(())
307 },
308 ),
309 ),
310 (
311 "_count",
312 vec![],
313 MetricProcesser::new(
314 |existing_metric: &mut MetricMarshal,
315 metric_value: MetricNumber,
316 _: Vec<String>,
317 _: Vec<String>,
318 _: Option<Exemplar>,
319 _: bool| {
320 if let MetricValueMarshal::Histogram(histogram_value) =
321 &mut existing_metric.value
322 {
323 let metric_value = if let Some(value) = metric_value.as_i64() {
324 if value < 0 {
325 return Err(ParseError::InvalidMetric(format!(
326 "Histogram counts must be positive (got: {})",
327 value
328 )));
329 }
330
331 value as u64
332 } else {
333 return Err(ParseError::InvalidMetric(format!(
334 "Histogram counts must be integers (got: {})",
335 metric_value.as_f64()
336 )));
337 };
338
339 match histogram_value.count {
340 Some(_) => {
341 return Err(ParseError::DuplicateMetric);
342 }
343 None => {
344 histogram_value.count = Some(metric_value);
345 }
346 };
347 } else {
348 unreachable!();
349 }
350
351 Ok(())
352 },
353 ),
354 ),
355 (
356 "_created",
357 vec![],
358 MetricProcesser::new(
359 |existing_metric: &mut MetricMarshal,
360 metric_value: MetricNumber,
361 _: Vec<String>,
362 _: Vec<String>,
363 _: Option<Exemplar>,
364 _: bool| {
365 if let MetricValueMarshal::Histogram(histogram_value) =
366 &mut existing_metric.value
367 {
368 match histogram_value.created {
369 Some(_) => {
370 return Err(ParseError::DuplicateMetric);
371 }
372 None => {
373 histogram_value.created = Some(metric_value.as_f64());
374 }
375 };
376 } else {
377 unreachable!();
378 }
379
380 Ok(())
381 },
382 ),
383 ),
384 (
385 "_sum",
386 vec![],
387 MetricProcesser::new(
388 |existing_metric: &mut MetricMarshal,
389 metric_value: MetricNumber,
390 _: Vec<String>,
391 _: Vec<String>,
392 _: Option<Exemplar>,
393 _: bool| {
394 if let MetricValueMarshal::Histogram(histogram_value) =
395 &mut existing_metric.value
396 {
397 if histogram_value.sum.is_some() {
398 return Err(ParseError::DuplicateMetric);
399 }
400
401 histogram_value.sum = Some(metric_value);
402
403 Ok(())
404 } else {
405 unreachable!();
406 }
407 },
408 ),
409 ),
410 ],
411 ),
412 (
413 vec![OpenMetricsType::GaugeHistogram],
414 vec![
415 (
416 "_bucket",
417 vec!["le"],
418 MetricProcesser::new(
419 |existing_metric: &mut MetricMarshal,
420 metric_value: MetricNumber,
421 label_names: Vec<String>,
422 label_values: Vec<String>,
423 exemplar: Option<Exemplar>,
424 _: bool| {
425 let bucket_bound: f64 = {
426 let bound_index =
427 label_names.iter().position(|s| s == "le").unwrap();
428
429 let bound = &label_values[bound_index];
430 match bound.parse() {
431 Ok(f) => f,
432 Err(_) => {
433 return Err(ParseError::InvalidMetric(format!("Expected histogram bucket bound to be an f64 (got: {})", bound)));
434 }
435 }
436 };
437
438 let bucket = HistogramBucket {
439 count: metric_value,
440 upper_bound: bucket_bound,
441 exemplar,
442 };
443
444 if let MetricValueMarshal::GaugeHistogram(value) =
445 &mut existing_metric.value
446 {
447 value.buckets.push(bucket);
448 } else {
449 unreachable!();
450 }
451
452 Ok(())
453 },
454 ),
455 ),
456 (
457 "_gcount",
458 vec![],
459 MetricProcesser::new(
460 |existing_metric: &mut MetricMarshal,
461 metric_value: MetricNumber,
462 _: Vec<String>,
463 _: Vec<String>,
464 _: Option<Exemplar>,
465 _: bool| {
466 if let MetricValueMarshal::GaugeHistogram(histogram_value) =
467 &mut existing_metric.value
468 {
469 let metric_value = if let Some(value) = metric_value.as_i64() {
470 if value < 0 {
471 return Err(ParseError::InvalidMetric(format!(
472 "Histogram counts must be positive (got: {})",
473 value
474 )));
475 }
476
477 value as u64
478 } else {
479 return Err(ParseError::InvalidMetric(format!(
480 "Histogram counts must be integers (got: {})",
481 metric_value.as_f64()
482 )));
483 };
484
485 match histogram_value.count {
486 Some(_) => {
487 return Err(ParseError::DuplicateMetric);
488 }
489 None => {
490 histogram_value.count = Some(metric_value);
491 }
492 };
493 } else {
494 unreachable!();
495 }
496
497 Ok(())
498 },
499 ),
500 ),
501 (
502 "_gsum",
503 vec![],
504 MetricProcesser::new(
505 |existing_metric: &mut MetricMarshal,
506 metric_value: MetricNumber,
507 _: Vec<String>,
508 _: Vec<String>,
509 _: Option<Exemplar>,
510 _: bool| {
511 if let MetricValueMarshal::GaugeHistogram(histogram_value) =
512 &mut existing_metric.value
513 {
514 if histogram_value.sum.is_some() {
515 return Err(ParseError::DuplicateMetric);
516 }
517
518 histogram_value.sum = Some(metric_value);
519
520 Ok(())
521 } else {
522 unreachable!();
523 }
524 },
525 ),
526 ),
527 ],
528 ),
529 (
530 vec![OpenMetricsType::Counter],
531 vec![
532 (
533 "_total",
534 vec![],
535 MetricProcesser::new(
536 |existing_metric: &mut MetricMarshal,
537 metric_value: MetricNumber,
538 _: Vec<String>,
539 _: Vec<String>,
540 exemplar: Option<Exemplar>,
541 _: bool| {
542 if let MetricValueMarshal::Counter(counter_value) =
543 &mut existing_metric.value
544 {
545 if counter_value.value.is_some() {
546 return Err(ParseError::DuplicateMetric);
547 }
548
549 let value = metric_value.as_f64();
550 if value < 0. || value.is_nan() {
551 return Err(ParseError::InvalidMetric(format!(
552 "Counter totals must be non negative (got: {})",
553 metric_value.as_f64()
554 )));
555 }
556
557 counter_value.value = Some(metric_value);
558 counter_value.exemplar = exemplar;
559 } else {
560 unreachable!();
561 }
562
563 Ok(())
564 },
565 ),
566 ),
567 (
568 "_created",
569 vec![],
570 MetricProcesser::new(
571 |existing_metric: &mut MetricMarshal,
572 metric_value: MetricNumber,
573 _: Vec<String>,
574 _: Vec<String>,
575 _: Option<Exemplar>,
576 _: bool| {
577 if let MetricValueMarshal::Counter(counter_value) =
578 &mut existing_metric.value
579 {
580 if counter_value.created.is_some() {
581 return Err(ParseError::DuplicateMetric);
582 }
583
584 counter_value.created = Some(metric_value.as_f64());
585 Ok(())
586 } else {
587 unreachable!();
588 }
589 },
590 ),
591 ),
592 ],
593 ),
594 (
595 vec![OpenMetricsType::Gauge],
596 vec![(
597 "",
598 vec![],
599 MetricProcesser::new(
600 |existing_metric: &mut MetricMarshal,
601 metric_value: MetricNumber,
602 _: Vec<String>,
603 _: Vec<String>,
604 _: Option<Exemplar>,
605 _: bool| {
606 if let MetricValueMarshal::Gauge(gauge_value) =
607 &mut existing_metric.value
608 {
609 if gauge_value.is_some() {
610 return Err(ParseError::DuplicateMetric);
611 }
612
613 existing_metric.value =
614 MetricValueMarshal::Gauge(Some(metric_value));
615 } else {
616 unreachable!();
617 }
618
619 Ok(())
620 },
621 ),
622 )],
623 ),
624 (
625 vec![OpenMetricsType::StateSet],
626 vec![(
627 "",
628 vec![],
629 MetricProcesser::new(
630 |existing_metric: &mut MetricMarshal,
631 metric_value: MetricNumber,
632 _: Vec<String>,
633 _: Vec<String>,
634 _: Option<Exemplar>,
635 _: bool| {
636 if let MetricValueMarshal::StateSet(stateset_value) =
637 &mut existing_metric.value
638 {
639 if stateset_value.is_some() {
640 return Err(ParseError::DuplicateMetric);
641 }
642
643 if existing_metric.label_values.is_empty() {
644 return Err(ParseError::InvalidMetric(
645 "Stateset must have labels".to_string(),
646 ));
647 }
648
649 if metric_value.as_f64() != 0.
650 && (metric_value.as_f64() - 1.).abs() > f64::EPSILON
651 {
652 return Err(ParseError::InvalidMetric(format!(
653 "Stateset value must be 0 or 1 (got: {})",
654 metric_value.as_f64()
655 )));
656 }
657
658 existing_metric.value =
659 MetricValueMarshal::StateSet(Some(metric_value));
660 } else {
661 unreachable!();
662 }
663
664 Ok(())
665 },
666 ),
667 )],
668 ),
669 (
670 vec![OpenMetricsType::Unknown],
671 vec![(
672 "",
673 vec![],
674 MetricProcesser::new(
675 |existing_metric: &mut MetricMarshal,
676 metric_value: MetricNumber,
677 _: Vec<String>,
678 _: Vec<String>,
679 _: Option<Exemplar>,
680 _: bool| {
681 if let MetricValueMarshal::Unknown(unknown_value) =
682 &mut existing_metric.value
683 {
684 if unknown_value.is_some() {
685 return Err(ParseError::DuplicateMetric);
686 }
687
688 existing_metric.value =
689 MetricValueMarshal::Unknown(Some(metric_value));
690 } else {
691 unreachable!();
692 }
693
694 Ok(())
695 },
696 ),
697 )],
698 ),
699 (
700 vec![OpenMetricsType::Info],
701 vec![(
702 "_info",
703 vec![],
704 MetricProcesser::new(
705 |_: &mut MetricMarshal,
706 metric_value: MetricNumber,
707 _: Vec<String>,
708 _: Vec<String>,
709 _: Option<Exemplar>,
710 created: bool| {
711 let metric_value = if let Some(value) = metric_value.as_i64() {
712 value as u64
713 } else {
714 return Err(ParseError::InvalidMetric(format!(
715 "Info values must be integers (got: {})",
716 metric_value.as_f64()
717 )));
718 };
719
720 if metric_value != 1 {
721 return Err(ParseError::InvalidMetric(format!(
722 "Info values must be 1 (got: {})",
723 metric_value
724 )));
725 }
726
727 if !created {
728 return Err(ParseError::DuplicateMetric);
729 }
730
731 Ok(())
732 },
733 ),
734 )],
735 ),
736 (
737 vec![OpenMetricsType::Summary],
738 vec![
739 (
740 "_count",
741 vec![],
742 MetricProcesser::new(
743 |existing_metric: &mut MetricMarshal,
744 metric_value: MetricNumber,
745 _: Vec<String>,
746 _: Vec<String>,
747 _: Option<Exemplar>,
748 _: bool| {
749 if let MetricValueMarshal::Summary(summary_value) =
750 &mut existing_metric.value
751 {
752 let metric_value = if let Some(value) = metric_value.as_i64() {
753 if value < 0 {
754 return Err(ParseError::InvalidMetric(format!(
755 "Summary counts must be positive (got: {})",
756 value
757 )));
758 }
759 value as u64
760 } else {
761 return Err(ParseError::InvalidMetric(format!(
762 "Summary counts must be integers (got: {})",
763 metric_value.as_f64()
764 )));
765 };
766
767 if summary_value.count.is_none() {
768 summary_value.count = Some(metric_value);
769 } else {
770 return Err(ParseError::DuplicateMetric);
771 }
772 } else {
773 unreachable!();
774 }
775
776 Ok(())
777 },
778 ),
779 ),
780 (
781 "_sum",
782 vec![],
783 MetricProcesser::new(
784 |existing_metric: &mut MetricMarshal,
785 metric_value: MetricNumber,
786 _: Vec<String>,
787 _: Vec<String>,
788 _: Option<Exemplar>,
789 _: bool| {
790 let value = metric_value.as_f64();
791 if value < 0. || value.is_nan() {
792 return Err(ParseError::InvalidMetric(format!(
793 "Summary sums must be non negative (got: {})",
794 metric_value.as_f64()
795 )));
796 }
797
798 if let MetricValueMarshal::Summary(summary_value) =
799 &mut existing_metric.value
800 {
801 if summary_value.sum.is_none() {
802 summary_value.sum = Some(metric_value);
803 Ok(())
804 } else {
805 Err(ParseError::DuplicateMetric)
806 }
807 } else {
808 unreachable!();
809 }
810 },
811 ),
812 ),
813 (
814 "",
815 vec!["quantile"],
816 MetricProcesser::new(
817 |existing_metric: &mut MetricMarshal,
818 metric_value: MetricNumber,
819 label_names: Vec<String>,
820 label_values: Vec<String>,
821 _: Option<Exemplar>,
822 _: bool| {
823 let value = metric_value.as_f64();
824 if !value.is_nan() && value < 0. {
825 return Err(ParseError::InvalidMetric(
826 "Summary quantiles can't be negative".to_owned(),
827 ));
828 }
829
830 let bucket_bound: f64 = {
831 let bound_index =
832 label_names.iter().position(|s| s == "quantile").unwrap();
833 let bound = &label_values[bound_index];
834
835 match bound.parse() {
836 Ok(f) => f,
837 Err(_) => {
838 return Err(ParseError::InvalidMetric(format!(
839 "Summary bounds must be numbers (got: {})",
840 bound
841 )));
842 }
843 }
844 };
845
846 if !(0. ..=1.).contains(&bucket_bound) || bucket_bound.is_nan() {
847 return Err(ParseError::InvalidMetric(format!(
848 "Summary bounds must be between 0 and 1 (got: {})",
849 bucket_bound
850 )));
851 }
852
853 let quantile = Quantile {
854 quantile: bucket_bound,
855 value: metric_value,
856 };
857
858 if let MetricValueMarshal::Summary(summary_value) =
859 &mut existing_metric.value
860 {
861 summary_value.quantiles.push(quantile);
862 } else {
863 unreachable!();
864 }
865
866 Ok(())
867 },
868 ),
869 ),
870 ],
871 ),
872 ];
873
874 let metric_type = self.family_type.as_ref().cloned().unwrap_or_default();
875
876 if !metric_type.can_have_exemplar(metric_name) && exemplar.is_some() {
877 return Err(ParseError::InvalidMetric(format!(
878 "Metric Type {:?} is not allowed exemplars",
879 metric_type
880 )));
881 }
882
883 for (test_type, actions) in handlers {
884 if test_type.contains(&metric_type) {
885 for (suffix, mandatory_labels, action) in actions {
886 if !metric_name.ends_with(suffix) {
887 continue;
888 }
889
890 let mut actual_label_names = label_names.clone();
891 let mut actual_label_values = label_values.clone();
892 for label in mandatory_labels {
893 if !label_names.contains(&label.to_owned()) {
894 return Err(ParseError::InvalidMetric(format!(
895 "Missing mandatory label for metric: {}",
896 label
897 )));
898 }
899
900 let index = actual_label_names.iter().position(|s| s == label).unwrap();
901
902 actual_label_names.remove(index);
903 actual_label_values.remove(index);
904 }
905
906 match &self.current_label_set {
907 None => self.current_label_set = Some(actual_label_values.clone()),
908 Some(s) => {
909 if s != &actual_label_values
910 && self.seen_label_sets.contains(&actual_label_values)
911 {
912 return Err(ParseError::InvalidMetric(format!(
913 "Interwoven labelsets: Found {:?} after {:?}",
914 s,
915 self.current_label_set.as_ref().unwrap()
916 )));
917 }
918 }
919 }
920
921 self.current_label_set = Some(actual_label_values.clone());
922 self.seen_label_sets.push(actual_label_values.clone());
923
924 let name = &metric_name.to_owned();
925 self.try_set_label_names(
926 name,
927 LabelNames::new(name, metric_type, actual_label_names),
928 )?;
929
930 let metric_name = metric_name.trim_end_matches(suffix);
931 if self.name.is_some() && self.name.as_ref().unwrap() != metric_name {
932 return Err(ParseError::InvalidMetric(format!(
933 "Invalid Name in metric family: {} != {}",
934 metric_name,
935 self.name.as_ref().unwrap()
936 )));
937 } else if self.name.is_none() {
938 self.name = Some(metric_name.to_owned());
939 }
940
941 let (existing_metric, created) = match self
942 .get_metric_by_labelset_mut(&actual_label_values)
943 {
944 Some(metric) => {
945 match (metric.timestamp.as_ref(), timestamp.as_ref()) {
946 (Some(metric_timestamp), Some(timestamp)) if timestamp < metric_timestamp => return Err(ParseError::InvalidMetric(format!("Timestamps went backwarts in family - saw {} and then saw{}", metric_timestamp, timestamp))),
947 (Some(_), None) | (None, Some(_)) => return Err(ParseError::InvalidMetric("Missing timestamp in family (one metric had a timestamp, another didn't)".to_string())),
948 (Some(metric_timestamp), Some(timestamp)) if timestamp >= metric_timestamp && !metric_type.can_have_multiple_lines() => return Ok(()),
949 _ => (metric, false)
950 }
951 }
952 None => {
953 let new_metric = self
954 .family_type
955 .as_ref()
956 .unwrap_or(&OpenMetricsType::Unknown)
957 .get_type_value();
958 self.add_metric(MetricMarshal::new(
959 actual_label_values.clone(),
960 timestamp,
961 new_metric,
962 ));
963 (
964 self.get_metric_by_labelset_mut(&actual_label_values)
965 .unwrap(),
966 true,
967 )
968 }
969 };
970
971 return action.0(
972 existing_metric,
973 metric_value,
974 label_names,
975 label_values,
976 exemplar,
977 created,
978 );
979 }
980 }
981 }
982
983 return Err(ParseError::InvalidMetric(format!(
984 "Found weird metric name for type ({:?}): {}",
985 metric_type, metric_name
986 )));
987 }
988}
989
990impl From<MetricFamilyMarshal<OpenMetricsType>>
991 for MetricFamily<OpenMetricsType, OpenMetricsValue>
992{
993 fn from(marshal: MetricFamilyMarshal<OpenMetricsType>) -> Self {
994 assert!(marshal.name.is_some());
995
996 MetricFamily::new(
997 marshal.name.unwrap(),
998 marshal
999 .label_names
1000 .map(|names| names.names)
1001 .unwrap_or_default(),
1002 marshal.family_type.unwrap_or_default(),
1003 marshal.help.unwrap_or_default(),
1004 marshal.unit.unwrap_or_default(),
1005 )
1006 .with_samples(marshal.metrics.into_iter().map(|m| m.into()))
1007 .unwrap()
1008 }
1009}
1010
1011pub fn parse_openmetrics(
1012 exposition_bytes: &str,
1013) -> Result<MetricsExposition<OpenMetricsType, OpenMetricsValue>, ParseError> {
1014 use pest::iterators::{Pair, Pairs};
1015
1016 fn parse_name(pair: Pair<Rule>) -> String {
1018 match pair.as_rule() {
1019 Rule::quotedname => unescape(pair.into_inner().next().unwrap().as_str()),
1020 _ => pair.as_str().to_owned(),
1021 }
1022 }
1023
1024 fn parse_metric_descriptor(
1025 pair: Pair<Rule>,
1026 family: &mut MetricFamilyMarshal<OpenMetricsType>,
1027 ) -> Result<(), ParseError> {
1028 assert_eq!(pair.as_rule(), Rule::metricdescriptor);
1029
1030 let mut descriptor = pair.into_inner();
1031 let descriptor_type = descriptor.next().unwrap();
1032 let metric_name = parse_name(descriptor.next().unwrap());
1033
1034 match descriptor_type.as_rule() {
1035 Rule::kw_help => {
1036 let help_text = descriptor.next().map(|s| s.as_str()).unwrap_or_default();
1037 family.set_or_test_name(metric_name)?;
1038 family.try_add_help(unescape(help_text))?;
1039 }
1040 Rule::kw_type => {
1041 let family_type = descriptor.next().unwrap().as_str();
1042 family.set_or_test_name(metric_name)?;
1043 family.try_add_type(OpenMetricsType::try_from(family_type)?)?;
1044 }
1045 Rule::kw_unit => {
1046 let unit = descriptor.next().map(|s| s.as_str()).unwrap_or_default();
1047 if family.name.is_none() || &metric_name != family.name.as_ref().unwrap() {
1048 return Err(ParseError::InvalidMetric(
1049 "UNIT metric name doesn't match family".to_owned(),
1050 ));
1051 }
1052 family.try_add_unit(unit.to_string())?;
1053 }
1054 _ => unreachable!(),
1055 }
1056
1057 Ok(())
1058 }
1059
1060 fn parse_exemplar(pair: Pair<Rule>) -> Result<Exemplar, ParseError> {
1061 let mut inner = pair.into_inner();
1062
1063 let labels = inner.next().unwrap();
1064 assert_eq!(labels.as_rule(), Rule::labels);
1065
1066 let labels = parse_labels(labels.into_inner())?.into_iter().collect();
1067
1068 let id = inner.next().unwrap().as_str();
1069 let id = match id.parse() {
1070 Ok(i) => i,
1071 Err(_) => {
1072 return Err(ParseError::InvalidMetric(format!(
1073 "Exemplar value must be a number (got: {})",
1074 id
1075 )))
1076 }
1077 };
1078
1079 let timestamp = match inner.next() {
1080 Some(timestamp) => match timestamp.as_str().parse() {
1081 Ok(f) => Some(f),
1082 Err(_) => {
1083 return Err(ParseError::InvalidMetric(format!(
1084 "Exemplar timestamp must be a number (got: {})",
1085 timestamp.as_str()
1086 )))
1087 }
1088 },
1089 None => None,
1090 };
1091
1092 Ok(Exemplar::new(labels, id, timestamp))
1093 }
1094
1095 fn parse_labels(label_pairs: Pairs<Rule>) -> Result<Vec<(String, String)>, ParseError> {
1096 let mut labels: Vec<(String, String)> = Vec::new();
1097
1098 for label in label_pairs {
1099 assert_eq!(label.as_rule(), Rule::label);
1100 let mut label = label.into_inner();
1101 let name = parse_name(label.next().unwrap());
1102 let value = unescape(label.next().unwrap().as_str());
1103
1104 if labels.iter().any(|(n, _)| n == &name) {
1105 return Err(ParseError::InvalidMetric(format!(
1106 "Found label `{}` twice in the same labelset",
1107 name
1108 )));
1109 }
1110
1111 labels.push((name, value));
1112 }
1113
1114 labels.sort_unstable();
1115
1116 Ok(labels)
1117 }
1118
1119 fn parse_sample(
1120 pair: Pair<Rule>,
1121 family: &mut MetricFamilyMarshal<OpenMetricsType>,
1122 ) -> Result<(), ParseError> {
1123 assert_eq!(pair.as_rule(), Rule::sample);
1124
1125 let mut descriptor = pair.into_inner();
1126 let first = descriptor.next().unwrap();
1127
1128 let (metric_name, labels) = if first.as_rule() == Rule::namedlabels {
1129 let mut inner = first.into_inner();
1131 let name = parse_name(inner.next().unwrap());
1132 (name, parse_labels(inner)?)
1133 } else {
1134 let labels = match descriptor.peek().unwrap().as_rule() {
1135 Rule::labels => parse_labels(descriptor.next().unwrap().into_inner())?,
1136 _ => Vec::new(),
1137 };
1138 (first.as_str().to_owned(), labels)
1139 };
1140
1141 let (label_names, label_values): (Vec<_>, Vec<_>) = labels.into_iter().unzip();
1142
1143 let value = descriptor.next().unwrap().as_str();
1144 let value = match value.parse() {
1145 Ok(f) => MetricNumber::Int(f),
1146 Err(_) => match value.parse() {
1147 Ok(f) => MetricNumber::Float(f),
1148 Err(_) => {
1149 return Err(ParseError::InvalidMetric(format!(
1150 "Metric Value must be a number (got: {})",
1151 value
1152 )));
1153 }
1154 },
1155 };
1156
1157 let mut timestamp = None;
1158 let mut exemplar = None;
1159
1160 if descriptor.peek().is_some()
1161 && descriptor.peek().as_ref().unwrap().as_rule() == Rule::timestamp
1162 {
1163 timestamp = Some(descriptor.next().unwrap().as_str().parse().unwrap());
1164 }
1165
1166 if descriptor.peek().is_some()
1167 && descriptor.peek().as_ref().unwrap().as_rule() == Rule::exemplar
1168 {
1169 exemplar = Some(parse_exemplar(descriptor.next().unwrap())?);
1170 }
1171
1172 family.process_new_metric(
1173 &metric_name,
1174 value,
1175 label_names,
1176 label_values,
1177 timestamp,
1178 exemplar,
1179 )?;
1180
1181 Ok(())
1182 }
1183
1184 fn parse_metric_family(
1185 pair: Pair<Rule>,
1186 ) -> Result<MetricFamily<OpenMetricsType, OpenMetricsValue>, ParseError> {
1187 assert_eq!(pair.as_rule(), Rule::metricfamily);
1188
1189 let mut metric_family = MetricFamilyMarshal::empty();
1190
1191 for child in pair.into_inner() {
1192 match child.as_rule() {
1193 Rule::metricdescriptor => {
1194 if metric_family.metrics.is_empty() {
1195 parse_metric_descriptor(child, &mut metric_family)?;
1196 } else {
1197 return Err(ParseError::InvalidMetric(
1198 "Metric Descriptor after samples".to_owned(),
1199 ));
1200 }
1201 }
1202 Rule::sample => {
1203 parse_sample(child, &mut metric_family)?;
1204 }
1205 _ => unreachable!(),
1206 }
1207 }
1208
1209 metric_family.validate()?;
1210
1211 Ok(metric_family.into())
1212 }
1213
1214 let exposition_marshal = OpenMetricsParser::parse(Rule::exposition, exposition_bytes)?
1215 .next()
1216 .unwrap();
1217 let mut exposition = MetricsExposition::new();
1218
1219 assert_eq!(exposition_marshal.as_rule(), Rule::exposition);
1220
1221 let mut found_eof = false;
1222 for span in exposition_marshal.into_inner() {
1223 match span.as_rule() {
1224 Rule::metricfamily => {
1225 let family = parse_metric_family(span)?;
1226
1227 if exposition.families.contains_key(&family.family_name) {
1228 return Err(ParseError::InvalidMetric(format!(
1229 "Found a metric family called {}, after that family was finalised",
1230 family.family_name
1231 )));
1232 }
1233
1234 exposition
1235 .families
1236 .insert(family.family_name.clone(), family);
1237 }
1238 Rule::kw_eof => {
1239 found_eof = true;
1240
1241 if span.as_span().end() != exposition_bytes.len()
1242 && !(span.as_span().end() == exposition_bytes.len() - 1
1243 && exposition_bytes.ends_with('\n'))
1244 {
1245 return Err(ParseError::InvalidMetric(
1246 "Found text after the EOF token".to_string(),
1247 ));
1248 }
1249 }
1250 _ => unreachable!(),
1251 }
1252 }
1253
1254 if !found_eof {
1255 return Err(ParseError::InvalidMetric(
1256 "Didn't find an EOF token".to_string(),
1257 ));
1258 }
1259
1260 Ok(exposition)
1261}