///|
/// An opaque identity returned by a successful registry registration.
///
/// A registration is scoped to one `Registry`. It is intentionally not a
/// metric name: an old handle must never unregister a newer metric family that
/// reused the same name.
pub struct Registration {
token : Int
} derive(Debug, Eq)
///|
/// Return the registry-local token for diagnostics and test assertions.
///
/// The token alone is not accepted by `unregister`; callers must retain the
/// `Registration` value returned by this registry.
pub fn Registration::token(self : Registration) -> Int {
self.token
}
///|
priv struct DescriptorInfo {
name : String
help : String
unit : String?
kind : @metric.MetricKind
const_labels : Array[@metric.Label]
variable_label_names : Array[String]
}
///|
fn canonical_labels(labels : Array[@metric.Label]) -> Array[@metric.Label] {
let result = labels.copy()
result.sort_by((left, right) => {
let name_order = left.name.lexical_compare(right.name)
if name_order != 0 {
name_order
} else {
left.value.lexical_compare(right.value)
}
})
result
}
///|
fn labels_equal(
left : Array[@metric.Label],
right : Array[@metric.Label],
) -> Bool {
if left.length() != right.length() {
return false
}
for index in 0.. Bool {
if left.length() != right.length() {
return false
}
for index in 0.. DescriptorInfo {
{
name: descriptor.name(),
help: descriptor.help(),
unit: descriptor.unit(),
kind: descriptor.kind(),
const_labels: canonical_labels(descriptor.const_labels()),
// Label values supplied to a future vector are positional, so this order
// is part of descriptor identity and must not be canonicalized.
variable_label_names: descriptor.variable_label_names(),
}
}
///|
fn DescriptorInfo::from_counter(counter : @metric.Counter) -> DescriptorInfo {
DescriptorInfo::from_descriptor(counter.descriptor())
}
///|
fn DescriptorInfo::from_gauge(gauge : @metric.Gauge) -> DescriptorInfo {
DescriptorInfo::from_descriptor(gauge.descriptor())
}
///|
fn DescriptorInfo::from_histogram(
histogram : @metric.Histogram,
) -> DescriptorInfo {
DescriptorInfo::from_descriptor(histogram.descriptor())
}
///|
fn descriptor_infos_equal(
left : DescriptorInfo,
right : DescriptorInfo,
) -> Bool {
left.name == right.name &&
left.help == right.help &&
left.unit == right.unit &&
left.kind == right.kind &&
labels_equal(left.const_labels, right.const_labels) &&
strings_equal(left.variable_label_names, right.variable_label_names)
}
///|
fn descriptor_mismatch_field(
left : DescriptorInfo,
right : DescriptorInfo,
) -> String {
if left.kind != right.kind {
"type"
} else if left.help != right.help {
"help"
} else if left.unit != right.unit {
"unit"
} else if !labels_equal(left.const_labels, right.const_labels) {
"const_labels"
} else if !strings_equal(
left.variable_label_names,
right.variable_label_names,
) {
"variable_label_names"
} else {
"name"
}
}
///|
fn DescriptorInfo::family_type(self : DescriptorInfo) -> FamilyType {
match self.kind {
CounterKind => CounterFamily
GaugeKind => GaugeFamily
HistogramKind => HistogramFamily
}
}
///|
fn DescriptorInfo::expected_label_names(self : DescriptorInfo) -> Array[String] {
let result = self.variable_label_names.copy()
for label in self.const_labels {
result.push(label.name)
}
result.sort_by((left, right) => left.lexical_compare(right))
result
}