Skip to content

Commit 751a06b

Browse files
author
William Johnson
committed
When generating # Help and # Type metadata be sure to update the
name to include the `_total` suffix if the type is a counter. Signed-off-by: William Johnson <wjohnson@whamcloud.com>
1 parent adc7c4e commit 751a06b

5 files changed

Lines changed: 62 additions & 7 deletions

File tree

src/encoding.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,13 @@ impl DescriptorEncoder<'_> {
108108
help: &str,
109109
unit: Option<&'s Unit>,
110110
metric_type: MetricType,
111+
auto_suffix: bool,
111112
) -> Result<MetricEncoder<'s>, std::fmt::Error> {
112113
for_both_mut!(
113114
self,
114115
DescriptorEncoderInner,
115116
e,
116-
Ok(e.encode_descriptor(name, help, unit, metric_type)?.into())
117+
Ok(e.encode_descriptor(name, help, unit, metric_type, auto_suffix)?.into())
117118
)
118119
}
119120
}

src/encoding/protobuf.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ impl DescriptorEncoder<'_> {
9898
help: &str,
9999
unit: Option<&Unit>,
100100
metric_type: MetricType,
101+
auto_suffix: bool,
101102
) -> Result<MetricEncoder<'s>, std::fmt::Error> {
102103
let family = openmetrics_data_model::MetricFamily {
103104
name: {
@@ -135,6 +136,7 @@ impl DescriptorEncoder<'_> {
135136
.metrics,
136137
metric_type,
137138
labels,
139+
auto_suffix,
138140
})
139141
}
140142
}
@@ -150,6 +152,7 @@ pub(crate) struct MetricEncoder<'f> {
150152
family: &'f mut Vec<openmetrics_data_model::Metric>,
151153
/// Labels to be added to each metric.
152154
labels: Vec<openmetrics_data_model::Label>,
155+
auto_suffix: bool,
153156
}
154157

155158
impl MetricEncoder<'_> {
@@ -245,6 +248,7 @@ impl MetricEncoder<'_> {
245248
metric_type: self.metric_type,
246249
family: self.family,
247250
labels,
251+
auto_suffix: self.auto_suffix,
248252
})
249253
}
250254

src/encoding/text.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ impl DescriptorEncoder<'_> {
221221
help: &str,
222222
unit: Option<&'s Unit>,
223223
metric_type: MetricType,
224+
auto_suffix: bool,
224225
) -> Result<MetricEncoder<'s>, std::fmt::Error> {
225226
self.writer.write_str("# HELP ")?;
226227
if let Some(prefix) = self.prefix {
@@ -231,7 +232,10 @@ impl DescriptorEncoder<'_> {
231232
if let Some(unit) = unit {
232233
self.writer.write_str("_")?;
233234
self.writer.write_str(unit.as_str())?;
235+
} else if metric_type == MetricType::Counter && auto_suffix {
236+
self.writer.write_str("_total")?;
234237
}
238+
235239
self.writer.write_str(" ")?;
236240
self.writer.write_str(help)?;
237241
self.writer.write_str("\n")?;
@@ -245,7 +249,10 @@ impl DescriptorEncoder<'_> {
245249
if let Some(unit) = unit {
246250
self.writer.write_str("_")?;
247251
self.writer.write_str(unit.as_str())?;
252+
} else if metric_type == MetricType::Counter && auto_suffix {
253+
self.writer.write_str("_total")?;
248254
}
255+
249256
self.writer.write_str(" ")?;
250257
self.writer.write_str(metric_type.as_str())?;
251258
self.writer.write_str("\n")?;
@@ -271,6 +278,7 @@ impl DescriptorEncoder<'_> {
271278
unit,
272279
const_labels: self.labels,
273280
family_labels: None,
281+
auto_suffix,
274282
})
275283
}
276284
}
@@ -291,6 +299,7 @@ pub(crate) struct MetricEncoder<'a> {
291299
unit: Option<&'a Unit>,
292300
const_labels: &'a [(Cow<'static, str>, Cow<'static, str>)],
293301
family_labels: Option<&'a dyn super::EncodeLabelSet>,
302+
auto_suffix: bool,
294303
}
295304

