Line data Source code
1 : //! We re-export those from prometheus crate to
2 : //! make sure that we use the same dep version everywhere.
3 : //! Otherwise, we might not see all metrics registered via
4 : //! a default registry.
5 : #![deny(clippy::undocumented_unsafe_blocks)]
6 :
7 : use measured::{
8 : label::{LabelGroupSet, LabelGroupVisitor, LabelName, NoLabels},
9 : metric::{
10 : counter::CounterState,
11 : gauge::GaugeState,
12 : group::{Encoding, MetricValue},
13 : name::{MetricName, MetricNameEncoder},
14 : MetricEncoding, MetricFamilyEncoding,
15 : },
16 : FixedCardinalityLabel, LabelGroup, MetricGroup,
17 : };
18 : use once_cell::sync::Lazy;
19 : use prometheus::core::{
20 : Atomic, AtomicU64, Collector, GenericCounter, GenericCounterVec, GenericGauge, GenericGaugeVec,
21 : };
22 : pub use prometheus::opts;
23 : pub use prometheus::register;
24 : pub use prometheus::Error;
25 : use prometheus::Registry;
26 : pub use prometheus::{core, default_registry, proto};
27 : pub use prometheus::{exponential_buckets, linear_buckets};
28 : pub use prometheus::{register_counter_vec, Counter, CounterVec};
29 : pub use prometheus::{register_gauge, Gauge};
30 : pub use prometheus::{register_gauge_vec, GaugeVec};
31 : pub use prometheus::{register_histogram, Histogram};
32 : pub use prometheus::{register_histogram_vec, HistogramVec};
33 : pub use prometheus::{register_int_counter, IntCounter};
34 : pub use prometheus::{register_int_counter_vec, IntCounterVec};
35 : pub use prometheus::{register_int_gauge, IntGauge};
36 : pub use prometheus::{register_int_gauge_vec, IntGaugeVec};
37 : pub use prometheus::{Encoder, TextEncoder};
38 :
39 : pub mod launch_timestamp;
40 : mod wrappers;
41 : pub use wrappers::{CountedReader, CountedWriter};
42 : mod hll;
43 : pub use hll::{HyperLogLog, HyperLogLogState, HyperLogLogVec};
44 : #[cfg(target_os = "linux")]
45 : pub mod more_process_metrics;
46 :
47 : pub type UIntGauge = GenericGauge<AtomicU64>;
48 : pub type UIntGaugeVec = GenericGaugeVec<AtomicU64>;
49 :
50 : #[macro_export]
51 : macro_rules! register_uint_gauge_vec {
52 : ($NAME:expr, $HELP:expr, $LABELS_NAMES:expr $(,)?) => {{
53 : let gauge_vec = UIntGaugeVec::new($crate::opts!($NAME, $HELP), $LABELS_NAMES).unwrap();
54 946 : $crate::register(Box::new(gauge_vec.clone())).map(|_| gauge_vec)
55 : }};
56 : }
57 :
58 : #[macro_export]
59 : macro_rules! register_uint_gauge {
60 : ($NAME:expr, $HELP:expr $(,)?) => {{
61 : let gauge = $crate::UIntGauge::new($NAME, $HELP).unwrap();
62 494 : $crate::register(Box::new(gauge.clone())).map(|_| gauge)
63 : }};
64 : }
65 :
66 : /// Special internal registry, to collect metrics independently from the default registry.
67 : /// Was introduced to fix deadlock with lazy registration of metrics in the default registry.
68 : static INTERNAL_REGISTRY: Lazy<Registry> = Lazy::new(Registry::new);
69 :
70 : /// Register a collector in the internal registry. MUST be called before the first call to `gather()`.
71 : /// Otherwise, we can have a deadlock in the `gather()` call, trying to register a new collector
72 : /// while holding the lock.
73 0 : pub fn register_internal(c: Box<dyn Collector>) -> prometheus::Result<()> {
74 0 : INTERNAL_REGISTRY.register(c)
75 0 : }
76 :
77 : /// Gathers all Prometheus metrics and records the I/O stats just before that.
78 : ///
79 : /// Metrics gathering is a relatively simple and standalone operation, so
80 : /// it might be fine to do it this way to keep things simple.
81 0 : pub fn gather() -> Vec<prometheus::proto::MetricFamily> {
82 0 : update_rusage_metrics();
83 0 : let mut mfs = prometheus::gather();
84 0 : let mut internal_mfs = INTERNAL_REGISTRY.gather();
85 0 : mfs.append(&mut internal_mfs);
86 0 : mfs
87 0 : }
88 :
89 0 : static DISK_IO_BYTES: Lazy<IntGaugeVec> = Lazy::new(|| {
90 : register_int_gauge_vec!(
91 : "libmetrics_disk_io_bytes_total",
92 : "Bytes written and read from disk, grouped by the operation (read|write)",
93 : &["io_operation"]
94 : )
95 0 : .expect("Failed to register disk i/o bytes int gauge vec")
96 0 : });
97 :
98 0 : static MAXRSS_KB: Lazy<IntGauge> = Lazy::new(|| {
99 : register_int_gauge!(
100 : "libmetrics_maxrss_kb",
101 : "Memory usage (Maximum Resident Set Size)"
102 : )
103 0 : .expect("Failed to register maxrss_kb int gauge")
104 0 : });
105 :
106 : /// Most common fsync latency is 50 µs - 100 µs, but it can be much higher,
107 : /// especially during many concurrent disk operations.
108 : pub const DISK_FSYNC_SECONDS_BUCKETS: &[f64] =
109 : &[0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 30.0];
110 :
111 : pub struct BuildInfo {
112 : pub revision: &'static str,
113 : pub build_tag: &'static str,
114 : }
115 :
116 : // todo: allow label group without the set
117 : impl LabelGroup for BuildInfo {
118 0 : fn visit_values(&self, v: &mut impl LabelGroupVisitor) {
119 0 : const REVISION: &LabelName = LabelName::from_str("revision");
120 0 : v.write_value(REVISION, &self.revision);
121 0 : const BUILD_TAG: &LabelName = LabelName::from_str("build_tag");
122 0 : v.write_value(BUILD_TAG, &self.build_tag);
123 0 : }
124 : }
125 :
126 : impl<T: Encoding> MetricFamilyEncoding<T> for BuildInfo
127 : where
128 : GaugeState: MetricEncoding<T>,
129 : {
130 0 : fn collect_family_into(
131 0 : &self,
132 0 : name: impl measured::metric::name::MetricNameEncoder,
133 0 : enc: &mut T,
134 0 : ) -> Result<(), T::Err> {
135 0 : enc.write_help(&name, "Build/version information")?;
136 0 : GaugeState::write_type(&name, enc)?;
137 0 : GaugeState {
138 0 : count: std::sync::atomic::AtomicI64::new(1),
139 0 : }
140 0 : .collect_into(&(), self, name, enc)
141 0 : }
142 : }
143 :
144 0 : #[derive(MetricGroup)]
145 : #[metric(new(build_info: BuildInfo))]
146 : pub struct NeonMetrics {
147 : #[cfg(target_os = "linux")]
148 : #[metric(namespace = "process")]
149 : #[metric(init = measured_process::ProcessCollector::for_self())]
150 : process: measured_process::ProcessCollector,
151 :
152 : #[metric(namespace = "libmetrics")]
153 : #[metric(init = LibMetrics::new(build_info))]
154 : libmetrics: LibMetrics,
155 : }
156 :
157 0 : #[derive(MetricGroup)]
158 : #[metric(new(build_info: BuildInfo))]
159 : pub struct LibMetrics {
160 : #[metric(init = build_info)]
161 : build_info: BuildInfo,
162 :
163 : #[metric(flatten)]
164 : rusage: Rusage,
165 :
166 : serve_count: CollectionCounter,
167 : }
168 :
169 0 : fn write_gauge<Enc: Encoding>(
170 0 : x: i64,
171 0 : labels: impl LabelGroup,
172 0 : name: impl MetricNameEncoder,
173 0 : enc: &mut Enc,
174 0 : ) -> Result<(), Enc::Err> {
175 0 : enc.write_metric_value(name, labels, MetricValue::Int(x))
176 0 : }
177 :
178 : #[derive(Default)]
179 : struct Rusage;
180 :
181 0 : #[derive(FixedCardinalityLabel, Clone, Copy)]
182 : #[label(singleton = "io_operation")]
183 : enum IoOp {
184 : Read,
185 : Write,
186 : }
187 :
188 : impl<T: Encoding> MetricGroup<T> for Rusage
189 : where
190 : GaugeState: MetricEncoding<T>,
191 : {
192 0 : fn collect_group_into(&self, enc: &mut T) -> Result<(), T::Err> {
193 0 : const DISK_IO: &MetricName = MetricName::from_str("disk_io_bytes_total");
194 0 : const MAXRSS: &MetricName = MetricName::from_str("maxrss_kb");
195 0 :
196 0 : let ru = get_rusage_stats();
197 0 :
198 0 : enc.write_help(
199 0 : DISK_IO,
200 0 : "Bytes written and read from disk, grouped by the operation (read|write)",
201 0 : )?;
202 0 : GaugeState::write_type(DISK_IO, enc)?;
203 0 : write_gauge(ru.ru_inblock * BYTES_IN_BLOCK, IoOp::Read, DISK_IO, enc)?;
204 0 : write_gauge(ru.ru_oublock * BYTES_IN_BLOCK, IoOp::Write, DISK_IO, enc)?;
205 :
206 0 : enc.write_help(MAXRSS, "Memory usage (Maximum Resident Set Size)")?;
207 0 : GaugeState::write_type(MAXRSS, enc)?;
208 0 : write_gauge(ru.ru_maxrss, IoOp::Read, MAXRSS, enc)?;
209 :
210 0 : Ok(())
211 0 : }
212 : }
213 :
214 : #[derive(Default)]
215 : struct CollectionCounter(CounterState);
216 :
217 : impl<T: Encoding> MetricFamilyEncoding<T> for CollectionCounter
218 : where
219 : CounterState: MetricEncoding<T>,
220 : {
221 0 : fn collect_family_into(
222 0 : &self,
223 0 : name: impl measured::metric::name::MetricNameEncoder,
224 0 : enc: &mut T,
225 0 : ) -> Result<(), T::Err> {
226 0 : self.0.inc();
227 0 : enc.write_help(&name, "Number of metric requests made")?;
228 0 : self.0.collect_into(&(), NoLabels, name, enc)
229 0 : }
230 : }
231 :
232 0 : pub fn set_build_info_metric(revision: &str, build_tag: &str) {
233 0 : let metric = register_int_gauge_vec!(
234 : "libmetrics_build_info",
235 : "Build/version information",
236 : &["revision", "build_tag"]
237 : )
238 0 : .expect("Failed to register build info metric");
239 0 : metric.with_label_values(&[revision, build_tag]).set(1);
240 0 : }
241 : const BYTES_IN_BLOCK: i64 = 512;
242 :
243 : // Records I/O stats in a "cross-platform" way.
244 : // Compiles both on macOS and Linux, but current macOS implementation always returns 0 as values for I/O stats.
245 : // An alternative is to read procfs (`/proc/[pid]/io`) which does not work under macOS at all, hence abandoned.
246 : //
247 : // Uses https://www.freebsd.org/cgi/man.cgi?query=getrusage to retrieve the number of block operations
248 : // performed by the process.
249 : // We know the size of the block, so we can determine the I/O bytes out of it.
250 : // The value might be not 100% exact, but should be fine for Prometheus metrics in this case.
251 0 : fn update_rusage_metrics() {
252 0 : let rusage_stats = get_rusage_stats();
253 0 :
254 0 : DISK_IO_BYTES
255 0 : .with_label_values(&["read"])
256 0 : .set(rusage_stats.ru_inblock * BYTES_IN_BLOCK);
257 0 : DISK_IO_BYTES
258 0 : .with_label_values(&["write"])
259 0 : .set(rusage_stats.ru_oublock * BYTES_IN_BLOCK);
260 0 :
261 0 : // On macOS, the unit of maxrss is bytes; on Linux, it's kilobytes. https://stackoverflow.com/a/59915669
262 0 : #[cfg(target_os = "macos")]
263 0 : {
264 0 : MAXRSS_KB.set(rusage_stats.ru_maxrss / 1024);
265 0 : }
266 0 : #[cfg(not(target_os = "macos"))]
267 0 : {
268 0 : MAXRSS_KB.set(rusage_stats.ru_maxrss);
269 0 : }
270 0 : }
271 :
272 0 : fn get_rusage_stats() -> libc::rusage {
273 0 : let mut rusage = std::mem::MaybeUninit::uninit();
274 0 :
275 0 : // SAFETY: kernel will initialize the struct for us
276 0 : unsafe {
277 0 : let ret = libc::getrusage(libc::RUSAGE_SELF, rusage.as_mut_ptr());
278 0 : assert!(ret == 0, "getrusage failed: bad args");
279 0 : rusage.assume_init()
280 0 : }
281 0 : }
282 :
283 : /// Create an [`IntCounterPairVec`] and registers to default registry.
284 : #[macro_export(local_inner_macros)]
285 : macro_rules! register_int_counter_pair_vec {
286 : ($NAME1:expr, $HELP1:expr, $NAME2:expr, $HELP2:expr, $LABELS_NAMES:expr $(,)?) => {{
287 : match (
288 : $crate::register_int_counter_vec!($NAME1, $HELP1, $LABELS_NAMES),
289 : $crate::register_int_counter_vec!($NAME2, $HELP2, $LABELS_NAMES),
290 : ) {
291 : (Ok(inc), Ok(dec)) => Ok($crate::IntCounterPairVec::new(inc, dec)),
292 : (Err(e), _) | (_, Err(e)) => Err(e),
293 : }
294 : }};
295 : }
296 :
297 : /// Create an [`IntCounterPair`] and registers to default registry.
298 : #[macro_export(local_inner_macros)]
299 : macro_rules! register_int_counter_pair {
300 : ($NAME1:expr, $HELP1:expr, $NAME2:expr, $HELP2:expr $(,)?) => {{
301 : match (
302 : $crate::register_int_counter!($NAME1, $HELP1),
303 : $crate::register_int_counter!($NAME2, $HELP2),
304 : ) {
305 : (Ok(inc), Ok(dec)) => Ok($crate::IntCounterPair::new(inc, dec)),
306 : (Err(e), _) | (_, Err(e)) => Err(e),
307 : }
308 : }};
309 : }
310 :
311 : /// A Pair of [`GenericCounterVec`]s. Like an [`GenericGaugeVec`] but will always observe changes
312 : pub struct GenericCounterPairVec<P: Atomic> {
313 : inc: GenericCounterVec<P>,
314 : dec: GenericCounterVec<P>,
315 : }
316 :
317 : /// A Pair of [`GenericCounter`]s. Like an [`GenericGauge`] but will always observe changes
318 : pub struct GenericCounterPair<P: Atomic> {
319 : inc: GenericCounter<P>,
320 : dec: GenericCounter<P>,
321 : }
322 :
323 : impl<P: Atomic> GenericCounterPairVec<P> {
324 160 : pub fn new(inc: GenericCounterVec<P>, dec: GenericCounterVec<P>) -> Self {
325 160 : Self { inc, dec }
326 160 : }
327 :
328 : /// `get_metric_with_label_values` returns the [`GenericCounterPair<P>`] for the given slice
329 : /// of label values (same order as the VariableLabels in Desc). If that combination of
330 : /// label values is accessed for the first time, a new [`GenericCounterPair<P>`] is created.
331 : ///
332 : /// An error is returned if the number of label values is not the same as the
333 : /// number of VariableLabels in Desc.
334 861 : pub fn get_metric_with_label_values(
335 861 : &self,
336 861 : vals: &[&str],
337 861 : ) -> prometheus::Result<GenericCounterPair<P>> {
338 861 : Ok(GenericCounterPair {
339 861 : inc: self.inc.get_metric_with_label_values(vals)?,
340 861 : dec: self.dec.get_metric_with_label_values(vals)?,
341 : })
342 861 : }
343 :
344 : /// `with_label_values` works as `get_metric_with_label_values`, but panics if an error
345 : /// occurs.
346 180 : pub fn with_label_values(&self, vals: &[&str]) -> GenericCounterPair<P> {
347 180 : self.get_metric_with_label_values(vals).unwrap()
348 180 : }
349 :
350 24 : pub fn remove_label_values(&self, res: &mut [prometheus::Result<()>; 2], vals: &[&str]) {
351 24 : res[0] = self.inc.remove_label_values(vals);
352 24 : res[1] = self.dec.remove_label_values(vals);
353 24 : }
354 : }
355 :
356 : impl<P: Atomic> GenericCounterPair<P> {
357 0 : pub fn new(inc: GenericCounter<P>, dec: GenericCounter<P>) -> Self {
358 0 : Self { inc, dec }
359 0 : }
360 :
361 : /// Increment the gauge by 1, returning a guard that decrements by 1 on drop.
362 364 : pub fn guard(&self) -> GenericCounterPairGuard<P> {
363 364 : self.inc.inc();
364 364 : GenericCounterPairGuard(self.dec.clone())
365 364 : }
366 :
367 : /// Increment the gauge by n, returning a guard that decrements by n on drop.
368 0 : pub fn guard_by(&self, n: P::T) -> GenericCounterPairGuardBy<P> {
369 0 : self.inc.inc_by(n);
370 0 : GenericCounterPairGuardBy(self.dec.clone(), n)
371 0 : }
372 :
373 : /// Increase the gauge by 1.
374 : #[inline]
375 3354 : pub fn inc(&self) {
376 3354 : self.inc.inc();
377 3354 : }
378 :
379 : /// Decrease the gauge by 1.
380 : #[inline]
381 2750 : pub fn dec(&self) {
382 2750 : self.dec.inc();
383 2750 : }
384 :
385 : /// Add the given value to the gauge. (The value can be
386 : /// negative, resulting in a decrement of the gauge.)
387 : #[inline]
388 0 : pub fn inc_by(&self, v: P::T) {
389 0 : self.inc.inc_by(v);
390 0 : }
391 :
392 : /// Subtract the given value from the gauge. (The value can be
393 : /// negative, resulting in an increment of the gauge.)
394 : #[inline]
395 0 : pub fn dec_by(&self, v: P::T) {
396 0 : self.dec.inc_by(v);
397 0 : }
398 : }
399 :
400 : impl<P: Atomic> Clone for GenericCounterPair<P> {
401 6078 : fn clone(&self) -> Self {
402 6078 : Self {
403 6078 : inc: self.inc.clone(),
404 6078 : dec: self.dec.clone(),
405 6078 : }
406 6078 : }
407 : }
408 :
409 : /// Guard returned by [`GenericCounterPair::guard`]
410 : pub struct GenericCounterPairGuard<P: Atomic>(GenericCounter<P>);
411 :
412 : impl<P: Atomic> Drop for GenericCounterPairGuard<P> {
413 364 : fn drop(&mut self) {
414 364 : self.0.inc();
415 364 : }
416 : }
417 : /// Guard returned by [`GenericCounterPair::guard_by`]
418 : pub struct GenericCounterPairGuardBy<P: Atomic>(GenericCounter<P>, P::T);
419 :
420 : impl<P: Atomic> Drop for GenericCounterPairGuardBy<P> {
421 0 : fn drop(&mut self) {
422 0 : self.0.inc_by(self.1);
423 0 : }
424 : }
425 :
426 : /// A Pair of [`IntCounterVec`]s. Like an [`IntGaugeVec`] but will always observe changes
427 : pub type IntCounterPairVec = GenericCounterPairVec<AtomicU64>;
428 :
429 : /// A Pair of [`IntCounter`]s. Like an [`IntGauge`] but will always observe changes
430 : pub type IntCounterPair = GenericCounterPair<AtomicU64>;
431 :
432 : /// A guard for [`IntCounterPair`] that will decrement the gauge on drop
433 : pub type IntCounterPairGuard = GenericCounterPairGuard<AtomicU64>;
434 :
435 : pub trait CounterPairAssoc {
436 : const INC_NAME: &'static MetricName;
437 : const DEC_NAME: &'static MetricName;
438 :
439 : const INC_HELP: &'static str;
440 : const DEC_HELP: &'static str;
441 :
442 : type LabelGroupSet: LabelGroupSet;
443 : }
444 :
445 : pub struct CounterPairVec<A: CounterPairAssoc> {
446 : vec: measured::metric::MetricVec<MeasuredCounterPairState, A::LabelGroupSet>,
447 : }
448 :
449 : impl<A: CounterPairAssoc> Default for CounterPairVec<A>
450 : where
451 : A::LabelGroupSet: Default,
452 : {
453 216 : fn default() -> Self {
454 216 : Self {
455 216 : vec: Default::default(),
456 216 : }
457 216 : }
458 : }
459 :
460 : impl<A: CounterPairAssoc> CounterPairVec<A> {
461 0 : pub fn guard(
462 0 : &self,
463 0 : labels: <A::LabelGroupSet as LabelGroupSet>::Group<'_>,
464 0 : ) -> MeasuredCounterPairGuard<'_, A> {
465 0 : let id = self.vec.with_labels(labels);
466 0 : self.vec.get_metric(id).inc.inc();
467 0 : MeasuredCounterPairGuard { vec: &self.vec, id }
468 0 : }
469 0 : pub fn inc(&self, labels: <A::LabelGroupSet as LabelGroupSet>::Group<'_>) {
470 0 : let id = self.vec.with_labels(labels);
471 0 : self.vec.get_metric(id).inc.inc();
472 0 : }
473 0 : pub fn dec(&self, labels: <A::LabelGroupSet as LabelGroupSet>::Group<'_>) {
474 0 : let id = self.vec.with_labels(labels);
475 0 : self.vec.get_metric(id).dec.inc();
476 0 : }
477 0 : pub fn remove_metric(
478 0 : &self,
479 0 : labels: <A::LabelGroupSet as LabelGroupSet>::Group<'_>,
480 0 : ) -> Option<MeasuredCounterPairState> {
481 0 : let id = self.vec.with_labels(labels);
482 0 : self.vec.remove_metric(id)
483 0 : }
484 :
485 0 : pub fn sample(&self, labels: <A::LabelGroupSet as LabelGroupSet>::Group<'_>) -> u64 {
486 0 : let id = self.vec.with_labels(labels);
487 0 : let metric = self.vec.get_metric(id);
488 0 :
489 0 : let inc = metric.inc.count.load(std::sync::atomic::Ordering::Relaxed);
490 0 : let dec = metric.dec.count.load(std::sync::atomic::Ordering::Relaxed);
491 0 : inc.saturating_sub(dec)
492 0 : }
493 : }
494 :
495 : impl<T, A> ::measured::metric::group::MetricGroup<T> for CounterPairVec<A>
496 : where
497 : T: ::measured::metric::group::Encoding,
498 : A: CounterPairAssoc,
499 : ::measured::metric::counter::CounterState: ::measured::metric::MetricEncoding<T>,
500 : {
501 0 : fn collect_group_into(&self, enc: &mut T) -> Result<(), T::Err> {
502 0 : // write decrement first to avoid a race condition where inc - dec < 0
503 0 : T::write_help(enc, A::DEC_NAME, A::DEC_HELP)?;
504 0 : self.vec
505 0 : .collect_family_into(A::DEC_NAME, &mut Dec(&mut *enc))?;
506 :
507 0 : T::write_help(enc, A::INC_NAME, A::INC_HELP)?;
508 0 : self.vec
509 0 : .collect_family_into(A::INC_NAME, &mut Inc(&mut *enc))?;
510 :
511 0 : Ok(())
512 0 : }
513 : }
514 :
515 : #[derive(MetricGroup, Default)]
516 : pub struct MeasuredCounterPairState {
517 : pub inc: CounterState,
518 : pub dec: CounterState,
519 : }
520 :
521 : impl measured::metric::MetricType for MeasuredCounterPairState {
522 : type Metadata = ();
523 : }
524 :
525 : pub struct MeasuredCounterPairGuard<'a, A: CounterPairAssoc> {
526 : vec: &'a measured::metric::MetricVec<MeasuredCounterPairState, A::LabelGroupSet>,
527 : id: measured::metric::LabelId<A::LabelGroupSet>,
528 : }
529 :
530 : impl<A: CounterPairAssoc> Drop for MeasuredCounterPairGuard<'_, A> {
531 0 : fn drop(&mut self) {
532 0 : self.vec.get_metric(self.id).dec.inc();
533 0 : }
534 : }
535 :
536 : /// [`MetricEncoding`] for [`MeasuredCounterPairState`] that only writes the inc counter to the inner encoder.
537 : struct Inc<T>(T);
538 : /// [`MetricEncoding`] for [`MeasuredCounterPairState`] that only writes the dec counter to the inner encoder.
539 : struct Dec<T>(T);
540 :
541 : impl<T: Encoding> Encoding for Inc<T> {
542 : type Err = T::Err;
543 :
544 0 : fn write_help(&mut self, name: impl MetricNameEncoder, help: &str) -> Result<(), Self::Err> {
545 0 : self.0.write_help(name, help)
546 0 : }
547 :
548 0 : fn write_metric_value(
549 0 : &mut self,
550 0 : name: impl MetricNameEncoder,
551 0 : labels: impl LabelGroup,
552 0 : value: MetricValue,
553 0 : ) -> Result<(), Self::Err> {
554 0 : self.0.write_metric_value(name, labels, value)
555 0 : }
556 : }
557 :
558 : impl<T: Encoding> MetricEncoding<Inc<T>> for MeasuredCounterPairState
559 : where
560 : CounterState: MetricEncoding<T>,
561 : {
562 0 : fn write_type(name: impl MetricNameEncoder, enc: &mut Inc<T>) -> Result<(), T::Err> {
563 0 : CounterState::write_type(name, &mut enc.0)
564 0 : }
565 0 : fn collect_into(
566 0 : &self,
567 0 : metadata: &(),
568 0 : labels: impl LabelGroup,
569 0 : name: impl MetricNameEncoder,
570 0 : enc: &mut Inc<T>,
571 0 : ) -> Result<(), T::Err> {
572 0 : self.inc.collect_into(metadata, labels, name, &mut enc.0)
573 0 : }
574 : }
575 :
576 : impl<T: Encoding> Encoding for Dec<T> {
577 : type Err = T::Err;
578 :
579 0 : fn write_help(&mut self, name: impl MetricNameEncoder, help: &str) -> Result<(), Self::Err> {
580 0 : self.0.write_help(name, help)
581 0 : }
582 :
583 0 : fn write_metric_value(
584 0 : &mut self,
585 0 : name: impl MetricNameEncoder,
586 0 : labels: impl LabelGroup,
587 0 : value: MetricValue,
588 0 : ) -> Result<(), Self::Err> {
589 0 : self.0.write_metric_value(name, labels, value)
590 0 : }
591 : }
592 :
593 : /// Write the dec counter to the encoder
594 : impl<T: Encoding> MetricEncoding<Dec<T>> for MeasuredCounterPairState
595 : where
596 : CounterState: MetricEncoding<T>,
597 : {
598 0 : fn write_type(name: impl MetricNameEncoder, enc: &mut Dec<T>) -> Result<(), T::Err> {
599 0 : CounterState::write_type(name, &mut enc.0)
600 0 : }
601 0 : fn collect_into(
602 0 : &self,
603 0 : metadata: &(),
604 0 : labels: impl LabelGroup,
605 0 : name: impl MetricNameEncoder,
606 0 : enc: &mut Dec<T>,
607 0 : ) -> Result<(), T::Err> {
608 0 : self.dec.collect_into(metadata, labels, name, &mut enc.0)
609 0 : }
610 : }
|