mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
RTT is per-host aware.
This commit is contained in:
parent
84a3709a59
commit
1e806ebdd9
@ -1,122 +0,0 @@
|
||||
use crate::submissions::get_org_details;
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use influxdb2::{models::Query, Client, FromDataPoint};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, FromDataPoint)]
|
||||
pub struct BitsAndPackets {
|
||||
direction: String,
|
||||
host_id: String,
|
||||
min: f64,
|
||||
max: f64,
|
||||
avg: f64,
|
||||
time: DateTime<FixedOffset>,
|
||||
}
|
||||
|
||||
impl Default for BitsAndPackets {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
direction: "".to_string(),
|
||||
host_id: "".to_string(),
|
||||
min: 0.0,
|
||||
max: 0.0,
|
||||
avg: 0.0,
|
||||
time: DateTime::<Utc>::MIN_UTC.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromDataPoint)]
|
||||
pub struct Rtt {
|
||||
host_id: String,
|
||||
min: f64,
|
||||
max: f64,
|
||||
avg: f64,
|
||||
time: DateTime<FixedOffset>,
|
||||
}
|
||||
|
||||
impl Default for Rtt {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
host_id: "".to_string(),
|
||||
min: 0.0,
|
||||
max: 0.0,
|
||||
avg: 0.0,
|
||||
time: DateTime::<Utc>::MIN_UTC.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Packets {
|
||||
value: f64,
|
||||
date: String,
|
||||
l: f64,
|
||||
u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct PacketChart {
|
||||
msg: String,
|
||||
down: Vec<Packets>,
|
||||
up: Vec<Packets>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct RttChart {
|
||||
msg: String,
|
||||
data: Vec<Packets>,
|
||||
histo: Vec<u64>,
|
||||
}
|
||||
|
||||
pub async fn rtt(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str) {
|
||||
if let Some(org) = get_org_details(cnn, key).await {
|
||||
let influx_url = format!("http://{}:8086", org.influx_host);
|
||||
let client = Client::new(influx_url, &org.influx_org, &org.influx_token);
|
||||
|
||||
let qs = format!(
|
||||
"from(bucket: \"{}\")
|
||||
|> range(start: -5m)
|
||||
|> filter(fn: (r) => r[\"_measurement\"] == \"rtt\")
|
||||
|> filter(fn: (r) => r[\"organization_id\"] == \"{}\")
|
||||
|> aggregateWindow(every: 10s, fn: mean, createEmpty: false)
|
||||
|> yield(name: \"last\")",
|
||||
org.influx_bucket, org.key
|
||||
);
|
||||
|
||||
let query = Query::new(qs);
|
||||
let rows = client.query::<Rtt>(Some(query)).await;
|
||||
match rows {
|
||||
Err(e) => {
|
||||
tracing::error!("Error querying InfluxDB: {}", e);
|
||||
}
|
||||
Ok(rows) => {
|
||||
// Parse and send the data
|
||||
//println!("{rows:?}");
|
||||
|
||||
let mut data = Vec::new();
|
||||
let mut histo = vec![0; 20];
|
||||
|
||||
for row in rows
|
||||
.iter()
|
||||
{
|
||||
data.push(Packets {
|
||||
value: row.avg,
|
||||
date: row.time.format("%H:%M:%S").to_string(),
|
||||
l: row.min,
|
||||
u: row.max - row.min,
|
||||
});
|
||||
let bucket = u64::min(19, (row.avg / 200.0) as u64);
|
||||
histo[bucket as usize] += 1;
|
||||
}
|
||||
|
||||
// Send it
|
||||
let chart = RttChart { msg: "rttChart".to_string(), data, histo };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,10 +4,9 @@ use axum::{
|
||||
};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde_json::Value;
|
||||
use crate::web::wss::queries::{send_packets_for_all_nodes, send_throughput_for_all_nodes};
|
||||
use crate::web::wss::queries::{send_packets_for_all_nodes, send_throughput_for_all_nodes, send_rtt_for_all_nodes};
|
||||
mod login;
|
||||
mod nodes;
|
||||
mod dashboard;
|
||||
mod queries;
|
||||
|
||||
pub async fn ws_handler(ws: WebSocketUpgrade, State(state): State<Pool<Postgres>>) -> impl IntoResponse {
|
||||
@ -69,7 +68,7 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool<Postgres>) {
|
||||
}
|
||||
"rttChart" => {
|
||||
if let Some(credentials) = &credentials {
|
||||
dashboard::rtt(cnn.clone(), &mut socket, &credentials.license_key).await;
|
||||
let _ = send_rtt_for_all_nodes(cnn.clone(), &mut socket, &credentials.license_key).await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
|
@ -3,5 +3,7 @@
|
||||
|
||||
mod packet_counts;
|
||||
mod throughput;
|
||||
mod rtt;
|
||||
pub use packet_counts::send_packets_for_all_nodes;
|
||||
pub use throughput::send_throughput_for_all_nodes;
|
||||
pub use throughput::send_throughput_for_all_nodes;
|
||||
pub use rtt::send_rtt_for_all_nodes;
|
@ -61,7 +61,7 @@ export class PacketsChart implements Component {
|
||||
type: "line",
|
||||
data: u,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band' + node.node_id,
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
@ -105,7 +105,7 @@ export class PacketsChart implements Component {
|
||||
type: "line",
|
||||
data: u,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band' + node.node_id,
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
@ -125,7 +125,6 @@ export class PacketsChart implements Component {
|
||||
series.push(val);
|
||||
}
|
||||
|
||||
|
||||
if (!this.chartMade) {
|
||||
this.myChart.hideLoading();
|
||||
var option: echarts.EChartsOption;
|
||||
|
@ -5,10 +5,6 @@ import * as echarts from 'echarts';
|
||||
export class RttChart implements Component {
|
||||
div: HTMLElement;
|
||||
myChart: echarts.ECharts;
|
||||
download: any;
|
||||
downloadMin: any;
|
||||
downloadMax: any;
|
||||
x: any;
|
||||
chartMade: boolean = false;
|
||||
|
||||
constructor() {
|
||||
@ -26,16 +22,62 @@ export class RttChart implements Component {
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChart") {
|
||||
//console.log(event);
|
||||
this.download = [];
|
||||
this.downloadMin = [];
|
||||
this.downloadMax = [];
|
||||
this.x = [];
|
||||
for (let i = 0; i < event.data.length; i++) {
|
||||
this.download.push(event.data[i].value);
|
||||
this.downloadMin.push(event.data[i].l);
|
||||
this.downloadMax.push(event.data[i].u);
|
||||
this.x.push(event.data[i].date);
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
// providing upload and download banding per node.
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
let d: number[] = [];
|
||||
let u: number[] = [];
|
||||
let l: number[] = [];
|
||||
for (let j=0; j<node.rtt.length; j++) {
|
||||
if (first) x.push(node.rtt[j].date);
|
||||
d.push(node.rtt[j].value);
|
||||
u.push(node.rtt[j].u);
|
||||
l.push(node.rtt[j].l);
|
||||
}
|
||||
if (first) first = false;
|
||||
|
||||
let min: echarts.SeriesOption = {
|
||||
name: "L",
|
||||
type: "line",
|
||||
data: l,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
};
|
||||
let max: echarts.SeriesOption = {
|
||||
name: "U",
|
||||
type: "line",
|
||||
data: u,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
areaStyle: {
|
||||
color: '#ccc'
|
||||
},
|
||||
};
|
||||
let val: echarts.SeriesOption = {
|
||||
name: node.node_name,
|
||||
type: "line",
|
||||
data: d,
|
||||
symbol: 'none',
|
||||
};
|
||||
|
||||
series.push(min);
|
||||
series.push(max);
|
||||
series.push(val);
|
||||
}
|
||||
|
||||
if (!this.chartMade) {
|
||||
@ -44,48 +86,21 @@ export class RttChart implements Component {
|
||||
this.myChart.setOption<echarts.EChartsOption>(
|
||||
(option = {
|
||||
title: { text: "TCP Round-Trip Time" },
|
||||
legend: {
|
||||
orient: "horizontal",
|
||||
right: 10,
|
||||
top: "bottom",
|
||||
data: legend,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: this.x,
|
||||
data: x,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: 'ms',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "L",
|
||||
type: "line",
|
||||
data: this.downloadMin,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band',
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "U",
|
||||
type: "line",
|
||||
data: this.downloadMax,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band',
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
areaStyle: {
|
||||
color: '#ccc'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Download",
|
||||
type: "line",
|
||||
data: this.download,
|
||||
symbol: 'none',
|
||||
itemStyle: {
|
||||
color: '#333'
|
||||
},
|
||||
},
|
||||
]
|
||||
series: series
|
||||
})
|
||||
);
|
||||
option && this.myChart.setOption(option);
|
||||
|
@ -26,8 +26,8 @@ export class RttHisto implements Component {
|
||||
//console.log(event);
|
||||
this.download = [];
|
||||
this.x = [];
|
||||
for (let i = 0; i < event.histo.length; i++) {
|
||||
this.download.push(event.histo[i]);
|
||||
for (let i = 0; i < event.histogram.length; i++) {
|
||||
this.download.push(event.histogram[i]);
|
||||
this.x.push(i * 10);
|
||||
}
|
||||
|
||||
@ -50,9 +50,6 @@ export class RttHisto implements Component {
|
||||
name: "RTT",
|
||||
type: "bar",
|
||||
data: this.download,
|
||||
itemStyle: {
|
||||
color: '#333'
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
|
@ -61,7 +61,7 @@ export class ThroughputChart implements Component {
|
||||
type: "line",
|
||||
data: u,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band' + node.node_id,
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
@ -105,7 +105,7 @@ export class ThroughputChart implements Component {
|
||||
type: "line",
|
||||
data: u,
|
||||
symbol: 'none',
|
||||
stack: 'confidence-band' + node.node_id,
|
||||
stack: 'confidence-band-' + node.node_id,
|
||||
lineStyle: {
|
||||
opacity: 0
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user