Skip to content

Commit 0c534c9

Browse files
committed
Address comments
1 parent d4882eb commit 0c534c9

3 files changed

Lines changed: 174 additions & 99 deletions

File tree

src/encoding/text.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Open Metrics text format implementation.
22
//!
33
//! ```
4-
//! # use prometheus_client::encoding::text::{encode, encode_registry, encode_eof};
4+
//! # use prometheus_client::encoding::text::{encode, encode_registry, encode_eof, EncodeError};
55
//! # use prometheus_client::metrics::counter::Counter;
66
//! # use prometheus_client::registry::Registry;
77
//! #
@@ -45,9 +45,58 @@ use crate::metrics::MetricType;
4545
use crate::registry::{Prefix, Registry, Unit};
4646

4747
use std::borrow::Cow;
48+
use std::cell::Cell;
4849
use std::collections::HashMap;
4950
use std::fmt::Write;
5051

52+
thread_local! {
53+
static UNSUPPORTED_NATIVE_HISTOGRAM: Cell<bool> = Cell::new(false);
54+
}
55+
56+
/// Error returned by text encoding.
57+
#[derive(Clone, Copy, Debug)]
58+
pub enum EncodeError {
59+
/// Formatting failed while writing text output.
60+
Fmt(std::fmt::Error),
61+
/// The OpenMetrics text encoder does not support native-only histograms.
62+
UnsupportedNativeHistogram,
63+
}
64+
65+
impl std::fmt::Display for EncodeError {
66+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67+
match self {
68+
EncodeError::Fmt(_) => f.write_str("failed to encode metrics into OpenMetrics text"),
69+
EncodeError::UnsupportedNativeHistogram => {
70+
f.write_str("OpenMetrics text encoding does not support native-only histograms")
71+
}
72+
}
73+
}
74+
}
75+
76+
impl std::error::Error for EncodeError {
77+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
78+
match self {
79+
EncodeError::Fmt(err) => Some(err),
80+
EncodeError::UnsupportedNativeHistogram => None,
81+
}
82+
}
83+
}
84+
85+
impl From<std::fmt::Error> for EncodeError {
86+
fn from(err: std::fmt::Error) -> Self {
87+
if UNSUPPORTED_NATIVE_HISTOGRAM.with(|unsupported| unsupported.replace(false)) {
88+
EncodeError::UnsupportedNativeHistogram
89+
} else {
90+
EncodeError::Fmt(err)
91+
}
92+
}
93+
}
94+
95+
fn mark_unsupported_native_histogram() -> std::fmt::Error {
96+
UNSUPPORTED_NATIVE_HISTOGRAM.with(|unsupported| unsupported.set(true));
97+
std::fmt::Error
98+
}
99+
51100
/// Encode both the metrics registered with the provided [`Registry`] and the
52101
/// EOF marker into the provided [`Write`]r using the OpenMetrics text format.
53102
///
@@ -84,14 +133,14 @@ use std::fmt::Write;
84133
/// // Encode the complete OpenMetrics exposition into the buffer
85134
/// let mut buffer = String::new();
86135
/// encode(&mut buffer, &registry)?;
87-
/// # Ok::<(), std::fmt::Error>(())
136+
/// # Ok::<(), prometheus_client::encoding::text::EncodeError>(())
88137
/// ```
89-
pub fn encode<W>(writer: &mut W, registry: &Registry) -> Result<(), std::fmt::Error>
138+
pub fn encode<W>(writer: &mut W, registry: &Registry) -> Result<(), EncodeError>
90139
where
91140
W: Write,
92141
{
93142
encode_registry(writer, registry)?;
94-
encode_eof(writer)
143+
encode_eof(writer).map_err(EncodeError::Fmt)
95144
}
96145

97146
/// Encode the metrics registered with the provided [`Registry`] into the
@@ -138,13 +187,16 @@ where
138187
///
139188
/// // Encode the gauge registry into the buffer
140189
/// encode_registry(&mut buffer, &reg_gauge)?;
141-
/// # Ok::<(), std::fmt::Error>(())
190+
/// # Ok::<(), prometheus_client::encoding::text::EncodeError>(())
142191
/// ```
143-
pub fn encode_registry<W>(writer: &mut W, registry: &Registry) -> Result<(), std::fmt::Error>
192+
pub fn encode_registry<W>(writer: &mut W, registry: &Registry) -> Result<(), EncodeError>
144193
where
145194
W: Write,
146195
{
147-
registry.encode(&mut DescriptorEncoder::new(writer).into())
196+
UNSUPPORTED_NATIVE_HISTOGRAM.with(|unsupported| unsupported.set(false));
197+
registry
198+
.encode(&mut DescriptorEncoder::new(writer).into())
199+
.map_err(EncodeError::from)
148200
}
149201

150202
/// Encode the EOF marker into the provided [`Write`]r using the OpenMetrics
@@ -175,7 +227,7 @@ where
175227
///
176228
/// // Encode EOF marker to complete the message
177229
/// encode_eof(&mut buffer)?;
178-
/// # Ok::<(), std::fmt::Error>(())
230+
/// # Ok::<(), prometheus_client::encoding::text::EncodeError>(())
179231
/// ```
180232
pub fn encode_eof<W>(writer: &mut W) -> Result<(), std::fmt::Error>
181233
where
@@ -455,7 +507,7 @@ impl MetricEncoder<'_> {
455507
_native: NativeHistogram<'_>,
456508
) -> Result<(), std::fmt::Error> {
457509
if buckets.is_empty() {
458-
return Err(std::fmt::Error);
510+
return Err(mark_unsupported_native_histogram());
459511
}
460512

461513
self.encode_histogram(sum, count, buckets, exemplars)
@@ -990,7 +1042,10 @@ mod tests {
9901042
histogram.observe(1.0);
9911043

9921044
let mut encoded = String::new();
993-
assert!(encode(&mut encoded, &registry).is_err());
1045+
assert!(matches!(
1046+
encode(&mut encoded, &registry),
1047+
Err(EncodeError::UnsupportedNativeHistogram)
1048+
));
9941049
}
9951050

9961051
#[test]

src/metrics/exemplar.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,9 @@ impl<S> HistogramWithExemplars<S> {
275275
impl<S: EncodeLabelSet> EncodeMetric for HistogramWithExemplars<S> {
276276
fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> {
277277
let inner = self.inner();
278-
let (sum, count, buckets) = inner.histogram.get();
279-
encoder.encode_histogram(sum, count, &buckets, Some(&inner.exemplars))
278+
inner
279+
.histogram
280+
.encode_with_exemplars(&mut encoder, Some(&inner.exemplars))
280281
}
281282

282283
fn metric_type(&self) -> MetricType {

0 commit comments

Comments
 (0)