From ac304b436bff3cf065977535c8a66527f3cb4eb2 Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Mon, 1 May 2023 13:22:30 +0000 Subject: [PATCH] Checkpoint before I rearrange some things for efficiency. --- .../lts_node/src/web/wss/mod.rs | 15 ++- .../lts_node/src/web/wss/queries/mod.rs | 4 +- .../src/web/wss/queries/site_heat_map.rs | 105 ++++++++++++++++++ .../long_term_stats/site_build/src/bus.ts | 4 + .../site_build/src/components/root_heat.ts | 17 +++ .../site_build/src/dashboard/dashboard.ts | 6 +- .../site_build/src/dashboard/template.html | 10 ++ 7 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/rust/long_term_stats/lts_node/src/web/wss/queries/site_heat_map.rs create mode 100644 src/rust/long_term_stats/site_build/src/components/root_heat.ts diff --git a/src/rust/long_term_stats/lts_node/src/web/wss/mod.rs b/src/rust/long_term_stats/lts_node/src/web/wss/mod.rs index 045a761b..cc717050 100644 --- a/src/rust/long_term_stats/lts_node/src/web/wss/mod.rs +++ b/src/rust/long_term_stats/lts_node/src/web/wss/mod.rs @@ -1,5 +1,5 @@ use crate::web::wss::queries::{ - send_packets_for_all_nodes, send_rtt_for_all_nodes, send_throughput_for_all_nodes, send_packets_for_node, send_throughput_for_node, send_rtt_for_node, send_perf_for_node, omnisearch, + send_packets_for_all_nodes, send_rtt_for_all_nodes, send_throughput_for_all_nodes, send_packets_for_node, send_throughput_for_node, send_rtt_for_node, send_perf_for_node, omnisearch, root_heat_map, }; use axum::{ extract::{ @@ -179,6 +179,19 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool) { ).await; } } + "siteRootHeat" => { + if let Some(credentials) = &credentials { + let _ = root_heat_map( + cnn.clone(), + &mut socket, + &credentials.license_key, + period, + ) + .await; + } else { + log::info!("Throughput requested but no credentials provided"); + } + } _ => { log::warn!("Unknown message type: {msg_type}"); } diff --git a/src/rust/long_term_stats/lts_node/src/web/wss/queries/mod.rs b/src/rust/long_term_stats/lts_node/src/web/wss/queries/mod.rs index fb3ad132..0a650105 100644 --- a/src/rust/long_term_stats/lts_node/src/web/wss/queries/mod.rs +++ b/src/rust/long_term_stats/lts_node/src/web/wss/queries/mod.rs @@ -6,9 +6,11 @@ mod throughput; mod rtt; mod node_perf; mod search; +mod site_heat_map; pub mod time_period; pub use packet_counts::{ send_packets_for_all_nodes, send_packets_for_node }; pub use throughput::{ send_throughput_for_all_nodes, send_throughput_for_node }; pub use rtt::{ send_rtt_for_all_nodes, send_rtt_for_node }; pub use node_perf::send_perf_for_node; -pub use search::omnisearch; \ No newline at end of file +pub use search::omnisearch; +pub use site_heat_map::root_heat_map; \ No newline at end of file diff --git a/src/rust/long_term_stats/lts_node/src/web/wss/queries/site_heat_map.rs b/src/rust/long_term_stats/lts_node/src/web/wss/queries/site_heat_map.rs new file mode 100644 index 00000000..a50369af --- /dev/null +++ b/src/rust/long_term_stats/lts_node/src/web/wss/queries/site_heat_map.rs @@ -0,0 +1,105 @@ +use super::time_period::InfluxTimePeriod; +use crate::submissions::get_org_details; +use axum::extract::ws::{WebSocket, Message}; +use chrono::{DateTime, FixedOffset, Utc}; +use influxdb2::Client; +use influxdb2::{models::Query, FromDataPoint}; +use pgdb::sqlx::{query, Pool, Postgres, Row}; +use serde::Serialize; +use std::collections::HashMap; + +pub async fn root_heat_map( + cnn: Pool, + socket: &mut WebSocket, + key: &str, + period: InfluxTimePeriod, +) -> anyhow::Result<()> { + if let Some(org) = get_org_details(cnn.clone(), key).await { + let influx_url = format!("http://{}:8086", org.influx_host); + let client = Client::new(influx_url, &org.influx_org, &org.influx_token); + + // Get sites where parent=0 (for this setup) + let hosts: Vec = query("SELECT DISTINCT site_name FROM site_tree WHERE key=$1 AND parent=0 AND site_type='site'") + .bind(key) + .fetch_all(&cnn) + .await? + .iter() + .map(|row| row.try_get("site_name").unwrap()) + .collect(); + + let mut host_filter = "filter(fn: (r) => ".to_string(); + for host in hosts.iter() { + host_filter += &format!("r[\"node_name\"] == \"{host}\" or "); + } + host_filter = host_filter[0..host_filter.len() - 4].to_string(); + host_filter += ")"; + + // Query influx for RTT averages + let qs = format!( + "from(bucket: \"{}\") + |> {} + |> filter(fn: (r) => r[\"_measurement\"] == \"tree\") + |> filter(fn: (r) => r[\"organization_id\"] == \"{}\") + |> filter(fn: (r) => r[\"_field\"] == \"rtt_avg\") + |> {} + |> {} + |> yield(name: \"last\")", + org.influx_bucket, + period.range(), + org.key, + host_filter, + period.aggregate_window() + ); + println!("{qs}"); + + let query = Query::new(qs); + let rows = client.query::(Some(query)).await; + match rows { + Err(e) => { + tracing::error!("Error querying InfluxDB: {}", e); + return Err(anyhow::Error::msg("Unable to query influx")); + } + Ok(rows) => { + let mut sorter: HashMap, f64)>> = HashMap::new(); + for row in rows.iter() { + if let Some(hat) = sorter.get_mut(&row.node_name) { + hat.push((row.time, row.rtt_avg)); + } else { + sorter.insert(row.node_name.clone(), vec![(row.time, row.rtt_avg)]); + } + } + let msg = HeatMessage { + msg: "rootHeat".to_string(), + data: sorter, + }; + let json = serde_json::to_string(&msg).unwrap(); + socket.send(Message::Text(json)).await.unwrap(); + } + } + } + + Ok(()) +} + +#[derive(Serialize)] +struct HeatMessage { + msg: String, + data: HashMap, f64)>>, +} + +#[derive(Debug, FromDataPoint)] +pub struct HeatRow { + pub node_name: String, + pub rtt_avg: f64, + pub time: DateTime, +} + +impl Default for HeatRow { + fn default() -> Self { + Self { + node_name: "".to_string(), + rtt_avg: 0.0, + time: DateTime::::MIN_UTC.into(), + } + } +} diff --git a/src/rust/long_term_stats/site_build/src/bus.ts b/src/rust/long_term_stats/site_build/src/bus.ts index 5262c454..226b449e 100644 --- a/src/rust/long_term_stats/site_build/src/bus.ts +++ b/src/rust/long_term_stats/site_build/src/bus.ts @@ -115,6 +115,10 @@ export class Bus { this.ws.send(json); } + requestSiteRootHeat() { + this.ws.send("{ \"msg\": \"siteRootHeat\", \"period\": \"" + window.graphPeriod + "\" }"); + } + sendSearch(term: string) { let request = { msg: "search", diff --git a/src/rust/long_term_stats/site_build/src/components/root_heat.ts b/src/rust/long_term_stats/site_build/src/components/root_heat.ts new file mode 100644 index 00000000..895f7e2a --- /dev/null +++ b/src/rust/long_term_stats/site_build/src/components/root_heat.ts @@ -0,0 +1,17 @@ +import { Component } from "./component"; + +export class RootHeat implements Component { + wireup(): void { + + } + + ontick(): void { + window.bus.requestSiteRootHeat(); + } + + onmessage(event: any): void { + if (event.msg == "rootHeat") { + console.log(event); + } + } +} \ No newline at end of file diff --git a/src/rust/long_term_stats/site_build/src/dashboard/dashboard.ts b/src/rust/long_term_stats/site_build/src/dashboard/dashboard.ts index ac7c2397..448be514 100644 --- a/src/rust/long_term_stats/site_build/src/dashboard/dashboard.ts +++ b/src/rust/long_term_stats/site_build/src/dashboard/dashboard.ts @@ -7,6 +7,7 @@ import { PacketsChart } from '../components/packets'; import { ThroughputChart } from '../components/throughput'; import { RttChart } from '../components/rtt_graph'; import { RttHisto } from '../components/rtt_histo'; +import { RootHeat } from '../components/root_heat'; export class DashboardPage implements Page { menu: MenuPage; @@ -24,13 +25,14 @@ export class DashboardPage implements Page { new ThroughputChart(), new RttChart(), new RttHisto(), + new RootHeat(), ]; } wireup() { this.components.forEach(component => { component.wireup(); - }); + }); } ontick(): void { @@ -46,7 +48,7 @@ export class DashboardPage implements Page { this.components.forEach(component => { component.onmessage(event); - }); + }); } } } \ No newline at end of file diff --git a/src/rust/long_term_stats/site_build/src/dashboard/template.html b/src/rust/long_term_stats/site_build/src/dashboard/template.html index 5aa15eb7..cbc12ea8 100644 --- a/src/rust/long_term_stats/site_build/src/dashboard/template.html +++ b/src/rust/long_term_stats/site_build/src/dashboard/template.html @@ -39,4 +39,14 @@ + +
+
+
+
+
+
+
+
+