diff --git a/packages/http-tracker-core/src/statistics/metrics.rs b/packages/http-tracker-core/src/statistics/metrics.rs index 05acea937..00d09b803 100644 --- a/packages/http-tracker-core/src/statistics/metrics.rs +++ b/packages/http-tracker-core/src/statistics/metrics.rs @@ -1,7 +1,7 @@ use serde::Serialize; use torrust_tracker_metrics::label::LabelSet; use torrust_tracker_metrics::metric::MetricName; -use torrust_tracker_metrics::metric_collection::aggregate::Sum; +use torrust_tracker_metrics::metric_collection::aggregate::sum::Sum; use torrust_tracker_metrics::metric_collection::{Error, MetricCollection}; use torrust_tracker_metrics::metric_name; use torrust_tracker_primitives::DurationSinceUnixEpoch; @@ -53,8 +53,7 @@ impl Metrics { &metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of TCP (HTTP tracker) `scrape` requests from IPv4 peers. @@ -67,8 +66,7 @@ impl Metrics { &metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of TCP (HTTP tracker) `announce` requests from IPv6 peers. @@ -81,8 +79,7 @@ impl Metrics { &metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers. @@ -95,7 +92,6 @@ impl Metrics { &metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } } diff --git a/packages/metrics/README.md b/packages/metrics/README.md index 885d6fa45..9f3883fba 100644 --- a/packages/metrics/README.md +++ b/packages/metrics/README.md @@ -1,37 +1,202 @@ # Torrust Tracker Metrics -A library with the metrics types used by the [Torrust Tracker](https://github.com/torrust/torrust-tracker) packages. +A comprehensive metrics library providing type-safe metric collection, aggregation, and Prometheus export functionality for the [Torrust Tracker](https://github.com/torrust/torrust-tracker) ecosystem. + +## Overview + +This library offers a robust metrics system designed specifically for tracking and monitoring BitTorrent tracker performance. It provides type-safe metric collection with support for labels, time-series data, and multiple export formats including Prometheus. + +## Key Features + +- **Type-Safe Metrics**: Strongly typed `Counter` and `Gauge` metrics with compile-time guarantees +- **Label Support**: Rich labeling system for multi-dimensional metrics +- **Time-Series Data**: Built-in support for timestamped samples +- **Prometheus Export**: Native Prometheus format serialization +- **Aggregation Functions**: Sum operations with mathematically appropriate return types +- **JSON Serialization**: Full serde support for all metric types +- **Memory Efficient**: Optimized data structures for high-performance scenarios + +## Quick Start + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +torrust-tracker-metrics = "3.0.0" +``` + +### Basic Usage + +```rust +use torrust_tracker_metrics::{ + metric_collection::MetricCollection, + label::{LabelSet, LabelValue}, + metric_name, label_name, +}; +use torrust_tracker_primitives::DurationSinceUnixEpoch; + +// Create a metric collection +let mut metrics = MetricCollection::default(); + +// Define labels +let labels: LabelSet = [ + (label_name!("server"), LabelValue::new("tracker-01")), + (label_name!("protocol"), LabelValue::new("http")), +].into(); + +// Record metrics +let time = DurationSinceUnixEpoch::from_secs(1234567890); +metrics.increment_counter( + &metric_name!("requests_total"), + &labels, + time, +)?; + +metrics.set_gauge( + &metric_name!("active_connections"), + &labels, + 42.0, + time, +)?; + +// Export to Prometheus format +let prometheus_output = metrics.to_prometheus(); +println!("{}", prometheus_output); +``` + +### Metric Aggregation + +```rust +use torrust_tracker_metrics::metric_collection::aggregate::Sum; + +// Sum all counter values matching specific labels +let total_requests = metrics.sum( + &metric_name!("requests_total"), + &[("server", "tracker-01")].into(), +); + +println!("Total requests: {:?}", total_requests); +``` + +## Architecture + +### Core Components + +- **`Counter`**: Monotonically increasing integer values (u64) +- **`Gauge`**: Arbitrary floating-point values that can increase or decrease (f64) +- **`Metric`**: Generic metric container with metadata (name, description, unit) +- **`MetricCollection`**: Type-safe collection managing both counters and gauges +- **`LabelSet`**: Key-value pairs for metric dimensionality +- **`Sample`**: Timestamped metric values with associated labels + +### Type System + +The library uses Rust's type system to ensure metric safety: + +```rust +// Counter operations return u64 +let counter_sum: Option = counter_collection.sum(&name, &labels); + +// Gauge operations return f64 +let gauge_sum: Option = gauge_collection.sum(&name, &labels); + +// Mixed collections convert to f64 for compatibility +let mixed_sum: Option = metric_collection.sum(&name, &labels); +``` + +### Module Structure + +```output +src/ +├── counter.rs # Counter metric type +├── gauge.rs # Gauge metric type +├── metric/ # Generic metric container +│ ├── mod.rs +│ ├── name.rs # Metric naming +│ ├── description.rs # Metric descriptions +│ └── aggregate/ # Metric-level aggregations +├── metric_collection/ # Collection management +│ ├── mod.rs +│ └── aggregate/ # Collection-level aggregations +├── label/ # Label system +│ ├── name.rs # Label names +│ ├── value.rs # Label values +│ └── set.rs # Label collections +├── sample.rs # Timestamped values +├── sample_collection.rs # Sample management +├── prometheus.rs # Prometheus export +└── unit.rs # Measurement units +``` ## Documentation -[Crate documentation](https://docs.rs/torrust-tracker-metrics). +- [Crate documentation](https://docs.rs/torrust-tracker-metrics) +- [API Reference](https://docs.rs/torrust-tracker-metrics/latest/torrust_tracker_metrics/) + +## Development -## Testing +### Code Coverage -Run coverage report: +Run basic coverage report: ```console cargo llvm-cov --package torrust-tracker-metrics ``` -Generate LCOV report with `llvm-cov` (for Visual Studio Code extension): +Generate LCOV report (for IDE integration): ```console mkdir -p ./.coverage -cargo llvm-cov --package torrust-tracker-metrics --lcov --output-path=./.coverage/lcov.info +cargo llvm-cov --package torrust-tracker-metrics --lcov --output-path=./.coverage/lcov.info ``` -Generate HTML report with `llvm-cov`: +Generate detailed HTML coverage report: + +Generate detailed HTML coverage report: ```console mkdir -p ./.coverage -cargo llvm-cov --package torrust-tracker-metrics --html --output-dir ./.coverage +cargo llvm-cov --package torrust-tracker-metrics --html --output-dir ./.coverage ``` +Open the coverage report in your browser: + +```console +open ./.coverage/index.html # macOS +xdg-open ./.coverage/index.html # Linux +``` + +## Performance Considerations + +- **Memory Usage**: Metrics are stored in-memory with efficient HashMap-based collections +- **Label Cardinality**: Be mindful of label combinations as they create separate time series +- **Aggregation**: Sum operations are optimized for both single-type and mixed collections + +## Compatibility + +This library is designed to be compatible with the standard Rust [metrics](https://crates.io/crates/metrics) crate ecosystem where possible. + +## Contributing + +We welcome contributions! Please see the main [Torrust Tracker repository](https://github.com/torrust/torrust-tracker) for contribution guidelines. + +### Reporting Issues + +- [Bug Reports](https://github.com/torrust/torrust-tracker/issues/new?template=bug_report.md) +- [Feature Requests](https://github.com/torrust/torrust-tracker/issues/new?template=feature_request.md) + ## Acknowledgements -We copied some parts like units or function names and signatures from the crate [metrics](https://crates.io/crates/metrics) because we wanted to make it compatible as much as possible with it. In the future, we may consider using the `metrics` crate directly instead of maintaining our own version. +This library draws inspiration from the Rust [metrics](https://crates.io/crates/metrics) crate, incorporating compatible APIs and naming conventions where possible. We may consider migrating to the standard metrics crate in future versions while maintaining our specialized functionality. + +Special thanks to the Rust metrics ecosystem contributors for establishing excellent patterns for metrics collection and export. ## License -The project is licensed under the terms of the [GNU AFFERO GENERAL PUBLIC LICENSE](./LICENSE). +This project is licensed under the [GNU AFFERO GENERAL PUBLIC LICENSE v3.0](./LICENSE). + +## Related Projects + +- [Torrust Tracker](https://github.com/torrust/torrust-tracker) - The main BitTorrent tracker +- [metrics](https://crates.io/crates/metrics) - Standard Rust metrics facade +- [prometheus](https://crates.io/crates/prometheus) - Prometheus client library diff --git a/packages/metrics/cSpell.json b/packages/metrics/cSpell.json index 1a2c13d2e..f04cce9e3 100644 --- a/packages/metrics/cSpell.json +++ b/packages/metrics/cSpell.json @@ -6,7 +6,9 @@ "Kibibytes", "Mebibytes", "ñaca", + "println", "rstest", + "serde", "subsec", "Tebibytes", "thiserror" diff --git a/packages/metrics/src/aggregate.rs b/packages/metrics/src/aggregate.rs deleted file mode 100644 index 39b760fca..000000000 --- a/packages/metrics/src/aggregate.rs +++ /dev/null @@ -1,143 +0,0 @@ -use derive_more::Display; - -#[derive(Debug, Display, Clone, Copy, PartialEq, Default)] -pub struct AggregateValue(f64); - -impl AggregateValue { - #[must_use] - pub fn new(value: f64) -> Self { - Self(value) - } - - #[must_use] - pub fn value(&self) -> f64 { - self.0 - } -} - -impl From for AggregateValue { - fn from(value: f64) -> Self { - Self(value) - } -} - -impl From for f64 { - fn from(value: AggregateValue) -> Self { - value.0 - } -} - -#[cfg(test)] -mod tests { - use approx::assert_relative_eq; - - use super::*; - - #[test] - fn it_should_be_created_with_new() { - let value = AggregateValue::new(42.5); - assert_relative_eq!(value.value(), 42.5); - } - - #[test] - fn it_should_return_the_inner_value() { - let value = AggregateValue::new(123.456); - assert_relative_eq!(value.value(), 123.456); - } - - #[test] - fn it_should_handle_zero_value() { - let value = AggregateValue::new(0.0); - assert_relative_eq!(value.value(), 0.0); - } - - #[test] - fn it_should_handle_negative_values() { - let value = AggregateValue::new(-42.5); - assert_relative_eq!(value.value(), -42.5); - } - - #[test] - fn it_should_handle_infinity() { - let value = AggregateValue::new(f64::INFINITY); - assert_relative_eq!(value.value(), f64::INFINITY); - } - - #[test] - fn it_should_handle_nan() { - let value = AggregateValue::new(f64::NAN); - assert!(value.value().is_nan()); - } - - #[test] - fn it_should_be_created_from_f64() { - let value: AggregateValue = 42.5.into(); - assert_relative_eq!(value.value(), 42.5); - } - - #[test] - fn it_should_convert_to_f64() { - let value = AggregateValue::new(42.5); - let f64_value: f64 = value.into(); - assert_relative_eq!(f64_value, 42.5); - } - - #[test] - fn it_should_be_displayable() { - let value = AggregateValue::new(42.5); - assert_eq!(value.to_string(), "42.5"); - } - - #[test] - fn it_should_be_debuggable() { - let value = AggregateValue::new(42.5); - let debug_string = format!("{value:?}"); - assert_eq!(debug_string, "AggregateValue(42.5)"); - } - - #[test] - fn it_should_be_cloneable() { - let value = AggregateValue::new(42.5); - let cloned_value = value; - assert_eq!(value, cloned_value); - } - - #[test] - fn it_should_be_copyable() { - let value = AggregateValue::new(42.5); - let copied_value = value; - assert_eq!(value, copied_value); - } - - #[test] - fn it_should_support_equality_comparison() { - let value1 = AggregateValue::new(42.5); - let value2 = AggregateValue::new(42.5); - let value3 = AggregateValue::new(43.0); - - assert_eq!(value1, value2); - assert_ne!(value1, value3); - } - - #[test] - fn it_should_handle_special_float_values_in_equality() { - let nan1 = AggregateValue::new(f64::NAN); - let nan2 = AggregateValue::new(f64::NAN); - let infinity = AggregateValue::new(f64::INFINITY); - let neg_infinity = AggregateValue::new(f64::NEG_INFINITY); - - // NaN is not equal to itself in IEEE 754 - assert_ne!(nan1, nan2); - assert_eq!(infinity, AggregateValue::new(f64::INFINITY)); - assert_eq!(neg_infinity, AggregateValue::new(f64::NEG_INFINITY)); - assert_ne!(infinity, neg_infinity); - } - - #[test] - fn it_should_handle_conversion_roundtrip() { - let original_value = 42.5; - let aggregate_value = AggregateValue::from(original_value); - let converted_back: f64 = aggregate_value.into(); - assert_relative_eq!(original_value, converted_back); - } -} diff --git a/packages/metrics/src/lib.rs b/packages/metrics/src/lib.rs index c53e9dd02..997cd3c8c 100644 --- a/packages/metrics/src/lib.rs +++ b/packages/metrics/src/lib.rs @@ -1,4 +1,3 @@ -pub mod aggregate; pub mod counter; pub mod gauge; pub mod label; diff --git a/packages/metrics/src/metric/aggregate/sum.rs b/packages/metrics/src/metric/aggregate/sum.rs index f08ea7d55..30c2819b7 100644 --- a/packages/metrics/src/metric/aggregate/sum.rs +++ b/packages/metrics/src/metric/aggregate/sum.rs @@ -1,37 +1,34 @@ -use crate::aggregate::AggregateValue; use crate::counter::Counter; use crate::gauge::Gauge; use crate::label::LabelSet; use crate::metric::Metric; pub trait Sum { - fn sum(&self, label_set_criteria: &LabelSet) -> AggregateValue; + type Output; + fn sum(&self, label_set_criteria: &LabelSet) -> Self::Output; } impl Sum for Metric { - #[allow(clippy::cast_precision_loss)] - fn sum(&self, label_set_criteria: &LabelSet) -> AggregateValue { - let sum: f64 = self - .sample_collection + type Output = u64; + + fn sum(&self, label_set_criteria: &LabelSet) -> Self::Output { + self.sample_collection .iter() .filter(|(label_set, _measurement)| label_set.matches(label_set_criteria)) - .map(|(_label_set, measurement)| measurement.value().primitive() as f64) - .sum(); - - sum.into() + .map(|(_label_set, measurement)| measurement.value().primitive()) + .sum() } } impl Sum for Metric { - fn sum(&self, label_set_criteria: &LabelSet) -> AggregateValue { - let sum: f64 = self - .sample_collection + type Output = f64; + + fn sum(&self, label_set_criteria: &LabelSet) -> Self::Output { + self.sample_collection .iter() .filter(|(label_set, _measurement)| label_set.matches(label_set_criteria)) .map(|(_label_set, measurement)| measurement.value().primitive()) - .sum(); - - sum.into() + .sum() } } @@ -40,7 +37,6 @@ mod tests { use torrust_tracker_primitives::DurationSinceUnixEpoch; - use crate::aggregate::AggregateValue; use crate::counter::Counter; use crate::gauge::Gauge; use crate::label::LabelSet; @@ -83,14 +79,14 @@ mod tests { } } - fn counter_cases() -> Vec<(Metric, LabelSet, AggregateValue)> { + fn counter_cases() -> Vec<(Metric, LabelSet, u64)> { // (metric, label set criteria, expected_aggregate_value) vec![ // Metric with one sample without label set ( MetricBuilder::default().with_sample(1.into(), &LabelSet::empty()).build(), LabelSet::empty(), - 1.0.into(), + 1, ), // Metric with one sample with a label set ( @@ -98,7 +94,7 @@ mod tests { .with_sample(1.into(), &[("l1", "l1_value")].into()) .build(), [("l1", "l1_value")].into(), - 1.0.into(), + 1, ), // Metric with two samples, different label sets, sum all ( @@ -107,7 +103,7 @@ mod tests { .with_sample(2.into(), &[("l2", "l2_value")].into()) .build(), LabelSet::empty(), - 3.0.into(), + 3, ), // Metric with two samples, different label sets, sum one ( @@ -116,7 +112,7 @@ mod tests { .with_sample(2.into(), &[("l2", "l2_value")].into()) .build(), [("l1", "l1_value")].into(), - 1.0.into(), + 1, ), // Metric with two samples, same label key, different label values, sum by key ( @@ -125,7 +121,7 @@ mod tests { .with_sample(2.into(), &[("l1", "l1_value"), ("lb", "lb_value")].into()) .build(), [("l1", "l1_value")].into(), - 3.0.into(), + 3, ), // Metric with two samples, different label values, sum by subkey ( @@ -134,17 +130,17 @@ mod tests { .with_sample(2.into(), &[("l1", "l1_value"), ("lb", "lb_value")].into()) .build(), [("la", "la_value")].into(), - 1.0.into(), + 1, ), // Edge: Metric with no samples at all - (MetricBuilder::default().build(), LabelSet::empty(), 0.0.into()), + (MetricBuilder::default().build(), LabelSet::empty(), 0), // Edge: Metric with samples but no matching labels ( MetricBuilder::default() .with_sample(5.into(), &[("foo", "bar")].into()) .build(), [("not", "present")].into(), - 0.0.into(), + 0, ), // Edge: Metric with zero value ( @@ -152,7 +148,7 @@ mod tests { .with_sample(0.into(), &[("l3", "l3_value")].into()) .build(), [("l3", "l3_value")].into(), - 0.0.into(), + 0, ), // Edge: Metric with a very large value ( @@ -160,20 +156,19 @@ mod tests { .with_sample(u64::MAX.into(), &LabelSet::empty()) .build(), LabelSet::empty(), - #[allow(clippy::cast_precision_loss)] - (u64::MAX as f64).into(), + u64::MAX, ), ] } - fn gauge_cases() -> Vec<(Metric, LabelSet, AggregateValue)> { + fn gauge_cases() -> Vec<(Metric, LabelSet, f64)> { // (metric, label set criteria, expected_aggregate_value) vec![ // Metric with one sample without label set ( MetricBuilder::default().with_sample(1.0.into(), &LabelSet::empty()).build(), LabelSet::empty(), - 1.0.into(), + 1.0, ), // Metric with one sample with a label set ( @@ -181,7 +176,7 @@ mod tests { .with_sample(1.0.into(), &[("l1", "l1_value")].into()) .build(), [("l1", "l1_value")].into(), - 1.0.into(), + 1.0, ), // Metric with two samples, different label sets, sum all ( @@ -190,7 +185,7 @@ mod tests { .with_sample(2.0.into(), &[("l2", "l2_value")].into()) .build(), LabelSet::empty(), - 3.0.into(), + 3.0, ), // Metric with two samples, different label sets, sum one ( @@ -199,7 +194,7 @@ mod tests { .with_sample(2.0.into(), &[("l2", "l2_value")].into()) .build(), [("l1", "l1_value")].into(), - 1.0.into(), + 1.0, ), // Metric with two samples, same label key, different label values, sum by key ( @@ -208,7 +203,7 @@ mod tests { .with_sample(2.0.into(), &[("l1", "l1_value"), ("lb", "lb_value")].into()) .build(), [("l1", "l1_value")].into(), - 3.0.into(), + 3.0, ), // Metric with two samples, different label values, sum by subkey ( @@ -217,17 +212,17 @@ mod tests { .with_sample(2.0.into(), &[("l1", "l1_value"), ("lb", "lb_value")].into()) .build(), [("la", "la_value")].into(), - 1.0.into(), + 1.0, ), // Edge: Metric with no samples at all - (MetricBuilder::default().build(), LabelSet::empty(), 0.0.into()), + (MetricBuilder::default().build(), LabelSet::empty(), 0.0), // Edge: Metric with samples but no matching labels ( MetricBuilder::default() .with_sample(5.0.into(), &[("foo", "bar")].into()) .build(), [("not", "present")].into(), - 0.0.into(), + 0.0, ), // Edge: Metric with zero value ( @@ -235,7 +230,7 @@ mod tests { .with_sample(0.0.into(), &[("l3", "l3_value")].into()) .build(), [("l3", "l3_value")].into(), - 0.0.into(), + 0.0, ), // Edge: Metric with negative values ( @@ -244,7 +239,7 @@ mod tests { .with_sample(3.0.into(), &[("l5", "l5_value")].into()) .build(), LabelSet::empty(), - 1.0.into(), + 1.0, ), // Edge: Metric with a very large value ( @@ -252,7 +247,7 @@ mod tests { .with_sample(f64::MAX.into(), &LabelSet::empty()) .build(), LabelSet::empty(), - f64::MAX.into(), + f64::MAX, ), ] } @@ -274,8 +269,8 @@ mod tests { for (idx, (metric, criteria, expected_value)) in gauge_cases().iter().enumerate() { let sum = metric.sum(criteria); - assert_eq!( - sum, *expected_value, + assert!( + (sum - expected_value).abs() <= f64::EPSILON, "at case {idx}, expected sum to be {expected_value}, got {sum}" ); } diff --git a/packages/metrics/src/metric_collection/aggregate/mod.rs b/packages/metrics/src/metric_collection/aggregate/mod.rs new file mode 100644 index 000000000..dce785d95 --- /dev/null +++ b/packages/metrics/src/metric_collection/aggregate/mod.rs @@ -0,0 +1 @@ +pub mod sum; diff --git a/packages/metrics/src/metric_collection/aggregate.rs b/packages/metrics/src/metric_collection/aggregate/sum.rs similarity index 85% rename from packages/metrics/src/metric_collection/aggregate.rs rename to packages/metrics/src/metric_collection/aggregate/sum.rs index 7fd744d92..3285fa8f1 100644 --- a/packages/metrics/src/metric_collection/aggregate.rs +++ b/packages/metrics/src/metric_collection/aggregate/sum.rs @@ -1,4 +1,3 @@ -use crate::aggregate::AggregateValue; use crate::counter::Counter; use crate::gauge::Gauge; use crate::label::LabelSet; @@ -7,27 +6,34 @@ use crate::metric::MetricName; use crate::metric_collection::{MetricCollection, MetricKindCollection}; pub trait Sum { - fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option; + fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option; } impl Sum for MetricCollection { - fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { + fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { if let Some(value) = self.counters.sum(metric_name, label_set_criteria) { return Some(value); } - self.gauges.sum(metric_name, label_set_criteria) + if let Some(value) = self.gauges.sum(metric_name, label_set_criteria) { + return Some(value); + } + + None } } impl Sum for MetricKindCollection { - fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { - self.metrics.get(metric_name).map(|metric| metric.sum(label_set_criteria)) + fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { + #[allow(clippy::cast_precision_loss)] + self.metrics + .get(metric_name) + .map(|metric| metric.sum(label_set_criteria) as f64) } } impl Sum for MetricKindCollection { - fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { + fn sum(&self, metric_name: &MetricName, label_set_criteria: &LabelSet) -> Option { self.metrics.get(metric_name).map(|metric| metric.sum(label_set_criteria)) } } @@ -41,7 +47,7 @@ mod tests { use crate::label::LabelValue; use crate::label_name; - use crate::metric_collection::aggregate::Sum; + use crate::metric_collection::aggregate::sum::Sum; #[test] fn type_counter_with_two_samples() { @@ -69,10 +75,10 @@ mod tests { ) .unwrap(); - assert_eq!(collection.sum(&metric_name, &LabelSet::empty()), Some(2.0.into())); + assert_eq!(collection.sum(&metric_name, &LabelSet::empty()), Some(2.0)); assert_eq!( collection.sum(&metric_name, &(label_name!("label_1"), LabelValue::new("value_1")).into()), - Some(1.0.into()) + Some(1.0) ); } @@ -102,10 +108,10 @@ mod tests { ) .unwrap(); - assert_eq!(collection.sum(&metric_name, &LabelSet::empty()), Some(2.0.into())); + assert_eq!(collection.sum(&metric_name, &LabelSet::empty()), Some(2.0)); assert_eq!( collection.sum(&metric_name, &(label_name!("label_1"), LabelValue::new("value_1")).into()), - Some(1.0.into()) + Some(1.0) ); } } diff --git a/packages/udp-tracker-core/src/statistics/metrics.rs b/packages/udp-tracker-core/src/statistics/metrics.rs index 57838c66f..98906a596 100644 --- a/packages/udp-tracker-core/src/statistics/metrics.rs +++ b/packages/udp-tracker-core/src/statistics/metrics.rs @@ -1,7 +1,7 @@ use serde::Serialize; use torrust_tracker_metrics::label::LabelSet; use torrust_tracker_metrics::metric::MetricName; -use torrust_tracker_metrics::metric_collection::aggregate::Sum; +use torrust_tracker_metrics::metric_collection::aggregate::sum::Sum; use torrust_tracker_metrics::metric_collection::{Error, MetricCollection}; use torrust_tracker_metrics::metric_name; use torrust_tracker_primitives::DurationSinceUnixEpoch; @@ -54,8 +54,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "connect")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers. @@ -68,8 +67,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers. @@ -82,8 +80,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers. @@ -96,8 +93,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "connect")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers. @@ -110,8 +106,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers. @@ -124,7 +119,6 @@ impl Metrics { &metric_name!(UDP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } } diff --git a/packages/udp-tracker-server/src/statistics/metrics.rs b/packages/udp-tracker-server/src/statistics/metrics.rs index 8eba248d2..c50966bc6 100644 --- a/packages/udp-tracker-server/src/statistics/metrics.rs +++ b/packages/udp-tracker-server/src/statistics/metrics.rs @@ -1,7 +1,7 @@ use serde::Serialize; use torrust_tracker_metrics::label::LabelSet; use torrust_tracker_metrics::metric::MetricName; -use torrust_tracker_metrics::metric_collection::aggregate::Sum; +use torrust_tracker_metrics::metric_collection::aggregate::sum::Sum; use torrust_tracker_metrics::metric_collection::{Error, MetricCollection}; use torrust_tracker_metrics::metric_name; use torrust_tracker_primitives::DurationSinceUnixEpoch; @@ -56,8 +56,7 @@ impl Metrics { pub fn udp_requests_aborted(&self) -> u64 { self.metric_collection .sum(&metric_name!(UDP_TRACKER_SERVER_REQUESTS_ABORTED_TOTAL), &LabelSet::empty()) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) requests banned. @@ -67,8 +66,7 @@ impl Metrics { pub fn udp_requests_banned(&self) -> u64 { self.metric_collection .sum(&metric_name!(UDP_TRACKER_SERVER_REQUESTS_BANNED_TOTAL), &LabelSet::empty()) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of banned IPs. @@ -78,8 +76,7 @@ impl Metrics { pub fn udp_banned_ips_total(&self) -> u64 { self.metric_collection .sum(&metric_name!(UDP_TRACKER_SERVER_IPS_BANNED_TOTAL), &LabelSet::empty()) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Average rounded time spent processing UDP connect requests. @@ -92,8 +89,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_PERFORMANCE_AVG_PROCESSING_TIME_NS), &[("request_kind", "connect")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Average rounded time spent processing UDP announce requests. @@ -106,8 +102,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_PERFORMANCE_AVG_PROCESSING_TIME_NS), &[("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Average rounded time spent processing UDP scrape requests. @@ -120,8 +115,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_PERFORMANCE_AVG_PROCESSING_TIME_NS), &[("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } // UDPv4 @@ -135,8 +129,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) connections from IPv4 peers. @@ -149,8 +142,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "connect")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `announce` requests from IPv4 peers. @@ -163,8 +155,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers. @@ -177,8 +168,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) responses from IPv4 peers. @@ -191,8 +181,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_RESPONSES_SENT_TOTAL), &[("server_binding_address_ip_family", "inet")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `error` requests from IPv4 peers. @@ -205,8 +194,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_ERRORS_TOTAL), &[("server_binding_address_ip_family", "inet")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } // UDPv6 @@ -220,8 +208,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_RECEIVED_TOTAL), &[("server_binding_address_ip_family", "inet6")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers. @@ -234,8 +221,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "connect")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `announce` requests from IPv6 peers. @@ -248,8 +234,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "announce")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `scrape` requests from IPv6 peers. @@ -262,8 +247,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_REQUESTS_ACCEPTED_TOTAL), &[("server_binding_address_ip_family", "inet6"), ("request_kind", "scrape")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) responses from IPv6 peers. @@ -276,8 +260,7 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_RESPONSES_SENT_TOTAL), &[("server_binding_address_ip_family", "inet6")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } /// Total number of UDP (UDP tracker) `error` requests from IPv6 peers. @@ -290,7 +273,6 @@ impl Metrics { &metric_name!(UDP_TRACKER_SERVER_ERRORS_TOTAL), &[("server_binding_address_ip_family", "inet6")].into(), ) - .unwrap_or_default() - .value() as u64 + .unwrap_or_default() as u64 } }