Skip to content

Commit 903d47f

Browse files
committed
feat: [torrust#1145] add UDP avg processing time to stats
```json { "torrents": 1, "seeders": 1, "completed": 0, "leechers": 0, "tcp4_connections_handled": 0, "tcp4_announces_handled": 0, "tcp4_scrapes_handled": 0, "tcp6_connections_handled": 0, "tcp6_announces_handled": 0, "tcp6_scrapes_handled": 0, "udp_requests_aborted": 0, "udp_requests_banned": 0, "udp_banned_ips_total": 0, "udp_avg_connect_processing_time_ns": 37000, "udp_avg_announce_processing_time_ns": 42067, "udp_avg_scrape_processing_time_ns": 0, "udp4_requests": 60, "udp4_connections_handled": 30, "udp4_announces_handled": 30, "udp4_scrapes_handled": 0, "udp4_responses": 60, "udp4_errors_handled": 0, "udp6_requests": 0, "udp6_connections_handled": 0, "udp6_announces_handled": 0, "udp6_scrapes_handled": 0, "udp6_responses": 0, "udp6_errors_handled": 0 } ``` New metrcis are: - udp_avg_connect_processing_time_ns - udp_avg_announce_processing_time_ns - udp_avg_scrape_processing_time_ns
1 parent 08a862a commit 903d47f

File tree

7 files changed

+187
-29
lines changed

7 files changed

+187
-29
lines changed

src/core/services/statistics/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,29 @@ pub async fn get_metrics(tracker: Arc<Tracker>, ban_service: Arc<RwLock<BanServi
7070
TrackerMetrics {
7171
torrents_metrics,
7272
protocol_metrics: Metrics {
73-
// TCP
73+
// TCPv4
7474
tcp4_connections_handled: stats.tcp4_connections_handled,
7575
tcp4_announces_handled: stats.tcp4_announces_handled,
7676
tcp4_scrapes_handled: stats.tcp4_scrapes_handled,
77+
// TCPv6
7778
tcp6_connections_handled: stats.tcp6_connections_handled,
7879
tcp6_announces_handled: stats.tcp6_announces_handled,
7980
tcp6_scrapes_handled: stats.tcp6_scrapes_handled,
8081
// UDP
8182
udp_requests_aborted: stats.udp_requests_aborted,
8283
udp_requests_banned: stats.udp_requests_banned,
8384
udp_banned_ips_total: udp_banned_ips_total as u64,
85+
udp_avg_connect_processing_time_ns: stats.udp_avg_connect_processing_time_ns,
86+
udp_avg_announce_processing_time_ns: stats.udp_avg_announce_processing_time_ns,
87+
udp_avg_scrape_processing_time_ns: stats.udp_avg_scrape_processing_time_ns,
88+
// UDPv4
8489
udp4_requests: stats.udp4_requests,
8590
udp4_connections_handled: stats.udp4_connections_handled,
8691
udp4_announces_handled: stats.udp4_announces_handled,
8792
udp4_scrapes_handled: stats.udp4_scrapes_handled,
8893
udp4_responses: stats.udp4_responses,
8994
udp4_errors_handled: stats.udp4_errors_handled,
95+
// UDPv6
9096
udp6_requests: stats.udp6_requests,
9197
udp6_connections_handled: stats.udp6_connections_handled,
9298
udp6_announces_handled: stats.udp6_announces_handled,

src/core/statistics/event/handler.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::core::statistics::event::Event;
1+
use crate::core::statistics::event::{Event, UdpResponseKind};
22
use crate::core::statistics::repository::Repository;
33

44
pub async fn handle_event(event: Event, stats_repository: &Repository) {
@@ -45,10 +45,29 @@ pub async fn handle_event(event: Event, stats_repository: &Repository) {
4545
stats_repository.increase_udp4_scrapes().await;
4646
}
4747
Event::Udp4Response {
48-
kind: _,
49-
req_processing_time: _,
48+
kind,
49+
req_processing_time,
5050
} => {
5151
stats_repository.increase_udp4_responses().await;
52+
53+
match kind {
54+
UdpResponseKind::Connect => {
55+
stats_repository
56+
.recalculate_udp_avg_connect_processing_time_ns(req_processing_time)
57+
.await;
58+
}
59+
UdpResponseKind::Announce => {
60+
stats_repository
61+
.recalculate_udp_avg_announce_processing_time_ns(req_processing_time)
62+
.await;
63+
}
64+
UdpResponseKind::Scrape => {
65+
stats_repository
66+
.recalculate_udp_avg_scrape_processing_time_ns(req_processing_time)
67+
.await;
68+
}
69+
UdpResponseKind::Error => {}
70+
}
5271
}
5372
Event::Udp4Error => {
5473
stats_repository.increase_udp4_errors().await;

src/core/statistics/metrics.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct Metrics {
2828
/// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers.
2929
pub tcp6_scrapes_handled: u64,
3030

31+
// UDP
3132
/// Total number of UDP (UDP tracker) requests aborted.
3233
pub udp_requests_aborted: u64,
3334

@@ -37,6 +38,16 @@ pub struct Metrics {
3738
/// Total number of banned IPs.
3839
pub udp_banned_ips_total: u64,
3940

41+
/// Average rounded time spent processing UDP connect requests.
42+
pub udp_avg_connect_processing_time_ns: u64,
43+
44+
/// Average rounded time spent processing UDP announce requests.
45+
pub udp_avg_announce_processing_time_ns: u64,
46+
47+
/// Average rounded time spent processing UDP scrape requests.
48+
pub udp_avg_scrape_processing_time_ns: u64,
49+
50+
// UDPv4
4051
/// Total number of UDP (UDP tracker) requests from IPv4 peers.
4152
pub udp4_requests: u64,
4253

@@ -55,6 +66,7 @@ pub struct Metrics {
5566
/// Total number of UDP (UDP tracker) `error` requests from IPv4 peers.
5667
pub udp4_errors_handled: u64,
5768

69+
// UDPv6
5870
/// Total number of UDP (UDP tracker) requests from IPv6 peers.
5971
pub udp6_requests: u64,
6072

src/core/statistics/repository.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::sync::Arc;
2+
use std::time::Duration;
23

34
use tokio::sync::{RwLock, RwLockReadGuard};
45

@@ -112,6 +113,64 @@ impl Repository {
112113
drop(stats_lock);
113114
}
114115

116+
#[allow(clippy::cast_precision_loss)]
117+
#[allow(clippy::cast_possible_truncation)]
118+
#[allow(clippy::cast_sign_loss)]
119+
pub async fn recalculate_udp_avg_connect_processing_time_ns(&self, req_processing_time: Duration) {
120+
let mut stats_lock = self.stats.write().await;
121+
122+
let req_processing_time = req_processing_time.as_nanos() as f64;
123+
let udp_connections_handled = (stats_lock.udp4_connections_handled + stats_lock.udp6_connections_handled) as f64;
124+
125+
let previous_avg = stats_lock.udp_avg_connect_processing_time_ns;
126+
127+
// Moving average: https://en.wikipedia.org/wiki/Moving_average
128+
let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_connections_handled;
129+
130+
stats_lock.udp_avg_connect_processing_time_ns = new_avg.ceil() as u64;
131+
132+
drop(stats_lock);
133+
}
134+
135+
#[allow(clippy::cast_precision_loss)]
136+
#[allow(clippy::cast_possible_truncation)]
137+
#[allow(clippy::cast_sign_loss)]
138+
pub async fn recalculate_udp_avg_announce_processing_time_ns(&self, req_processing_time: Duration) {
139+
let mut stats_lock = self.stats.write().await;
140+
141+
let req_processing_time = req_processing_time.as_nanos() as f64;
142+
143+
let udp_announces_handled = (stats_lock.udp4_announces_handled + stats_lock.udp6_announces_handled) as f64;
144+
145+
let previous_avg = stats_lock.udp_avg_announce_processing_time_ns;
146+
147+
// Moving average: https://en.wikipedia.org/wiki/Moving_average
148+
let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_announces_handled;
149+
150+
stats_lock.udp_avg_announce_processing_time_ns = new_avg.ceil() as u64;
151+
152+
drop(stats_lock);
153+
}
154+
155+
#[allow(clippy::cast_precision_loss)]
156+
#[allow(clippy::cast_possible_truncation)]
157+
#[allow(clippy::cast_sign_loss)]
158+
pub async fn recalculate_udp_avg_scrape_processing_time_ns(&self, req_processing_time: Duration) {
159+
let mut stats_lock = self.stats.write().await;
160+
161+
let req_processing_time = req_processing_time.as_nanos() as f64;
162+
let udp_scrapes_handled = (stats_lock.udp4_scrapes_handled + stats_lock.udp6_scrapes_handled) as f64;
163+
164+
let previous_avg = stats_lock.udp_avg_scrape_processing_time_ns;
165+
166+
// Moving average: https://en.wikipedia.org/wiki/Moving_average
167+
let new_avg = previous_avg as f64 + (req_processing_time - previous_avg as f64) / udp_scrapes_handled;
168+
169+
stats_lock.udp_avg_scrape_processing_time_ns = new_avg.ceil() as u64;
170+
171+
drop(stats_lock);
172+
}
173+
115174
pub async fn increase_udp6_requests(&self) {
116175
let mut stats_lock = self.stats.write().await;
117176
stats_lock.udp6_requests += 1;

src/servers/apis/v1/context/stats/resources.rs

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,21 @@ pub struct Stats {
3434
/// Total number of TCP (HTTP tracker) `scrape` requests from IPv6 peers.
3535
pub tcp6_scrapes_handled: u64,
3636

37+
// UDP
3738
/// Total number of UDP (UDP tracker) requests aborted.
3839
pub udp_requests_aborted: u64,
3940
/// Total number of UDP (UDP tracker) requests banned.
4041
pub udp_requests_banned: u64,
4142
/// Total number of IPs banned for UDP (UDP tracker) requests.
4243
pub udp_banned_ips_total: u64,
44+
/// Average rounded time spent processing UDP connect requests.
45+
pub udp_avg_connect_processing_time_ns: u64,
46+
/// Average rounded time spent processing UDP announce requests.
47+
pub udp_avg_announce_processing_time_ns: u64,
48+
/// Average rounded time spent processing UDP scrape requests.
49+
pub udp_avg_scrape_processing_time_ns: u64,
4350

51+
// UDPv4
4452
/// Total number of UDP (UDP tracker) requests from IPv4 peers.
4553
pub udp4_requests: u64,
4654
/// Total number of UDP (UDP tracker) connections from IPv4 peers.
@@ -54,6 +62,7 @@ pub struct Stats {
5462
/// Total number of UDP (UDP tracker) `scrape` requests from IPv4 peers.
5563
pub udp4_errors_handled: u64,
5664

65+
// UDPv6
5766
/// Total number of UDP (UDP tracker) requests from IPv6 peers.
5867
pub udp6_requests: u64,
5968
/// Total number of UDP (UDP tracker) `connection` requests from IPv6 peers.
@@ -86,12 +95,17 @@ impl From<TrackerMetrics> for Stats {
8695
udp_requests_aborted: metrics.protocol_metrics.udp_requests_aborted,
8796
udp_requests_banned: metrics.protocol_metrics.udp_requests_banned,
8897
udp_banned_ips_total: metrics.protocol_metrics.udp_banned_ips_total,
98+
udp_avg_connect_processing_time_ns: metrics.protocol_metrics.udp_avg_connect_processing_time_ns,
99+
udp_avg_announce_processing_time_ns: metrics.protocol_metrics.udp_avg_announce_processing_time_ns,
100+
udp_avg_scrape_processing_time_ns: metrics.protocol_metrics.udp_avg_scrape_processing_time_ns,
101+
// UDPv4
89102
udp4_requests: metrics.protocol_metrics.udp4_requests,
90103
udp4_connections_handled: metrics.protocol_metrics.udp4_connections_handled,
91104
udp4_announces_handled: metrics.protocol_metrics.udp4_announces_handled,
92105
udp4_scrapes_handled: metrics.protocol_metrics.udp4_scrapes_handled,
93106
udp4_responses: metrics.protocol_metrics.udp4_responses,
94107
udp4_errors_handled: metrics.protocol_metrics.udp4_errors_handled,
108+
// UDPv6
95109
udp6_requests: metrics.protocol_metrics.udp6_requests,
96110
udp6_connections_handled: metrics.protocol_metrics.udp6_connections_handled,
97111
udp6_announces_handled: metrics.protocol_metrics.udp6_announces_handled,
@@ -132,48 +146,59 @@ mod tests {
132146
udp_requests_aborted: 11,
133147
udp_requests_banned: 12,
134148
udp_banned_ips_total: 13,
135-
udp4_requests: 14,
136-
udp4_connections_handled: 15,
137-
udp4_announces_handled: 16,
138-
udp4_scrapes_handled: 17,
139-
udp4_responses: 18,
140-
udp4_errors_handled: 19,
141-
udp6_requests: 20,
142-
udp6_connections_handled: 21,
143-
udp6_announces_handled: 22,
144-
udp6_scrapes_handled: 23,
145-
udp6_responses: 24,
146-
udp6_errors_handled: 25
149+
udp_avg_connect_processing_time_ns: 14,
150+
udp_avg_announce_processing_time_ns: 15,
151+
udp_avg_scrape_processing_time_ns: 16,
152+
// UDPv4
153+
udp4_requests: 17,
154+
udp4_connections_handled: 18,
155+
udp4_announces_handled: 19,
156+
udp4_scrapes_handled: 20,
157+
udp4_responses: 21,
158+
udp4_errors_handled: 22,
159+
// UDPv6
160+
udp6_requests: 23,
161+
udp6_connections_handled: 24,
162+
udp6_announces_handled: 25,
163+
udp6_scrapes_handled: 26,
164+
udp6_responses: 27,
165+
udp6_errors_handled: 28
147166
}
148167
}),
149168
Stats {
150169
torrents: 4,
151170
seeders: 1,
152171
completed: 2,
153172
leechers: 3,
154-
// TCP
173+
// TCPv4
155174
tcp4_connections_handled: 5,
156175
tcp4_announces_handled: 6,
157176
tcp4_scrapes_handled: 7,
177+
// TCPv6
158178
tcp6_connections_handled: 8,
159179
tcp6_announces_handled: 9,
160180
tcp6_scrapes_handled: 10,
161181
// UDP
162182
udp_requests_aborted: 11,
163183
udp_requests_banned: 12,
164184
udp_banned_ips_total: 13,
165-
udp4_requests: 14,
166-
udp4_connections_handled: 15,
167-
udp4_announces_handled: 16,
168-
udp4_scrapes_handled: 17,
169-
udp4_responses: 18,
170-
udp4_errors_handled: 19,
171-
udp6_requests: 20,
172-
udp6_connections_handled: 21,
173-
udp6_announces_handled: 22,
174-
udp6_scrapes_handled: 23,
175-
udp6_responses: 24,
176-
udp6_errors_handled: 25
185+
udp_avg_connect_processing_time_ns: 14,
186+
udp_avg_announce_processing_time_ns: 15,
187+
udp_avg_scrape_processing_time_ns: 16,
188+
// UDPv4
189+
udp4_requests: 17,
190+
udp4_connections_handled: 18,
191+
udp4_announces_handled: 19,
192+
udp4_scrapes_handled: 20,
193+
udp4_responses: 21,
194+
udp4_errors_handled: 22,
195+
// UDPv6
196+
udp6_requests: 23,
197+
udp6_connections_handled: 24,
198+
udp6_announces_handled: 25,
199+
udp6_scrapes_handled: 26,
200+
udp6_responses: 27,
201+
udp6_errors_handled: 28
177202
}
178203
);
179204
}

src/servers/apis/v1/context/stats/responses.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ pub fn metrics_response(tracker_metrics: &TrackerMetrics) -> Response {
2121
lines.push(format!("completed {}", tracker_metrics.torrents_metrics.downloaded));
2222
lines.push(format!("leechers {}", tracker_metrics.torrents_metrics.incomplete));
2323

24+
// TCP
25+
26+
// TCPv4
27+
2428
lines.push(format!(
2529
"tcp4_connections_handled {}",
2630
tracker_metrics.protocol_metrics.tcp4_connections_handled
@@ -34,6 +38,8 @@ pub fn metrics_response(tracker_metrics: &TrackerMetrics) -> Response {
3438
tracker_metrics.protocol_metrics.tcp4_scrapes_handled
3539
));
3640

41+
// TCPv6
42+
3743
lines.push(format!(
3844
"tcp6_connections_handled {}",
3945
tracker_metrics.protocol_metrics.tcp6_connections_handled
@@ -47,10 +53,34 @@ pub fn metrics_response(tracker_metrics: &TrackerMetrics) -> Response {
4753
tracker_metrics.protocol_metrics.tcp6_scrapes_handled
4854
));
4955

56+
// UDP
57+
5058
lines.push(format!(
5159
"udp_requests_aborted {}",
5260
tracker_metrics.protocol_metrics.udp_requests_aborted
5361
));
62+
lines.push(format!(
63+
"udp_requests_banned {}",
64+
tracker_metrics.protocol_metrics.udp_requests_banned
65+
));
66+
lines.push(format!(
67+
"udp_banned_ips_total {}",
68+
tracker_metrics.protocol_metrics.udp_banned_ips_total
69+
));
70+
lines.push(format!(
71+
"udp_avg_connect_processing_time_ns {}",
72+
tracker_metrics.protocol_metrics.udp_avg_connect_processing_time_ns
73+
));
74+
lines.push(format!(
75+
"udp_avg_announce_processing_time_ns {}",
76+
tracker_metrics.protocol_metrics.udp_avg_announce_processing_time_ns
77+
));
78+
lines.push(format!(
79+
"udp_avg_scrape_processing_time_ns {}",
80+
tracker_metrics.protocol_metrics.udp_avg_scrape_processing_time_ns
81+
));
82+
83+
// UDPv4
5484

5585
lines.push(format!("udp4_requests {}", tracker_metrics.protocol_metrics.udp4_requests));
5686
lines.push(format!(
@@ -71,6 +101,8 @@ pub fn metrics_response(tracker_metrics: &TrackerMetrics) -> Response {
71101
tracker_metrics.protocol_metrics.udp4_errors_handled
72102
));
73103

104+
// UDPv6
105+
74106
lines.push(format!("udp6_requests {}", tracker_metrics.protocol_metrics.udp6_requests));
75107
lines.push(format!(
76108
"udp6_connections_handled {}",

tests/servers/api/v1/contract/context/stats.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,17 @@ async fn should_allow_getting_tracker_statistics() {
4747
udp_requests_aborted: 0,
4848
udp_requests_banned: 0,
4949
udp_banned_ips_total: 0,
50+
udp_avg_connect_processing_time_ns: 0,
51+
udp_avg_announce_processing_time_ns: 0,
52+
udp_avg_scrape_processing_time_ns: 0,
53+
// UDPv4
5054
udp4_requests: 0,
5155
udp4_connections_handled: 0,
5256
udp4_announces_handled: 0,
5357
udp4_scrapes_handled: 0,
5458
udp4_responses: 0,
5559
udp4_errors_handled: 0,
60+
// UDPv6
5661
udp6_requests: 0,
5762
udp6_connections_handled: 0,
5863
udp6_announces_handled: 0,

0 commit comments

Comments
 (0)