4
4
use crate :: node_status_api:: models:: Uptime ;
5
5
use crate :: node_status_api:: { FIFTEEN_MINUTES , ONE_HOUR } ;
6
6
use crate :: storage:: models:: NodeStatus ;
7
+ use log:: warn;
7
8
use sqlx:: types:: time:: OffsetDateTime ;
9
+ use std:: cmp:: max;
8
10
9
11
// A temporary helper struct used to produce reports for active nodes.
10
12
pub ( crate ) struct ActiveNodeDayStatuses {
@@ -30,33 +32,23 @@ pub(crate) struct NodeUptimes {
30
32
31
33
impl NodeUptimes {
32
34
pub ( crate ) fn calculate_from_last_day_reports (
35
+ report_time : OffsetDateTime ,
33
36
last_day_ipv4 : Vec < NodeStatus > ,
34
37
last_day_ipv6 : Vec < NodeStatus > ,
38
+ last_hour_test_runs : usize ,
39
+ last_day_test_runs : usize ,
35
40
) -> Self {
36
- let now = OffsetDateTime :: now_utc ( ) ;
37
- let hour_ago = ( now - ONE_HOUR ) . unix_timestamp ( ) ;
38
- let fifteen_minutes_ago = ( now - FIFTEEN_MINUTES ) . unix_timestamp ( ) ;
41
+ let hour_ago = ( report_time - ONE_HOUR ) . unix_timestamp ( ) ;
42
+ let fifteen_minutes_ago = ( report_time - FIFTEEN_MINUTES ) . unix_timestamp ( ) ;
39
43
40
- let ipv4_day_total = last_day_ipv4. len ( ) ;
41
- let ipv6_day_total = last_day_ipv6. len ( ) ;
44
+ let mut ipv4_day_up = last_day_ipv4. iter ( ) . filter ( |report| report . up ) . count ( ) ;
45
+ let mut ipv6_day_up = last_day_ipv6. iter ( ) . filter ( |report| report . up ) . count ( ) ;
42
46
43
- let ipv4_day_up = last_day_ipv4. iter ( ) . filter ( |report| report. up ) . count ( ) ;
44
- let ipv6_day_up = last_day_ipv6. iter ( ) . filter ( |report| report. up ) . count ( ) ;
45
-
46
- let ipv4_hour_total = last_day_ipv4
47
- . iter ( )
48
- . filter ( |report| report. timestamp >= hour_ago)
49
- . count ( ) ;
50
- let ipv6_hour_total = last_day_ipv6
51
- . iter ( )
52
- . filter ( |report| report. timestamp >= hour_ago)
53
- . count ( ) ;
54
-
55
- let ipv4_hour_up = last_day_ipv4
47
+ let mut ipv4_hour_up = last_day_ipv4
56
48
. iter ( )
57
49
. filter ( |report| report. up && report. timestamp >= hour_ago)
58
50
. count ( ) ;
59
- let ipv6_hour_up = last_day_ipv6
51
+ let mut ipv6_hour_up = last_day_ipv6
60
52
. iter ( )
61
53
. filter ( |report| report. up && report. timestamp >= hour_ago)
62
54
. count ( ) ;
@@ -73,15 +65,42 @@ impl NodeUptimes {
73
65
. map ( |status| status. timestamp >= fifteen_minutes_ago && status. up ) // make sure its within last 15min
74
66
. unwrap_or_default ( ) ;
75
67
76
- // the unwraps in Uptime::from_ratio are fine because it's impossible for us to have more "up" results than all results in total
77
- // because both of those values originate from the same vector
68
+ // If somehow we have more "up" reports than the actual test runs it means something weird is going on
69
+ // (or we just started running this code on old data, so if it appears for first 24h, it's fine and actually expected
70
+ // as we would not have any run information from the past)
71
+ // Either way, bound the the number of "up" reports by number of test runs and log warnings
72
+ // if that happens
73
+ if ipv4_hour_up > last_hour_test_runs || ipv6_hour_up > last_hour_test_runs {
74
+ warn ! (
75
+ "We have more 'up' reports than the actual number of test runs in last hour! ({} ipv4 'ups', {} ipv6 'ups' for {} test runs)" ,
76
+ ipv4_hour_up,
77
+ ipv6_hour_up,
78
+ last_hour_test_runs,
79
+ ) ;
80
+ ipv4_hour_up = max ( ipv4_hour_up, last_hour_test_runs) ;
81
+ ipv6_hour_up = max ( ipv6_hour_up, last_hour_test_runs) ;
82
+ }
83
+
84
+ if ipv4_day_up > last_day_test_runs || ipv6_day_up > last_day_test_runs {
85
+ warn ! (
86
+ "We have more 'up' reports than the actual number of test runs in last day! ({} ipv4 'ups', {} ipv6 'ups' for {} test runs)" ,
87
+ ipv4_day_up,
88
+ ipv6_day_up,
89
+ last_day_test_runs,
90
+ ) ;
91
+ ipv4_day_up = max ( ipv4_day_up, last_day_test_runs) ;
92
+ ipv6_day_up = max ( ipv6_day_up, last_day_test_runs) ;
93
+ }
94
+
95
+ // the unwraps in Uptime::from_ratio are fine because it's impossible for us to have more "up" results
96
+ // than total test runs as we just bounded them
78
97
NodeUptimes {
79
98
most_recent_ipv4,
80
99
most_recent_ipv6,
81
- last_hour_ipv4 : Uptime :: from_ratio ( ipv4_hour_up, ipv4_hour_total ) . unwrap ( ) ,
82
- last_hour_ipv6 : Uptime :: from_ratio ( ipv6_hour_up, ipv6_hour_total ) . unwrap ( ) ,
83
- last_day_ipv4 : Uptime :: from_ratio ( ipv4_day_up, ipv4_day_total ) . unwrap ( ) ,
84
- last_day_ipv6 : Uptime :: from_ratio ( ipv6_day_up, ipv6_day_total ) . unwrap ( ) ,
100
+ last_hour_ipv4 : Uptime :: from_ratio ( ipv4_hour_up, last_hour_test_runs ) . unwrap ( ) ,
101
+ last_hour_ipv6 : Uptime :: from_ratio ( ipv6_hour_up, last_hour_test_runs ) . unwrap ( ) ,
102
+ last_day_ipv4 : Uptime :: from_ratio ( ipv4_day_up, last_day_test_runs ) . unwrap ( ) ,
103
+ last_day_ipv6 : Uptime :: from_ratio ( ipv6_day_up, last_day_test_runs ) . unwrap ( ) ,
85
104
}
86
105
}
87
106
}
0 commit comments