1use std::convert::TryFrom;
2
3use pest::Parser;
4
5use crate::{
6 internal::{
7 CounterValueMarshal, LabelNames, MarshalledMetric, MarshalledMetricFamily,
8 MetricFamilyMarshal, MetricMarshal, MetricProcesser, MetricValueMarshal, MetricsType,
9 unescape, unescape_help,
10 },
11 public::*,
12};
13
14#[derive(Parser)]
15#[grammar = "prometheus/prometheus.pest"]
16struct PrometheusParser;
17
18impl From<pest::error::Error<Rule>> for ParseError {
19 fn from(err: pest::error::Error<Rule>) -> Self {
20 ParseError::ParseError(err.to_string())
21 }
22}
23
24impl MarshalledMetricFamily for MetricFamilyMarshal<PrometheusType> {
25 type Error = ParseError;
26
27 fn validate(&self) -> Result<(), ParseError> {
28 for metric in self.metrics.iter() {
29 metric.validate(self)?;
30 }
31
32 Ok(())
33 }
34
35 fn process_new_metric(
36 &mut self,
37 metric_name: &str,
38 metric_value: MetricNumber,
39 label_names: Vec<String>,
40 label_values: Vec<String>,
41 timestamp: Option<Timestamp>,
42 exemplar: Option<Exemplar>,
43 ) -> Result<(), Self::Error> {
44 let handlers = vec![
45 (
46 vec![PrometheusType::Histogram],
47 vec![
48 (
49 "_bucket",
50 vec!["le"],
51 MetricProcesser::new(
52 |existing_metric: &mut MetricMarshal,
53 metric_value: MetricNumber,
54 label_names: Vec<String>,
55 label_values: Vec<String>,
56 exemplar: Option<Exemplar>,
57 _: bool| {
58 let bucket_bound: f64 = {
59 let bound_index =
60 label_names.iter().position(|s| s == "le").unwrap();
61
62 let bound = &label_values[bound_index];
63 match bound.parse() {
64 Ok(f) => f,
65 Err(_) => {
66 return Err(ParseError::InvalidMetric(format!(
67 "Invalid histogram bound: {}",
68 bound
69 )));
70 }
71 }
72 };
73
74 let bucket = HistogramBucket {
75 count: metric_value,
76 upper_bound: bucket_bound,
77 exemplar,
78 };
79
80 if let MetricValueMarshal::Histogram(value) =
81 &mut existing_metric.value
82 {
83 value.buckets.push(bucket);
84 } else {
85 unreachable!();
86 }
87
88 Ok(())
89 },
90 ),
91 ),
92 (
93 "_count",
94 vec![],
95 MetricProcesser::new(
96 |existing_metric: &mut MetricMarshal,
97 metric_value: MetricNumber,
98 _: Vec<String>,
99 _: Vec<String>,
100 _: Option<Exemplar>,
101 _: bool| {
102 if let MetricValueMarshal::Histogram(histogram_value) =
103 &mut existing_metric.value
104 {
105 let metric_value = if let Some(value) = metric_value.as_i64() {
106 if value < 0 {
107 return Err(ParseError::InvalidMetric(format!(
108 "Histogram counts must be positive (got: {})",
109 value
110 )));
111 }
112
113 value as u64
114 } else {
115 return Err(ParseError::InvalidMetric(format!(
116 "Histogram counts must be integers (got: {})",
117 metric_value.as_f64()
118 )));
119 };
120
121 match histogram_value.count {
122 Some(_) => {
123 return Err(ParseError::DuplicateMetric);
124 }
125 None => {
126 histogram_value.count = Some(metric_value);
127 }
128 };
129 } else {
130 unreachable!();
131 }
132
133 Ok(())
134 },
135 ),
136 ),
137 (
138 "_sum",
139 vec![],
140 MetricProcesser::new(
141 |existing_metric: &mut MetricMarshal,
142 metric_value: MetricNumber,
143 _: Vec<String>,
144 _: Vec<String>,
145 _: Option<Exemplar>,
146 _: bool| {
147 if let MetricValueMarshal::Histogram(histogram_value) =
148 &mut existing_metric.value
149 {
150 if histogram_value.sum.is_some() {
151 return Err(ParseError::DuplicateMetric);
152 }
153
154 histogram_value.sum = Some(metric_value);
155
156 Ok(())
157 } else {
158 unreachable!();
159 }
160 },
161 ),
162 ),
163 (
164 "",
165 vec![],
166 MetricProcesser::new(
167 |existing_metric: &mut MetricMarshal,
168 metric_value: MetricNumber,
169 _: Vec<String>,
170 _: Vec<String>,
171 _: Option<Exemplar>,
172 _: bool| {
173 if let MetricValueMarshal::Histogram(histogram_value) =
174 &mut existing_metric.value
175 {
176 let metric_value = if let Some(value) = metric_value.as_i64() {
177 if value < 0 {
178 return Err(ParseError::InvalidMetric(format!(
179 "Histogram counts must be positive (got: {})",
180 value
181 )));
182 }
183
184 value as u64
185 } else {
186 return Err(ParseError::InvalidMetric(format!(
187 "Histogram counts must be integers (got: {})",
188 metric_value.as_f64()
189 )));
190 };
191
192 match histogram_value.count {
193 Some(_) => {
194 return Err(ParseError::DuplicateMetric);
195 }
196 None => {
197 histogram_value.count = Some(metric_value);
198 }
199 };
200 } else {
201 unreachable!();
202 }
203
204 Ok(())
205 },
206 ),
207 ),
208 ],
209 ),
210 (
211 vec![PrometheusType::Counter],
212 vec![(
213 "",
214 vec![],
215 MetricProcesser::new(
216 |existing_metric: &mut MetricMarshal,
217 metric_value: MetricNumber,
218 _: Vec<String>,
219 _: Vec<String>,
220 exemplar: Option<Exemplar>,
221 _: bool| {
222 if let MetricValueMarshal::Counter(counter_value) =
223 &mut existing_metric.value
224 {
225 if counter_value.value.is_some() {
226 return Err(ParseError::DuplicateMetric);
227 }
228
229 let value = metric_value.as_f64();
230 if value < 0. || value.is_nan() {
231 return Err(ParseError::InvalidMetric(format!(
232 "Counter totals must be non negative (got: {})",
233 metric_value.as_f64()
234 )));
235 }
236
237 counter_value.value = Some(metric_value);
238 counter_value.exemplar = exemplar;
239 } else {
240 unreachable!();
241 }
242
243 Ok(())
244 },
245 ),
246 )],
247 ),
248 (
249 vec![PrometheusType::Gauge],
250 vec![(
251 "",
252 vec![],
253 MetricProcesser::new(
254 |existing_metric: &mut MetricMarshal,
255 metric_value: MetricNumber,
256 _: Vec<String>,
257 _: Vec<String>,
258 _: Option<Exemplar>,
259 _: bool| {
260 if let MetricValueMarshal::Gauge(gauge_value) =
261 &mut existing_metric.value
262 {
263 if gauge_value.is_some() {
264 return Err(ParseError::DuplicateMetric);
265 }
266
267 existing_metric.value =
268 MetricValueMarshal::Gauge(Some(metric_value));
269 } else {
270 unreachable!();
271 }
272
273 Ok(())
274 },
275 ),
276 )],
277 ),
278 (
279 vec![PrometheusType::Unknown],
280 vec![(
281 "",
282 vec![],
283 MetricProcesser::new(
284 |existing_metric: &mut MetricMarshal,
285 metric_value: MetricNumber,
286 _: Vec<String>,
287 _: Vec<String>,
288 _: Option<Exemplar>,
289 _: bool| {
290 if let MetricValueMarshal::Unknown(unknown_value) =
291 &mut existing_metric.value
292 {
293 if unknown_value.is_some() {
294 return Err(ParseError::DuplicateMetric);
295 }
296
297 existing_metric.value =
298 MetricValueMarshal::Unknown(Some(metric_value));
299 } else {
300 unreachable!();
301 }
302
303 Ok(())
304 },
305 ),
306 )],
307 ),
308 (
309 vec![PrometheusType::Summary],
310 vec![
311 (
312 "_count",
313 vec![],
314 MetricProcesser::new(
315 |existing_metric: &mut MetricMarshal,
316 metric_value: MetricNumber,
317 _: Vec<String>,
318 _: Vec<String>,
319 _: Option<Exemplar>,
320 _: bool| {
321 if let MetricValueMarshal::Summary(summary_value) =
322 &mut existing_metric.value
323 {
324 let metric_value = if let Some(value) = metric_value.as_i64() {
325 if value < 0 {
326 return Err(ParseError::InvalidMetric(format!(
327 "Summary counts must be positive (got: {})",
328 value
329 )));
330 }
331 value as u64
332 } else {
333 return Err(ParseError::InvalidMetric(format!(
334 "Summary counts must be integers (got: {})",
335 metric_value.as_f64()
336 )));
337 };
338
339 if summary_value.count.is_none() {
340 summary_value.count = Some(metric_value);
341 } else {
342 return Err(ParseError::DuplicateMetric);
343 }
344 } else {
345 unreachable!();
346 }
347
348 Ok(())
349 },
350 ),
351 ),
352 (
353 "_sum",
354 vec![],
355 MetricProcesser::new(
356 |existing_metric: &mut MetricMarshal,
357 metric_value: MetricNumber,
358 _: Vec<String>,
359 _: Vec<String>,
360 _: Option<Exemplar>,
361 _: bool| {
362 let value = metric_value.as_f64();
363 if value < 0. || value.is_nan() {
364 return Err(ParseError::InvalidMetric(format!(
365 "Counter totals must be non negative (got: {})",
366 metric_value.as_f64()
367 )));
368 }
369
370 if let MetricValueMarshal::Summary(summary_value) =
371 &mut existing_metric.value
372 {
373 if summary_value.sum.is_none() {
374 summary_value.sum = Some(metric_value);
375 Ok(())
376 } else {
377 Err(ParseError::DuplicateMetric)
378 }
379 } else {
380 unreachable!();
381 }
382 },
383 ),
384 ),
385 (
386 "",
387 vec!["quantile"],
388 MetricProcesser::new(
389 |existing_metric: &mut MetricMarshal,
390 metric_value: MetricNumber,
391 label_names: Vec<String>,
392 label_values: Vec<String>,
393 _: Option<Exemplar>,
394 _: bool| {
395 let value = metric_value.as_f64();
396 if !value.is_nan() && value < 0. {
397 return Err(ParseError::InvalidMetric(
398 "Summary quantiles can't be negative".to_owned(),
399 ));
400 }
401
402 let bucket_bound: f64 = {
403 let bound_index =
404 label_names.iter().position(|s| s == "quantile").unwrap();
405 let bound = &label_values[bound_index];
406
407 match bound.parse() {
408 Ok(f) => f,
409 Err(_) => {
410 return Err(ParseError::InvalidMetric(format!(
411 "Summary bounds must be numbers (got: {})",
412 bound
413 )));
414 }
415 }
416 };
417
418 if !(0. ..=1.).contains(&bucket_bound) || bucket_bound.is_nan() {
419 return Err(ParseError::InvalidMetric(format!(
420 "Summary bounds must be between 0 and 1 (got: {})",
421 bucket_bound
422 )));
423 }
424
425 let quantile = Quantile {
426 quantile: bucket_bound,
427 value: metric_value,
428 };
429
430 if let MetricValueMarshal::Summary(summary_value) =
431 &mut existing_metric.value
432 {
433 summary_value.quantiles.push(quantile);
434 } else {
435 unreachable!();
436 }
437
438 Ok(())
439 },
440 ),
441 ),
442 ],
443 ),
444 ];
445
446 let metric_type = self.family_type.as_ref().cloned().unwrap_or_default();
447
448 if !metric_type.can_have_exemplar(metric_name) && exemplar.is_some() {
449 return Err(ParseError::InvalidMetric(format!(
450 "Metric Type {:?} is not allowed exemplars",
451 metric_type
452 )));
453 }
454
455 for (test_type, actions) in handlers {
456 if test_type.contains(&metric_type) {
457 for (suffix, mandatory_labels, action) in actions {
458 if !metric_name.ends_with(suffix) {
459 continue;
460 }
461
462 let mut actual_label_names = label_names.clone();
463 let mut actual_label_values = label_values.clone();
464 for label in mandatory_labels {
465 if !label_names.contains(&label.to_owned()) {
466 return Err(ParseError::InvalidMetric(format!(
467 "Missing mandatory label for metric: {}",
468 label
469 )));
470 }
471
472 let index = actual_label_names.iter().position(|s| s == label).unwrap();
473
474 actual_label_names.remove(index);
475 actual_label_values.remove(index);
476 }
477
478 let name = &metric_name.to_owned();
479 self.try_set_label_names(
480 name,
481 LabelNames::new(name, metric_type.clone(), actual_label_names),
482 )?;
483
484 let metric_name = metric_name.trim_end_matches(suffix);
485 if self.name.is_some() && self.name.as_ref().unwrap() != metric_name {
486 return Err(ParseError::InvalidMetric(format!(
487 "Invalid Name in metric family: {} != {}",
488 metric_name,
489 self.name.as_ref().unwrap()
490 )));
491 } else if self.name.is_none() {
492 self.name = Some(metric_name.to_owned());
493 }
494
495 let (existing_metric, created) = match self
496 .get_metric_by_labelset_mut(&actual_label_values)
497 {
498 Some(metric) => {
499 match (metric.timestamp.as_ref(), timestamp.as_ref()) {
500 (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))),
501 (Some(_), None) | (None, Some(_)) => return Err(ParseError::InvalidMetric("Missing timestamp in family (one metric had a timestamp, another didn't)".to_string())),
502 (Some(metric_timestamp), Some(timestamp)) if timestamp >= metric_timestamp && !metric_type.can_have_multiple_lines() => return Ok(()),
503 _ => (metric, false)
504 }
505 }
506 None => {
507 let new_metric = self
508 .family_type
509 .as_ref()
510 .unwrap_or(&PrometheusType::Unknown)
511 .get_type_value();
512 self.add_metric(MetricMarshal::new(
513 actual_label_values.clone(),
514 timestamp,
515 new_metric,
516 ));
517 (
518 self.get_metric_by_labelset_mut(&actual_label_values)
519 .unwrap(),
520 true,
521 )
522 }
523 };
524
525 return action.0(
526 existing_metric,
527 metric_value,
528 label_names,
529 label_values,
530 exemplar,
531 created,
532 );
533 }
534 }
535 }
536
537 return Err(ParseError::InvalidMetric(format!(
538 "Found weird metric name for type ({:?}): {}",
539 metric_type, metric_name
540 )));
541 }
542}
543
544impl Default for PrometheusType {
545 fn default() -> Self {
546 PrometheusType::Unknown
547 }
548}
549
550impl From<MetricMarshal> for Sample<PrometheusValue> {
551 fn from(s: MetricMarshal) -> Sample<PrometheusValue> {
552 Sample::new(s.label_values, s.timestamp, s.value.into())
553 }
554}
555
556impl MarshalledMetric<PrometheusType> for MetricMarshal {
557 fn validate(&self, family: &MetricFamilyMarshal<PrometheusType>) -> Result<(), ParseError> {
558 if family.label_names.is_none() && !self.label_values.is_empty()
560 || (family.label_names.as_ref().unwrap().names.len() != self.label_values.len())
561 {
562 return Err(ParseError::InvalidMetric(format!(
563 "Metrics in family have different label sets: {:?} {:?}",
564 &family.label_names, self.label_values
565 )));
566 }
567
568 if family.unit.is_some() && family.metrics.is_empty() {
569 return Err(ParseError::InvalidMetric(
570 "Can't have metric with unit and no samples".to_owned(),
571 ));
572 }
573
574 if let MetricValueMarshal::Histogram(histogram_value) = &self.value {
575 if histogram_value.buckets.is_empty() {
576 return Err(ParseError::InvalidMetric(
577 "Histograms must have at least one bucket".to_owned(),
578 ));
579 }
580
581 if !histogram_value
582 .buckets
583 .iter()
584 .any(|b| b.upper_bound == f64::INFINITY)
585 {
586 return Err(ParseError::InvalidMetric(format!(
587 "Histograms must have a +INF bucket: {:?}",
588 histogram_value.buckets
589 )));
590 }
591
592 let buckets = &histogram_value.buckets;
593
594 let has_negative_bucket = buckets.iter().any(|f| f.upper_bound < 0.);
595
596 if has_negative_bucket {
597 if histogram_value.sum.is_some() {
598 return Err(ParseError::InvalidMetric(
599 "Histograms cannot have a sum with a negative bucket".to_owned(),
600 ));
601 }
602 } else if histogram_value.sum.is_some()
603 && histogram_value.sum.as_ref().unwrap().as_f64() < 0.
604 {
605 return Err(ParseError::InvalidMetric(
606 "Histograms cannot have a negative sum without a negative bucket".to_owned(),
607 ));
608 }
609
610 if histogram_value.sum.is_some() && histogram_value.count.is_none() {
611 return Err(ParseError::InvalidMetric(
612 "Count must be present if sum is present".to_owned(),
613 ));
614 }
615
616 if histogram_value.sum.is_none() && histogram_value.count.is_some() {
617 return Err(ParseError::InvalidMetric(
618 "Sum must be present if count is present".to_owned(),
619 ));
620 }
621
622 let mut last = f64::NEG_INFINITY;
623 for bucket in buckets {
624 if bucket.count.as_f64() < last {
625 return Err(ParseError::InvalidMetric(
626 "Histograms must be cumulative".to_owned(),
627 ));
628 }
629
630 last = bucket.count.as_f64();
631 }
632 }
633
634 Ok(())
635 }
636}
637
638impl From<MetricValueMarshal> for PrometheusValue {
639 fn from(m: MetricValueMarshal) -> PrometheusValue {
640 match m {
641 MetricValueMarshal::Unknown(u) => PrometheusValue::Unknown(u.unwrap()),
642 MetricValueMarshal::Gauge(g) => PrometheusValue::Gauge(g.unwrap()),
643 MetricValueMarshal::Counter(c) => PrometheusValue::Counter(c.into()),
644 MetricValueMarshal::Histogram(h) => PrometheusValue::Histogram(h),
645 MetricValueMarshal::Summary(s) => PrometheusValue::Summary(s),
646 _ => unreachable!(),
647 }
648 }
649}
650
651impl MetricsType for PrometheusType {
652 fn get_ignored_labels(&self, metric_name: &str) -> &[&str] {
653 match self {
654 PrometheusType::Histogram if metric_name.ends_with("_bucket") => &["le"],
655 _ => &[],
656 }
657 }
658
659 fn get_type_value(&self) -> MetricValueMarshal {
660 match self {
661 PrometheusType::Histogram => MetricValueMarshal::Histogram(HistogramValue::default()),
662 PrometheusType::Counter => MetricValueMarshal::Counter(CounterValueMarshal::default()),
663 PrometheusType::Unknown => MetricValueMarshal::Unknown(None),
664 PrometheusType::Gauge => MetricValueMarshal::Gauge(None),
665 PrometheusType::Summary => MetricValueMarshal::Summary(SummaryValue::default()),
666 }
667 }
668
669 fn can_have_multiple_lines(&self) -> bool {
670 matches!(
671 self,
672 PrometheusType::Counter | PrometheusType::Histogram | PrometheusType::Summary
673 )
674 }
675
676 fn can_have_exemplar(&self, metric_name: &str) -> bool {
677 match self {
678 PrometheusType::Counter => metric_name.ends_with("_total"),
679 PrometheusType::Histogram => metric_name.ends_with("_bucket"),
680 _ => false,
681 }
682 }
683
684 fn can_have_units(&self) -> bool {
685 false
686 }
687}
688
689impl From<MetricFamilyMarshal<PrometheusType>> for MetricFamily<PrometheusType, PrometheusValue> {
690 fn from(marshal: MetricFamilyMarshal<PrometheusType>) -> Self {
691 assert!(marshal.name.is_some());
692
693 MetricFamily::new(
694 marshal.name.unwrap(),
695 marshal
696 .label_names
697 .map(|names| names.names)
698 .unwrap_or_default(),
699 marshal.family_type.unwrap_or_default(),
700 marshal.help.unwrap_or_default(),
701 marshal.unit.unwrap_or_default(),
702 )
703 .with_samples(marshal.metrics.into_iter().map(|m| m.into()))
704 .unwrap()
705 }
706}
707
708impl TryFrom<&str> for PrometheusType {
709 type Error = ParseError;
710
711 fn try_from(value: &str) -> Result<Self, Self::Error> {
712 match value {
713 "counter" => Ok(PrometheusType::Counter),
714 "gauge" => Ok(PrometheusType::Gauge),
715 "histogram" => Ok(PrometheusType::Histogram),
716 "summary" => Ok(PrometheusType::Summary),
717 "untyped" => Ok(PrometheusType::Unknown),
718 _ => Err(ParseError::InvalidMetric(format!(
719 "Invalid metric type: {}",
720 value
721 ))),
722 }
723 }
724}
725
726pub fn parse_prometheus(
727 exposition_bytes: &str,
728) -> Result<MetricsExposition<PrometheusType, PrometheusValue>, ParseError> {
729 use pest::iterators::{Pair, Pairs};
730
731 fn parse_name(pair: Pair<Rule>) -> String {
733 match pair.as_rule() {
734 Rule::quotedname => unescape(pair.into_inner().next().unwrap().as_str()),
735 _ => pair.as_str().to_owned(),
736 }
737 }
738
739 fn parse_metric_descriptor(
740 pair: Pair<Rule>,
741 family: &mut MetricFamilyMarshal<PrometheusType>,
742 ) -> Result<(), ParseError> {
743 assert_eq!(pair.as_rule(), Rule::metricdescriptor);
744
745 let mut descriptor = pair.into_inner();
746 let descriptor_type = descriptor.next().unwrap();
747 let metric_name = parse_name(descriptor.next().unwrap());
748
749 match descriptor_type.as_rule() {
750 Rule::kw_help => {
751 let help_text = descriptor.next().map(|s| s.as_str()).unwrap_or_default();
752 family.set_or_test_name(metric_name)?;
753 family.try_add_help(unescape_help(help_text))?;
754 }
755 Rule::kw_type => {
756 let family_type = descriptor.next().unwrap().as_str();
757 family.set_or_test_name(metric_name)?;
758 family.try_add_type(PrometheusType::try_from(family_type)?)?;
759 }
760 _ => unreachable!(),
761 }
762
763 Ok(())
764 }
765
766 fn parse_exemplar(pair: Pair<Rule>) -> Result<Exemplar, ParseError> {
767 let mut inner = pair.into_inner();
768
769 let labels = inner.next().unwrap();
770 assert_eq!(labels.as_rule(), Rule::labels);
771
772 let labels = parse_labels(labels.into_inner())?.into_iter().collect();
773
774 let id = inner.next().unwrap().as_str();
775 let id = match id.parse() {
776 Ok(i) => i,
777 Err(_) => {
778 return Err(ParseError::InvalidMetric(format!(
779 "Exemplar value must be a number (got: {})",
780 id
781 )))
782 }
783 };
784
785 let timestamp = match inner.next() {
786 Some(timestamp) => match timestamp.as_str().parse() {
787 Ok(f) => Some(f),
788 Err(_) => {
789 return Err(ParseError::InvalidMetric(format!(
790 "Exemplar timestamp must be a number (got: {})",
791 timestamp.as_str()
792 )))
793 }
794 },
795 None => None,
796 };
797
798 Ok(Exemplar::new(labels, id, timestamp))
799 }
800
801 fn parse_labels(label_pairs: Pairs<Rule>) -> Result<Vec<(String, String)>, ParseError> {
802 let mut labels: Vec<(String, String)> = Vec::new();
803
804 for label in label_pairs {
805 assert_eq!(label.as_rule(), Rule::label);
806 let mut label = label.into_inner();
807 let name = parse_name(label.next().unwrap());
808 let value = unescape(label.next().unwrap().as_str());
809
810 if labels.iter().any(|(n, _)| n == &name) {
811 return Err(ParseError::InvalidMetric(format!(
812 "Found label `{}` twice in the same labelset",
813 name
814 )));
815 }
816
817 labels.push((name, value));
818 }
819
820 labels.sort_unstable();
821
822 Ok(labels)
823 }
824
825 fn parse_sample(
826 pair: Pair<Rule>,
827 family: &mut MetricFamilyMarshal<PrometheusType>,
828 ) -> Result<(), ParseError> {
829 assert_eq!(pair.as_rule(), Rule::metric);
830
831 let mut descriptor = pair.into_inner();
832 let first = descriptor.next().unwrap();
833
834 let (metric_name, labels) = if first.as_rule() == Rule::namedlabels {
835 let mut inner = first.into_inner();
837 let name = parse_name(inner.next().unwrap());
838 (name, parse_labels(inner)?)
839 } else {
840 let labels = match descriptor.peek().unwrap().as_rule() {
841 Rule::labels => parse_labels(descriptor.next().unwrap().into_inner())?,
842 _ => Vec::new(),
843 };
844 (first.as_str().to_owned(), labels)
845 };
846
847 let (label_names, label_values): (Vec<_>, Vec<_>) = labels.into_iter().unzip();
848
849 let value = descriptor.next().unwrap().as_str();
850 let value = match value.parse() {
851 Ok(f) => MetricNumber::Int(f),
852 Err(_) => match value.parse() {
853 Ok(f) => MetricNumber::Float(f),
854 Err(_) => {
855 return Err(ParseError::InvalidMetric(format!(
856 "Metric Value must be a number (got: {})",
857 value
858 )));
859 }
860 },
861 };
862
863 let mut timestamp = None;
864 let mut exemplar = None;
865
866 if descriptor.peek().is_some()
867 && descriptor.peek().as_ref().unwrap().as_rule() == Rule::timestamp
868 {
869 timestamp = Some(descriptor.next().unwrap().as_str().parse().unwrap());
870 }
871
872 if descriptor.peek().is_some()
873 && descriptor.peek().as_ref().unwrap().as_rule() == Rule::exemplar
874 {
875 exemplar = Some(parse_exemplar(descriptor.next().unwrap())?);
876 }
877
878 family.process_new_metric(
879 &metric_name,
880 value,
881 label_names,
882 label_values,
883 timestamp,
884 exemplar,
885 )?;
886
887 Ok(())
888 }
889
890 fn parse_metric_family(
891 pair: Pair<Rule>,
892 ) -> Result<MetricFamily<PrometheusType, PrometheusValue>, ParseError> {
893 assert_eq!(pair.as_rule(), Rule::metricfamily);
894
895 let mut metric_family = MetricFamilyMarshal::empty();
896
897 for child in pair.into_inner() {
898 match child.as_rule() {
899 Rule::metricdescriptor => {
900 if metric_family.metrics.is_empty() {
901 parse_metric_descriptor(child, &mut metric_family)?;
902 } else {
903 return Err(ParseError::InvalidMetric(
904 "Metric Descriptor after samples".to_owned(),
905 ));
906 }
907 }
908 Rule::metric => {
909 parse_sample(child, &mut metric_family)?;
910 }
911 _ => unreachable!(),
912 }
913 }
914
915 metric_family.validate()?;
916
917 Ok(metric_family.into())
918 }
919
920 let exposition_marshal = PrometheusParser::parse(Rule::exposition, exposition_bytes)?
921 .next()
922 .unwrap();
923 let mut exposition = MetricsExposition::new();
924
925 assert_eq!(exposition_marshal.as_rule(), Rule::exposition);
926
927 for span in exposition_marshal.into_inner() {
928 match span.as_rule() {
929 Rule::metricfamily => {
930 let family = parse_metric_family(span)?;
931
932 if exposition.families.contains_key(&family.family_name) {
933 return Err(ParseError::InvalidMetric(format!(
934 "Found a metric family called {}, after that family was finalised",
935 family.family_name
936 )));
937 }
938
939 exposition
940 .families
941 .insert(family.family_name.clone(), family);
942 }
943 Rule::EOI => {}
944 _ => unreachable!(),
945 }
946 }
947
948 Ok(exposition)
949}