Feature/removal of monitor good nodes (#833)

* Removed separated ipv4 and ipv6 testing

* Testing network using chosen core nodes

This should have probably been like 20 independent commits... sorry...

* SQL migrations for updated schema

* SQL updates

* Using absolute uptime directly

* New uptime calculations

* Config entries, more DB work, some cleanup

* Additional API query routes

* More SQL and API work

* Changed `_` to `-` in new routes

* Removed good topology from config

* Fixed gateways reader yield condition

* Initial gateways pinger

* Minor cleanup and logging level decreases

* Missing trait derivations

* Further logging adjustments

* Unused commented out import

* Claiming additional bandwidth in coconut feature when low

* Fixed build with coconut feature

* Minimum number of test routes

* Making beta/nightly clippy happier
This commit is contained in:
Jędrzej Stuczyński
2021-11-09 12:25:41 +00:00
committed by GitHub
parent 955ef7b871
commit 8bcc931d9b
27 changed files with 2380 additions and 1736 deletions
+66 -61
View File
@@ -5,100 +5,105 @@ use crate::node_status_api::models::Uptime;
use crate::node_status_api::{FIFTEEN_MINUTES, ONE_HOUR};
use crate::storage::models::NodeStatus;
use log::warn;
use std::cmp::min;
use std::convert::TryInto;
use time::OffsetDateTime;
// A temporary helper struct used to produce reports for active nodes.
pub(crate) struct ActiveNodeDayStatuses {
pub(crate) struct ActiveNodeStatuses {
pub(crate) identity: String,
pub(crate) owner: String,
pub(crate) ipv4_statuses: Vec<NodeStatus>,
pub(crate) ipv6_statuses: Vec<NodeStatus>,
pub(crate) statuses: Vec<NodeStatus>,
}
// A helper intermediate struct to remove duplicate code for construction of mixnode and gateway reports
pub(crate) struct NodeUptimes {
pub(crate) most_recent_ipv4: bool,
pub(crate) most_recent_ipv6: bool,
pub(crate) most_recent: Uptime,
pub(crate) last_hour_ipv4: Uptime,
pub(crate) last_hour_ipv6: Uptime,
pub(crate) last_day_ipv4: Uptime,
pub(crate) last_day_ipv6: Uptime,
pub(crate) last_hour: Uptime,
pub(crate) last_day: Uptime,
}
impl NodeUptimes {
pub(crate) fn calculate_from_last_day_reports(
report_time: OffsetDateTime,
last_day_ipv4: Vec<NodeStatus>,
last_day_ipv6: Vec<NodeStatus>,
last_day: Vec<NodeStatus>,
last_hour_test_runs: usize,
last_day_test_runs: usize,
) -> Self {
let hour_ago = (report_time - ONE_HOUR).unix_timestamp();
let fifteen_minutes_ago = (report_time - FIFTEEN_MINUTES).unix_timestamp();
let mut ipv4_day_up = last_day_ipv4.iter().filter(|report| report.up).count();
let mut ipv6_day_up = last_day_ipv6.iter().filter(|report| report.up).count();
let mut ipv4_hour_up = last_day_ipv4
.iter()
.filter(|report| report.up && report.timestamp >= hour_ago)
.count();
let mut ipv6_hour_up = last_day_ipv6
.iter()
.filter(|report| report.up && report.timestamp >= hour_ago)
.count();
// most recent status MUST BE within last 15min
let most_recent_ipv4 = last_day_ipv4
.iter()
.max_by_key(|report| report.timestamp) // find the most recent
.map(|status| status.timestamp >= fifteen_minutes_ago && status.up) // make sure its within last 15min
.unwrap_or_default();
let most_recent_ipv6 = last_day_ipv6
.iter()
.max_by_key(|report| report.timestamp) // find the most recent
.map(|status| status.timestamp >= fifteen_minutes_ago && status.up) // make sure its within last 15min
.unwrap_or_default();
// If somehow we have more "up" reports than the actual test runs it means something weird is going on
// If somehow we have more reports than the actual test runs it means something weird is going on
// (or we just started running this code on old data, so if it appears for first 24h, it's fine and actually expected
// as we would not have any run information from the past)
// Either way, bound the the number of "up" reports by number of test runs and log warnings
// if that happens
if ipv4_hour_up > last_hour_test_runs || ipv6_hour_up > last_hour_test_runs {
warn!(
"We have more 'up' reports than the actual number of test runs in last hour! ({} ipv4 'ups', {} ipv6 'ups' for {} test runs)",
ipv4_hour_up,
ipv6_hour_up,
last_hour_test_runs,
);
ipv4_hour_up = min(ipv4_hour_up, last_hour_test_runs);
ipv6_hour_up = min(ipv6_hour_up, last_hour_test_runs);
}
if ipv4_day_up > last_day_test_runs || ipv6_day_up > last_day_test_runs {
let last_day_sum: f32 = if last_day.len() > last_day_test_runs {
warn!(
"We have more 'up' reports than the actual number of test runs in last day! ({} ipv4 'ups', {} ipv6 'ups' for {} test runs)",
ipv4_day_up,
ipv6_day_up,
"We have more reports than the actual number of test runs in last day! ({} reports for {} test runs)",
last_day.len(),
last_day_test_runs,
);
ipv4_day_up = min(ipv4_day_up, last_day_test_runs);
ipv6_day_up = min(ipv6_day_up, last_day_test_runs);
}
last_day
.iter()
.take(last_day_test_runs)
.map(|report| report.reliability as f32)
.sum()
} else {
// we average over expected number of test runs so if a node was not online for some of them
// it's treated as if it had a "zero" status.
last_day
.iter()
.map(|report| report.reliability as f32)
.sum()
};
let last_hour_reports = last_day
.iter()
.filter(|report| report.timestamp >= hour_ago)
.count();
let last_hour_sum: f32 = if last_hour_reports > last_hour_test_runs {
warn!(
"We have more reports than the actual number of test runs in last hour! ({} reports for {} test runs)",
last_hour_reports,
last_hour_test_runs,
);
last_day
.iter()
.filter(|report| report.timestamp >= hour_ago)
.take(last_hour_test_runs)
.map(|report| report.reliability as f32)
.sum()
} else {
last_day
.iter()
.filter(|report| report.timestamp >= hour_ago)
.map(|report| report.reliability as f32)
.sum()
};
// find the most recent
let most_recent_report = last_day.iter().max_by_key(|report| report.timestamp);
let most_recent = if let Some(most_recent_report) = most_recent_report {
// make sure its within last 15min
if most_recent_report.timestamp >= fifteen_minutes_ago {
most_recent_report.reliability
} else {
0
}
} else {
0
};
// the unwraps in Uptime::from_ratio are fine because it's impossible for us to have more "up" results
// than total test runs as we just bounded them
NodeUptimes {
most_recent_ipv4,
most_recent_ipv6,
last_hour_ipv4: Uptime::from_ratio(ipv4_hour_up, last_hour_test_runs).unwrap(),
last_hour_ipv6: Uptime::from_ratio(ipv6_hour_up, last_hour_test_runs).unwrap(),
last_day_ipv4: Uptime::from_ratio(ipv4_day_up, last_day_test_runs).unwrap(),
last_day_ipv6: Uptime::from_ratio(ipv6_day_up, last_day_test_runs).unwrap(),
most_recent: most_recent.try_into().unwrap(),
last_hour: Uptime::from_uptime_sum(last_hour_sum, last_hour_test_runs).unwrap(),
last_day: Uptime::from_uptime_sum(last_day_sum, last_hour_test_runs).unwrap(),
}
}
}