mirror of
https://github.com/4cuck/nitter-status.git
synced 2026-10-26 00:52:25 +00:00
per-host health graph with response times
This commit is contained in:
1 parent
7b736f09bf
commit
7d044b998d
2 files changed
+42
-7
No files matched your search
@@ -4,8 +4,6 @@ use sea_orm::{entity::prelude::*, FromQueryResult};
|
|||||||
use sea_query::{Alias, Order, Query, SimpleExpr};
|
use sea_query::{Alias, Order, Query, SimpleExpr};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::check_errors;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize)]
|
||||||
#[sea_orm(table_name = "health_check")]
|
#[sea_orm(table_name = "health_check")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
@@ -78,6 +76,35 @@ impl HealthyAmount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, FromQueryResult, Serialize)]
|
||||||
|
pub struct ResponseTimeStat {
|
||||||
|
pub time: i64,
|
||||||
|
pub resp_time: Option<i64>,
|
||||||
|
pub healthy: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseTimeStat {
|
||||||
|
/// Fetch the response time + alive for a host in the specified from - to region or over all time
|
||||||
|
pub async fn fetch(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
from: Option<DateTimeUtc>,
|
||||||
|
to: Option<DateTimeUtc>,
|
||||||
|
host: i32,
|
||||||
|
) -> Result<Vec<Self>, DbErr> {
|
||||||
|
let builder = db.get_database_backend();
|
||||||
|
let mut stmt: sea_query::SelectStatement = Query::select();
|
||||||
|
stmt.column(self::Column::Time)
|
||||||
|
.column(self::Column::Healthy)
|
||||||
|
.column(self::Column::RespTime)
|
||||||
|
.and_where(self::Column::Host.eq(host))
|
||||||
|
.from(self::Entity);
|
||||||
|
if let (Some(from), Some(to)) = (from, to) {
|
||||||
|
stmt.and_where(self::Column::Time.between(from.timestamp(), to.timestamp()));
|
||||||
|
}
|
||||||
|
Self::find_by_statement(builder.build(&stmt)).all(db).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use chrono::{TimeZone, Utc};
|
use chrono::{TimeZone, Utc};
|
||||||
use entities::{
|
use entities::{
|
||||||
health_check,
|
health_check::{self, ResponseTimeStat},
|
||||||
host_overrides::{
|
host_overrides::{
|
||||||
self,
|
self,
|
||||||
keys::{HostOverrides, LOCKED_FALSE, LOCKED_TRUE},
|
keys::{HostOverrides, LOCKED_FALSE, LOCKED_TRUE},
|
||||||
@@ -45,20 +45,28 @@ pub async fn health_csv_api(
|
|||||||
session: Session,
|
session: Session,
|
||||||
) -> Result<axum::response::Response> {
|
) -> Result<axum::response::Response> {
|
||||||
let (host, _login) = get_specific_login_host(instance, &session, db).await?;
|
let (host, _login) = get_specific_login_host(instance, &session, db).await?;
|
||||||
// TODO: Fetch request times and show an additional(?) red dot for failed requests"
|
// Nächstes mal:
|
||||||
|
// Fetch request times and show an additional(?) red dot for failed requests"
|
||||||
|
// Siehe globale? API mit response times
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
let healthy_data = health_check::HealthyAmount::fetch(db, None, None, Some(&[host.id])).await?;
|
let healthy_data = ResponseTimeStat::fetch(db, None, None, host.id).await?;
|
||||||
let queried = std::time::Instant::now();
|
let queried = std::time::Instant::now();
|
||||||
let mut data = String::with_capacity((4 + 3 + 3 + 3 + 3 + 3 + 4) * healthy_data.len());
|
let mut data = String::with_capacity((4 + 3 + 3 + 3 + 3 + 3 + 4) * healthy_data.len());
|
||||||
|
|
||||||
data.push_str("Date,Healthy,Dead\n");
|
data.push_str("Date,Healthy Rsp Time,Dead Rsp Time\n");
|
||||||
|
|
||||||
for entry in healthy_data {
|
for entry in healthy_data {
|
||||||
let time = Utc
|
let time = Utc
|
||||||
.timestamp_opt(entry.time, 0)
|
.timestamp_opt(entry.time, 0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.format("%Y-%m-%dT%H:%M:%SZ");
|
.format("%Y-%m-%dT%H:%M:%SZ");
|
||||||
writeln!(&mut data, "{time},{},{}", entry.alive, entry.dead)
|
let (rsp_healthy, rsp_dead) = match (entry.resp_time, entry.healthy) {
|
||||||
|
(None, true) => (-1, 0), // no respons etime but healthy/unhealthy
|
||||||
|
(None, false) => (0, -1), // we don't really expect thse two cases and return -1
|
||||||
|
(Some(time), true) => (time, 0),
|
||||||
|
(Some(time), false) => (0, time),
|
||||||
|
};
|
||||||
|
writeln!(&mut data, "{time},{},{}", rsp_healthy, rsp_dead)
|
||||||
.map_err(|e| ServerError::CSV(e.to_string()))?;
|
.map_err(|e| ServerError::CSV(e.to_string()))?;
|
||||||
}
|
}
|
||||||
let formatted = std::time::Instant::now();
|
let formatted = std::time::Instant::now();
|
||||||
|
|||||||
Reference in new issue
Block a user