///|
/// Structural counts for an exposition document.
pub(all) struct MetricsSummary {
family_count : Int
sample_count : Int
label_count : Int
exemplar_count : Int
counter_count : Int
gauge_count : Int
histogram_count : Int
gauge_histogram_count : Int
summary_count : Int
info_count : Int
state_set_count : Int
unknown_count : Int
} derive(Eq)
///|
/// Count families, samples, labels, exemplars, and family types.
pub fn summarize(document : Document) -> MetricsSummary {
let mut sample_count = 0
let mut label_count = 0
let mut exemplar_count = 0
let mut counter_count = 0
let mut gauge_count = 0
let mut histogram_count = 0
let mut gauge_histogram_count = 0
let mut summary_count = 0
let mut info_count = 0
let mut state_set_count = 0
let mut unknown_count = 0
for family in document.families {
match family.metric_type {
Counter => counter_count += 1
Gauge => gauge_count += 1
Histogram => histogram_count += 1
GaugeHistogram => gauge_histogram_count += 1
Summary => summary_count += 1
Info => info_count += 1
StateSet => state_set_count += 1
Unknown => unknown_count += 1
}
sample_count += family.samples.length()
for sample in family.samples {
label_count += sample.labels.length()
match sample.exemplar {
Some(exemplar) => {
exemplar_count += 1
label_count += exemplar.labels.length()
}
None => ()
}
}
}
{
family_count: document.families.length(),
sample_count,
label_count,
exemplar_count,
counter_count,
gauge_count,
histogram_count,
gauge_histogram_count,
summary_count,
info_count,
state_set_count,
unknown_count,
}
}
///|
/// Return structural counts for this document.
pub fn Document::summary(self : Document) -> MetricsSummary {
summarize(self)
}
///|
/// Render summary counts on one stable machine-readable line.
pub fn MetricsSummary::to_text(self : MetricsSummary) -> String {
"families=\{self.family_count} samples=\{self.sample_count} labels=\{self.label_count} exemplars=\{self.exemplar_count} counter=\{self.counter_count} gauge=\{self.gauge_count} histogram=\{self.histogram_count} gaugehistogram=\{self.gauge_histogram_count} summary=\{self.summary_count} info=\{self.info_count} stateset=\{self.state_set_count} unknown=\{self.unknown_count}"
}
///|
fn severity_keyword(severity : Severity) -> String {
match severity {
Error => "error"
Warning => "warning"
}
}
///|
/// Render one validation issue without relying on debug formatting.
pub fn ValidationIssue::to_text(self : ValidationIssue) -> String {
let family = if self.family == "" { "" } else { self.family }
let sample = match self.sample {
Some(name) => " sample=\{name}"
None => ""
}
"\{severity_keyword(self.severity)} [\{self.code}] family=\{family}\{sample}: \{self.message}"
}
///|
/// Render all issues followed by an error/warning total.
pub fn ValidationReport::to_text(self : ValidationReport) -> String {
let out = StringBuilder()
for issue in self.issues {
out.write_string(issue.to_text())
out.write_char('\n')
}
out.write_string("errors=\{self.error_count} warnings=\{self.warning_count}")
out.to_string()
}