Skip to content

Commit 7e94075

Browse files
committed
Merge #1467: Overhaul stats: Refactor metrics (part 1)
f9ad729 feat: [#1445] add logs for metrics initialization (Jose Celano) ad782eb refactor: [#1445] rename metric label (Jose Celano) 482a1be feat: [#1445] add request kind label to total errors metric (Jose Celano) 13ea091 feat: [#1445] add logs to the event listener's initialization (Jose Celano) 2ccb247 refactor: [#1445] return errors instead of panicking in the SampleCollection struct (Jose Celano) 42e1524 refactor: [#1445] return errors instead of panicking in the MetricCollection struct (Jose Celano) 785a978 refactor: [#1445] remove panic from MetricColelction::new method (Jose Celano) d263be7 refactor: [#1445] return optionals for metric values in metric collection (Jose Celano) 4d68267 refactor: [#1445] replace metric label name constructor by macro (Jose Celano) 7a24f85 refactor: [#1445] new macro to create metric label names (Jose Celano) 5497970 refactor: [#1445] replace metric name constructor by macro (Jose Celano) fc14a81 refactor: [#1445] new macro to create metric names (Jose Celano) Pull request description: Refactor metrics (part 1) ### Subtasks - [x] Extract macro for metric name constructor (to fail at compilation time with empty names) - [x] Replace metric name constructor by new macro - [x] Extract macro for label name constructor (to fail at compilation time with empty names) - [x] Replace label name constructor by new macro - [x] Return an optional in `get_counter_value` and `get_gauge_value`. - [x] Return errors instead of panicking in the `MetricCollection` struct. - [x] Add logs to the listener's initialization (when it starts and finishes). - [x] Add req kind label to the number of errors metric. - [x] Add `tracing` crate. ACKs for top commit: josecelano: ACK f9ad729 Tree-SHA512: 38abbc070a7f3aa0134295667430fa8d7ce90294ae872699786f973d8c790c908a00ed4c5506253dbccd7ae5990c76fd92d187ff935a0806e84909d2e7b64b50
2 parents b061357 + f9ad729 commit 7e94075

File tree

32 files changed

+693
-406
lines changed

32 files changed

+693
-406
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/http-tracker-core/src/event/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::net::{IpAddr, SocketAddr};
22

3-
use torrust_tracker_metrics::label::{LabelName, LabelSet, LabelValue};
3+
use torrust_tracker_metrics::label::{LabelSet, LabelValue};
4+
use torrust_tracker_metrics::label_name;
45
use torrust_tracker_primitives::service_binding::ServiceBinding;
56

67
pub mod sender;
@@ -65,15 +66,15 @@ impl From<ConnectionContext> for LabelSet {
6566
fn from(connection_context: ConnectionContext) -> Self {
6667
LabelSet::from([
6768
(
68-
LabelName::new("server_binding_protocol"),
69+
label_name!("server_binding_protocol"),
6970
LabelValue::new(&connection_context.server.service_binding.protocol().to_string()),
7071
),
7172
(
72-
LabelName::new("server_binding_ip"),
73+
label_name!("server_binding_ip"),
7374
LabelValue::new(&connection_context.server.service_binding.bind_address().ip().to_string()),
7475
),
7576
(
76-
LabelName::new("server_binding_port"),
77+
label_name!("server_binding_port"),
7778
LabelValue::new(&connection_context.server.service_binding.bind_address().port().to_string()),
7879
),
7980
])

packages/http-tracker-core/src/statistics/event/handler.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::net::IpAddr;
22

3-
use torrust_tracker_metrics::label::{LabelName, LabelSet, LabelValue};
4-
use torrust_tracker_metrics::metric::MetricName;
3+
use torrust_tracker_metrics::label::{LabelSet, LabelValue};
4+
use torrust_tracker_metrics::{label_name, metric_name};
55
use torrust_tracker_primitives::DurationSinceUnixEpoch;
66

77
use crate::event::Event;
@@ -29,11 +29,15 @@ pub async fn handle_event(event: Event, stats_repository: &Repository, now: Dura
2929
// Extendable metrics
3030

3131
let mut label_set = LabelSet::from(connection);
32-
label_set.upsert(LabelName::new("request_kind"), LabelValue::new("announce"));
33-
34-
stats_repository
35-
.increase_counter(&MetricName::new(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &label_set, now)
36-
.await;
32+
label_set.upsert(label_name!("request_kind"), LabelValue::new("announce"));
33+
34+
match stats_repository
35+
.increase_counter(&metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &label_set, now)
36+
.await
37+
{
38+
Ok(()) => {}
39+
Err(err) => tracing::error!("Failed to increase the counter: {}", err),
40+
};
3741
}
3842
Event::TcpScrape { connection } => {
3943
// Global fixed metrics
@@ -50,11 +54,15 @@ pub async fn handle_event(event: Event, stats_repository: &Repository, now: Dura
5054
// Extendable metrics
5155

5256
let mut label_set = LabelSet::from(connection);
53-
label_set.upsert(LabelName::new("request_kind"), LabelValue::new("scrape"));
54-
55-
stats_repository
56-
.increase_counter(&MetricName::new(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &label_set, now)
57-
.await;
57+
label_set.upsert(label_name!("request_kind"), LabelValue::new("scrape"));
58+
59+
match stats_repository
60+
.increase_counter(&metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL), &label_set, now)
61+
.await
62+
{
63+
Ok(()) => {}
64+
Err(err) => tracing::error!("Failed to increase the counter: {}", err),
65+
};
5866
}
5967
}
6068

packages/http-tracker-core/src/statistics/keeper.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use tokio::sync::broadcast::Receiver;
33
use super::event::listener::dispatch_events;
44
use super::repository::Repository;
55
use crate::event::Event;
6+
use crate::HTTP_TRACKER_LOG_TARGET;
67

78
/// The service responsible for keeping tracker metrics (listening to statistics events and handle them).
89
///
@@ -29,7 +30,13 @@ impl Keeper {
2930
pub fn run_event_listener(&mut self, receiver: Receiver<Event>) {
3031
let stats_repository = self.repository.clone();
3132

32-
tokio::spawn(async move { dispatch_events(receiver, stats_repository).await });
33+
tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "Starting HTTP tracker core event listener");
34+
35+
tokio::spawn(async move {
36+
dispatch_events(receiver, stats_repository).await;
37+
38+
tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "HTTP tracker core event listener finished");
39+
});
3340
}
3441
}
3542

packages/http-tracker-core/src/statistics/metrics.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use serde::Serialize;
22
use torrust_tracker_metrics::label::LabelSet;
33
use torrust_tracker_metrics::metric::MetricName;
4-
use torrust_tracker_metrics::metric_collection::MetricCollection;
4+
use torrust_tracker_metrics::metric_collection::{Error, MetricCollection};
55
use torrust_tracker_primitives::DurationSinceUnixEpoch;
66

77
/// Metrics collected by the tracker.
@@ -24,11 +24,28 @@ pub struct Metrics {
2424
}
2525

2626
impl Metrics {
27-
pub fn increase_counter(&mut self, metric_name: &MetricName, labels: &LabelSet, now: DurationSinceUnixEpoch) {
28-
self.metric_collection.increase_counter(metric_name, labels, now);
27+
/// # Errors
28+
///
29+
/// Returns an error if the metric does not exist and it cannot be created.
30+
pub fn increase_counter(
31+
&mut self,
32+
metric_name: &MetricName,
33+
labels: &LabelSet,
34+
now: DurationSinceUnixEpoch,
35+
) -> Result<(), Error> {
36+
self.metric_collection.increase_counter(metric_name, labels, now)
2937
}
3038

31-
pub fn set_gauge(&mut self, metric_name: &MetricName, labels: &LabelSet, value: f64, now: DurationSinceUnixEpoch) {
32-
self.metric_collection.set_gauge(metric_name, labels, value, now);
39+
/// # Errors
40+
///
41+
/// Returns an error if the metric does not exist and it cannot be created.
42+
pub fn set_gauge(
43+
&mut self,
44+
metric_name: &MetricName,
45+
labels: &LabelSet,
46+
value: f64,
47+
now: DurationSinceUnixEpoch,
48+
) -> Result<(), Error> {
49+
self.metric_collection.set_gauge(metric_name, labels, value, now)
3350
}
3451
}

packages/http-tracker-core/src/statistics/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub mod setup;
77

88
use metrics::Metrics;
99
use torrust_tracker_metrics::metric::description::MetricDescription;
10-
use torrust_tracker_metrics::metric::MetricName;
10+
use torrust_tracker_metrics::metric_name;
1111
use torrust_tracker_metrics::unit::Unit;
1212

1313
const HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL: &str = "http_tracker_core_requests_received_total";
@@ -17,7 +17,7 @@ pub fn describe_metrics() -> Metrics {
1717
let mut metrics = Metrics::default();
1818

1919
metrics.metric_collection.describe_counter(
20-
&MetricName::new(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL),
20+
&metric_name!(HTTP_TRACKER_CORE_REQUESTS_RECEIVED_TOTAL),
2121
Some(Unit::Count),
2222
Some(MetricDescription::new("Total number of HTTP requests received")),
2323
);

packages/http-tracker-core/src/statistics/repository.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::Arc;
33
use tokio::sync::{RwLock, RwLockReadGuard};
44
use torrust_tracker_metrics::label::LabelSet;
55
use torrust_tracker_metrics::metric::MetricName;
6+
use torrust_tracker_metrics::metric_collection::Error;
67
use torrust_tracker_primitives::DurationSinceUnixEpoch;
78

89
use super::describe_metrics;
@@ -56,9 +57,22 @@ impl Repository {
5657
drop(stats_lock);
5758
}
5859

59-
pub async fn increase_counter(&self, metric_name: &MetricName, labels: &LabelSet, now: DurationSinceUnixEpoch) {
60+
/// # Errors
61+
///
62+
/// This function will return an error if the metric collection fails to
63+
/// increase the counter.
64+
pub async fn increase_counter(
65+
&self,
66+
metric_name: &MetricName,
67+
labels: &LabelSet,
68+
now: DurationSinceUnixEpoch,
69+
) -> Result<(), Error> {
6070
let mut stats_lock = self.stats.write().await;
61-
stats_lock.increase_counter(metric_name, labels, now);
71+
72+
let result = stats_lock.increase_counter(metric_name, labels, now);
73+
6274
drop(stats_lock);
75+
76+
result
6377
}
6478
}

packages/metrics/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ serde = { version = "1", features = ["derive"] }
2121
serde_json = "1.0.140"
2222
thiserror = "2"
2323
torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" }
24+
tracing = "0.1.41"
2425

2526
[dev-dependencies]
2627
approx = "0.5.1"

packages/metrics/src/label/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
mod name;
1+
pub mod name;
22
mod pair;
33
mod set;
4-
mod value;
4+
pub mod value;
55

66
pub type LabelName = name::LabelName;
77
pub type LabelValue = value::LabelValue;

packages/metrics/src/label/name.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ impl LabelName {
1414
/// Panics if the provided name is empty.
1515
#[must_use]
1616
pub fn new(name: &str) -> Self {
17-
assert!(
18-
!name.is_empty(),
19-
"Label name cannot be empty. It must have at least one character."
20-
);
21-
17+
assert!(!name.is_empty(), "Label name cannot be empty.");
2218
Self(name.to_owned())
2319
}
2420
}
@@ -69,6 +65,19 @@ impl PrometheusSerializable for LabelName {
6965
}
7066
}
7167
}
68+
69+
#[macro_export]
70+
macro_rules! label_name {
71+
("") => {
72+
compile_error!("Label name cannot be empty");
73+
};
74+
($name:literal) => {
75+
$crate::label::name::LabelName::new($name)
76+
};
77+
($name:ident) => {
78+
$crate::label::name::LabelName::new($name)
79+
};
80+
}
7281
#[cfg(test)]
7382
mod tests {
7483
mod serialization_of_label_name_to_prometheus {
@@ -83,7 +92,7 @@ mod tests {
8392
#[case("3 leading lowercase", "v123", "v123")]
8493
#[case("4 leading uppercase", "V123", "V123")]
8594
fn valid_names_in_prometheus(#[case] case: &str, #[case] input: &str, #[case] output: &str) {
86-
assert_eq!(LabelName::new(input).to_prometheus(), output, "{case} failed: {input:?}");
95+
assert_eq!(label_name!(input).to_prometheus(), output, "{case} failed: {input:?}");
8796
}
8897

8998
#[rstest]
@@ -96,7 +105,7 @@ mod tests {
96105
#[case("7 all invalid characters", "!@#$%^&*()", "__________")]
97106
#[case("8 non_ascii_characters", "ñaca©", "_aca_")]
98107
fn names_that_need_changes_in_prometheus(#[case] case: &str, #[case] input: &str, #[case] output: &str) {
99-
assert_eq!(LabelName::new(input).to_prometheus(), output, "{case} failed: {input:?}");
108+
assert_eq!(label_name!(input).to_prometheus(), output, "{case} failed: {input:?}");
100109
}
101110

102111
#[rstest]
@@ -105,11 +114,11 @@ mod tests {
105114
#[case("3 processed to double underscore", "^^name", "___name")]
106115
#[case("4 processed to double underscore after first char", "0__name", "___name")]
107116
fn names_starting_with_double_underscore(#[case] case: &str, #[case] input: &str, #[case] output: &str) {
108-
assert_eq!(LabelName::new(input).to_prometheus(), output, "{case} failed: {input:?}");
117+
assert_eq!(label_name!(input).to_prometheus(), output, "{case} failed: {input:?}");
109118
}
110119

111120
#[test]
112-
#[should_panic(expected = "Label name cannot be empty. It must have at least one character.")]
121+
#[should_panic(expected = "Label name cannot be empty.")]
113122
fn empty_name() {
114123
let _name = LabelName::new("");
115124
}

0 commit comments

Comments
 (0)