mirror of
https://github.com/4cuck/nitter-status.git
synced 2026-10-27 00:57:39 +00:00
render missing entries
This commit is contained in:
1 parent
29489b5618
commit
660da56c3f
5 files changed
+73
-44
No files matched your search
+1
-1
@@ -27,4 +27,4 @@ REFERER="https://localhost"
|
||||
# Ping AVG period in hours
|
||||
PING_RANGE_H="3"
|
||||
# enable/disable startup scanning
|
||||
#DISABLE_STARTUP_SCAN=true
|
||||
DISABLE_STARTUP_SCAN=false
|
||||
@@ -30,9 +30,9 @@ pub struct CacheHost {
|
||||
pub domain: String,
|
||||
pub points: i32,
|
||||
pub rss: bool,
|
||||
pub recent_pings: Vec<i32>,
|
||||
pub ping_max: i32,
|
||||
pub ping_min: i32,
|
||||
pub recent_pings: Vec<Option<i32>>,
|
||||
pub ping_max: Option<i32>,
|
||||
pub ping_min: Option<i32>,
|
||||
pub ping_avg: Option<i32>,
|
||||
pub version: Option<String>,
|
||||
pub healthy: bool,
|
||||
|
||||
+30
-22
@@ -39,10 +39,12 @@ pub struct LastPingsQuery {
|
||||
ping: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
struct LastPings {
|
||||
avg: i32,
|
||||
pings: Vec<i32>,
|
||||
avg: Option<i32>,
|
||||
min: Option<i32>,
|
||||
max: Option<i32>,
|
||||
pings: Vec<Option<i32>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, FromQueryResult)]
|
||||
@@ -123,9 +125,9 @@ impl Scanner {
|
||||
rss: host.rss,
|
||||
version: host.version,
|
||||
healthy: last_check.healthy,
|
||||
ping_max: host_ping_data.as_ref().and_then(|v|v.pings.iter().max().cloned()).unwrap_or(0i32),
|
||||
ping_min: host_ping_data.as_ref().and_then(|v|v.pings.iter().min().cloned()).unwrap_or(0i32),
|
||||
ping_avg: host_ping_data.as_ref().map(|v|v.avg),
|
||||
ping_max: host_ping_data.as_ref().and_then(|v|v.max),
|
||||
ping_min: host_ping_data.as_ref().and_then(|v|v.min),
|
||||
ping_avg: host_ping_data.as_ref().and_then(|v|v.avg),
|
||||
recent_pings: host_ping_data.map(|v|v.pings).unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
@@ -149,15 +151,15 @@ impl Scanner {
|
||||
#[derive(Debug, FromQueryResult, Default)]
|
||||
struct PingEntry {
|
||||
host: i32,
|
||||
ping: i32,
|
||||
ping: Option<i32>,
|
||||
}
|
||||
let last_pings = PingEntry::find_by_statement(Statement::from_sql_and_values(
|
||||
DbBackend::Sqlite,
|
||||
r#"
|
||||
SELECT u.host,u.resp_time as ping FROM update_check u
|
||||
SELECT u.host,(CASE u.healthy WHEN true THEN u.resp_time ELSE null END) as ping FROM update_check u
|
||||
JOIN host h ON h.id = u.host
|
||||
WHERE h.enabled = true AND u.healthy = true AND u.time >= $1
|
||||
ORDER BY u.host,u.time DESC
|
||||
WHERE h.enabled = true AND u.time >= $1
|
||||
ORDER BY u.host,u.time ASC
|
||||
"#,
|
||||
[age.into()],
|
||||
))
|
||||
@@ -169,31 +171,37 @@ impl Scanner {
|
||||
None => {return Ok(HashMap::new());},
|
||||
Some(v) => v,
|
||||
};
|
||||
let mut current_entry = LastPings {
|
||||
pings: Vec::new(),// TODO: optimize capacity
|
||||
avg: 0,
|
||||
};
|
||||
let mut current_entry = LastPings::default();
|
||||
let mut last_host = first.host;
|
||||
let mut non_null_entries = first.ping.as_ref().map_or(0, |_|1);
|
||||
current_entry.pings.push(first.ping);
|
||||
for ping in iter {
|
||||
if last_host != ping.host {
|
||||
let mut new_entry = LastPings{
|
||||
avg: 0,
|
||||
pings: Vec::new(),
|
||||
};
|
||||
let mut new_entry = LastPings::default();
|
||||
// will overflow only if we hit > 1500 days of backlog
|
||||
// when having 5 minutes interval and only 5000ms response times
|
||||
current_entry.avg = (current_entry.pings.iter().copied().sum::<i32>() / (current_entry.pings.len() as i32) ) as i32;
|
||||
if let Some(sum) = current_entry.avg {
|
||||
current_entry.avg = Some(sum / non_null_entries);
|
||||
}
|
||||
non_null_entries = 0;
|
||||
std::mem::swap(&mut new_entry, &mut current_entry);
|
||||
// insert back the old (swapped) entry
|
||||
assert_eq!(map.insert(last_host, new_entry).is_some(),false);
|
||||
last_host = ping.host;
|
||||
}
|
||||
if let Some(ping) = ping.ping.as_ref() {
|
||||
current_entry.avg = Some(current_entry.avg.unwrap_or(0) + ping);
|
||||
non_null_entries += 1;
|
||||
current_entry.min = Some(current_entry.min.map_or(*ping,|v|v.min(*ping)));
|
||||
current_entry.max = Some(current_entry.max.map_or(*ping,|v|v.max(*ping)));
|
||||
}
|
||||
current_entry.pings.push(ping.ping);
|
||||
}
|
||||
// Insert last one
|
||||
current_entry.avg = (current_entry.pings.iter().copied().sum::<i32>() / (current_entry.pings.len() as i32) ) as i32;
|
||||
map.insert(last_host, current_entry);
|
||||
// Insert last entry
|
||||
if let Some(sum) = current_entry.avg {
|
||||
current_entry.avg = Some(sum / non_null_entries);
|
||||
}
|
||||
assert_eq!(map.insert(last_host, current_entry).is_some(),false);
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ pub async fn instances(
|
||||
context.insert("instances", &guard.hosts);
|
||||
let time = guard.last_update.format("%Y.%m.%d %H:%M").to_string();
|
||||
context.insert("last_updated", &time);
|
||||
|
||||
let res = Html(template.render("instances.html.j2", &context)?).into_response();
|
||||
drop(guard);
|
||||
res
|
||||
|
||||
@@ -26,34 +26,56 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for host in instances %}
|
||||
{% for host in instances -%}
|
||||
<tr>
|
||||
<td><a href="{{host.url}}">{{host.domain}}</a></td>
|
||||
<td>{% if host.healthy%} ✅ {% else %} ❌ {% endif %}</td>
|
||||
<td>{% if host.healthy -%} ✅ {% else -%} ❌ {% endif -%}</td>
|
||||
<td>
|
||||
{% if host.recent_pings|length > 0 %}
|
||||
{% set height = 57 %}
|
||||
{% set width = 182 %}
|
||||
{% set amount = host.recent_pings|length %}
|
||||
{% set width_bar = width / amount %}
|
||||
{% set offset = 5 %}
|
||||
{% set step_size = (host.ping_max - host.ping_min)/(height-offset) %}
|
||||
{% if host.recent_pings|length > 0 -%}
|
||||
{% set height = 57 -%}
|
||||
{% set width = 182 -%}
|
||||
{% set amount = host.recent_pings|length -%}
|
||||
{% set width_bar = width / amount -%}
|
||||
{% set offset = 5 -%}
|
||||
{% set error_size = height / 3 %}
|
||||
{% if host.ping_max and host.ping_min -%}
|
||||
{# only one entry, so max = min => step_size would be 0 #}
|
||||
{% if host.ping_max == host.ping_min -%}
|
||||
{% set step_size = 5/(height-offset) -%}
|
||||
{% else -%}
|
||||
{% set step_size = (host.ping_max - host.ping_min)/(height-offset) -%}
|
||||
{% endif -%}
|
||||
{% else %}
|
||||
{# no valid entries, only nulls #}
|
||||
{% set step_size = 5/(height-offset) -%}
|
||||
{% endif %}
|
||||
{# <!-- step size {{step_size}} -->
|
||||
<!-- ping_max {{host.ping_max}} -->
|
||||
<!-- ping_min {{host.ping_min}} --> #}
|
||||
<svg viewBox="0 0 182 56" width="{{width - 1}}" height="{{height - 1}}">
|
||||
{% set avg_pos = (height-(host.ping_avg - host.ping_min )/step_size) - offset %}
|
||||
<line x1="1" x2="181" y1="{{avg_pos}}" y2="{{avg_pos}}" stroke="black" stroke-width="0.72727275" stroke-linecap="butt" stroke-opacity="0.3"><title>Average</title></line>
|
||||
{% for ping in host.recent_pings %}
|
||||
{% set height_bar = (ping - host.ping_min )/step_size + offset%}
|
||||
<rect x="{{(loop.index-1) * width_bar}}" y="{{height - height_bar - offset}}" width="{{width_bar}}" height="{{height_bar}}" fill="#a09df2" fill-opacity="0.95"><title>{{ping}}</title></rect>
|
||||
{% endfor %}
|
||||
{% if host.ping_avg and host.ping_min -%}
|
||||
{% set avg_pos = (height-(host.ping_avg - host.ping_min )/step_size) - offset -%}
|
||||
<line x1="1" x2="181" y1="{{avg_pos}}" y2="{{avg_pos}}" stroke="black" stroke-width="0.72727275" stroke-linecap="butt" stroke-opacity="0.3"><title>Average</title></line>
|
||||
{% endif -%}
|
||||
{% for ping in host.recent_pings -%}
|
||||
{% if ping -%}
|
||||
{% set height_bar = (ping - host.ping_min )/step_size + offset -%}
|
||||
{% set color_bar = "#a09df2" -%}
|
||||
{% else %}
|
||||
{% set height_bar = error_size -%}
|
||||
{% set color_bar = "#cc0000" -%}
|
||||
{% endif %}
|
||||
<rect x="{{(loop.index-1) * width_bar}}" y="{{height - height_bar - offset}}" width="{{width_bar}}" height="{{height_bar}}" fill="{{color_bar}}" fill-opacity="0.95"><title>{{ping | default(value="unhealthy") }}</title></rect>
|
||||
{% endfor -%}
|
||||
</svg>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{host.ping_avg}}</td>
|
||||
<td>{% if host.rss%} ✅ {% else %} ❌ {% endif %}</td>
|
||||
<td>{% if host.rss -%} ✅ {% else %} ❌ {% endif %}</td>
|
||||
<td>{{host.version}}</td>
|
||||
<td>{{host.points}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user