296305
impl std::fmt::Debug for MetricEncoder<'_> {
@@ -307,6 +316,7 @@ impl std::fmt::Debug for MetricEncoder<'_> {
307316
.field("unit", &self.unit)
308317
.field("const_labels", &self.const_labels)
309318
.field("labels", &labels.as_str())
319+
.field("auto_suffix", &self.auto_suffix)
310320
.finish()
311321
}
312322
}
@@ -323,7 +333,9 @@ impl MetricEncoder<'_> {
323333
) -> Result<(), std::fmt::Error> {
324334
self.write_prefix_name_unit()?;
325335

326-
self.write_suffix("total")?;
336+
if self.auto_suffix {
337+
self.write_suffix("total")?;
338+
}
327339

328340
self.encode_labels::<NoLabelSet>(None)?;
329341

@@ -393,6 +405,7 @@ impl MetricEncoder<'_> {
393405
unit: self.unit,
394406
const_labels: self.const_labels,
395407
family_labels: Some(label_set),
408+
auto_suffix: self.auto_suffix,
396409
})
397410
}
398411

@@ -1082,6 +1095,7 @@ mod tests {
10821095
"some help",
10831096
None,
10841097
counter.metric_type(),
1098+
false,
10851099
)?;
10861100
counter.encode(metric_encoder)?;
10871101
Ok(())

src/metrics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub trait TypedMetric {
1414
}
1515

1616
/// OpenMetrics metric type.
17-
#[derive(Clone, Copy, Debug)]
17+
#[derive(Clone, Copy, Debug, PartialEq)]
1818
#[allow(missing_docs)]
1919
pub enum MetricType {
2020
Counter,

src/registry.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,39 @@ impl Registry {
126126
help: H,
127127
metric: impl Metric,
128128
) {
129-
self.priv_register(name, help, metric, None)
129+
self.priv_register(name, help, metric, None, true)
130+
}
131+
132+
/// Register a metric with the [`Registry`].
133+
///
134+
/// Note: In the Open Metrics text exposition format some metric types have
135+
/// a special suffix, e.g. the
136+
/// [`Counter`](crate::metrics::counter::Counter`) metric with `_total`.
137+
/// These suffixes are inferred through the metric type and must not be
138+
/// appended to the metric name manually by the user.
139+
///
140+
/// Note: A full stop punctuation mark (`.`) is automatically added to the
141+
/// passed help text.
142+
///
143+
/// Use [`Registry::register_with_unit`] whenever a unit for the given
144+
/// metric is known.
145+
///
146+
/// ```
147+
/// # use prometheus_client::metrics::counter::{Atomic as _, Counter};
148+
/// # use prometheus_client::registry::{Registry, Unit};
149+
/// #
150+
/// let mut registry = Registry::default();
151+
/// let counter: Counter = Counter::default();
152+
///
153+
/// registry.register_without_auto_suffix("my_counter", "This is my counter", counter.clone());
154+
/// ```
155+
pub fn register_without_auto_suffix<N: Into<String>, H: Into<String>>(
156+
&mut self,
157+
name: N,
158+
help: H,
159+
metric: impl Metric,
160+
) {
161+
self.priv_register(name, help, metric, None, false)
130162
}
131163

132164
/// Register a metric with the [`Registry`] specifying the metric's unit.
@@ -158,7 +190,7 @@ impl Registry {
158190
unit: Unit,
159191
metric: impl Metric,
160192
) {
161-
self.priv_register(name, help, metric, Some(unit))
193+
self.priv_register(name, help, metric, Some(unit), false)
162194
}
163195

164196
fn priv_register<N: Into<String>, H: Into<String>>(
@@ -167,8 +199,9 @@ impl Registry {
167199
help: H,
168200
metric: impl Metric,
169201
unit: Option<Unit>,
202+
auto_suffix: bool,
170203
) {
171-
let descriptor = Descriptor::new(name, help, unit);
204+
let descriptor = Descriptor::new(name, help, unit, auto_suffix);
172205
self.metrics.push((descriptor, Box::new(metric)));
173206
}
174207

@@ -295,6 +328,7 @@ impl Registry {
295328
&descriptor.help,
296329
descriptor.unit.as_ref(),
297330
EncodeMetric::metric_type(metric.as_ref()),
331+
descriptor.auto_suffix,
298332
)?;
299333
metric.encode(metric_encoder)?;
300334
}
@@ -335,15 +369,17 @@ struct Descriptor {
335369
name: String,
336370
help: String,
337371
unit: Option<Unit>,
372+
auto_suffix: bool,
338373
}
339374

340375
impl Descriptor {
341376
/// Create new [`Descriptor`].
342-
fn new<N: Into<String>, H: Into<String>>(name: N, help: H, unit: Option<Unit>) -> Self {
377+
fn new<N: Into<String>, H: Into<String>>(name: N, help: H, unit: Option<Unit>, auto_suffix: bool) -> Self {
343378
Self {
344379
name: name.into(),
345380
help: help.into() + ".",
346381
unit,
382+
auto_suffix,
347383
}
348384
}
349385
}

0 commit comments

Comments
 (0)