mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
WASM-based websocket system, including compression and binary encoding.
This commit is contained in:
parent
423be6f1ed
commit
f41e9d7261
1
.gitignore
vendored
1
.gitignore
vendored
@ -62,6 +62,7 @@ src/rust/long_term_stats/pgdb/.env
|
||||
src/rust/long_term_stats/site_build/node_modules
|
||||
src/rust/long_term_stats/site_build/output
|
||||
src/rust/long_term_stats/site_build/package-lock.json
|
||||
src/rust/long_term_stats/wasm_pipe/staging
|
||||
|
||||
# Ignore Rust build artifacts
|
||||
src/rust/target
|
||||
|
43
src/rust/Cargo.lock
generated
43
src/rust/Cargo.lock
generated
@ -2137,10 +2137,12 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber 0.3.17",
|
||||
"wasm_pipe_types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4306,9 +4308,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4"
|
||||
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@ -4316,9 +4318,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822"
|
||||
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@ -4343,9 +4345,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434"
|
||||
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -4353,9 +4355,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869"
|
||||
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4366,9 +4368,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
|
||||
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
@ -4383,6 +4385,27 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm_pipe"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"miniz_oxide",
|
||||
"serde_cbor",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm_pipe_types",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm_pipe_types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.62"
|
||||
|
@ -33,5 +33,7 @@ members = [
|
||||
"long_term_stats/pgdb", # PostgreSQL interface for the LTS system
|
||||
"long_term_stats/licman", # A CLI tool for managing the licensing server
|
||||
"long_term_stats/lts_client", # Shared data and client-side code for long-term stats
|
||||
"long_term_stats/wasm_pipe", # Provides a WebAssembly tight/compressed data pipeline
|
||||
"long_term_stats/wasm_pipe_types", # Common types between the WASM conduit and the WASM server
|
||||
"lqos_map_perf", # A CLI tool for testing eBPF map performance
|
||||
]
|
||||
|
@ -26,3 +26,5 @@ tower = { version = "0.4", features = ["util"] }
|
||||
tower-http = { version = "0.4.0", features = ["fs", "trace"] }
|
||||
chrono = "0"
|
||||
miniz_oxide = "0.7.1"
|
||||
tokio-util = { version = "0.7.8", features = ["io"] }
|
||||
wasm_pipe_types = { path = "../wasm_pipe_types" }
|
||||
|
@ -1,9 +1,13 @@
|
||||
#!/bin/bash
|
||||
pushd ../wasm_pipe
|
||||
./build.sh
|
||||
popd
|
||||
pushd ../site_build
|
||||
./esbuild.mjs
|
||||
popd
|
||||
pushd web
|
||||
cp ../../site_build/output/* .
|
||||
cp ../../site_build/src/main.html .
|
||||
cp ../../site_build/wasm/wasm_pipe_bg.wasm .
|
||||
popd
|
||||
RUST_LOG=warn RUST_BACKTRACE=1 cargo run
|
||||
RUST_LOG=info RUST_BACKTRACE=1 cargo run --release
|
||||
|
@ -3,9 +3,13 @@
|
||||
//! should provide HTTPS.
|
||||
mod wss;
|
||||
use crate::web::wss::ws_handler;
|
||||
use axum::body::StreamBody;
|
||||
use axum::http::{header, HeaderMap};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::{response::Html, routing::get, Router};
|
||||
use pgdb::sqlx::Pool;
|
||||
use pgdb::sqlx::Postgres;
|
||||
use tokio_util::io::ReaderStream;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tower_http::trace::DefaultMakeSpan;
|
||||
|
||||
@ -14,6 +18,7 @@ const JS_MAP: &str = include_str!("../../web/app.js.map");
|
||||
const CSS: &str = include_str!("../../web/style.css");
|
||||
const CSS_MAP: &str = include_str!("../../web/style.css.map");
|
||||
const HTML_MAIN: &str = include_str!("../../web/main.html");
|
||||
const WASM_BODY: &[u8] = include_bytes!("../../web/wasm_pipe_bg.wasm");
|
||||
|
||||
pub async fn webserver(cnn: Pool<Postgres>) {
|
||||
let app = Router::new()
|
||||
@ -23,6 +28,7 @@ pub async fn webserver(cnn: Pool<Postgres>) {
|
||||
.route("/style.css", get(css))
|
||||
.route("/style.css.map", get(css_map))
|
||||
.route("/ws", get(ws_handler))
|
||||
.route("/wasm_pipe_bg.wasm", get(wasm_file))
|
||||
.with_state(cnn)
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
@ -67,3 +73,20 @@ async fn css_map() -> axum::response::Response<String> {
|
||||
.body(CSS_MAP.to_string())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn wasm_file() -> impl IntoResponse {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
header::CONTENT_TYPE,
|
||||
header::HeaderValue::from_static("application/wasm"),
|
||||
);
|
||||
headers.insert(
|
||||
header::CONTENT_DISPOSITION,
|
||||
header::HeaderValue::from_static("attachment; filename=wasm_pipe_bg.wasm"),
|
||||
);
|
||||
axum::response::Response::builder()
|
||||
.header(header::CONTENT_TYPE, header::HeaderValue::from_static("application/wasm"))
|
||||
.header(header::CONTENT_DISPOSITION, header::HeaderValue::from_static("attachment; filename=wasm_pipe_bg.wasm"))
|
||||
.body(StreamBody::new(ReaderStream::new(WASM_BODY)))
|
||||
.unwrap()
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
use wasm_pipe_types::WasmResponse;
|
||||
|
||||
use super::send_response;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct LoginResult {
|
||||
@ -11,71 +13,45 @@ pub struct LoginResult {
|
||||
pub license_key: String,
|
||||
}
|
||||
|
||||
pub async fn on_login(json: &Value, socket: &mut WebSocket, cnn: Pool<Postgres>) -> Option<LoginResult> {
|
||||
if let (
|
||||
Some(Value::String(license)),
|
||||
Some(Value::String(username)),
|
||||
Some(Value::String(password)),
|
||||
) = (
|
||||
json.get("license"),
|
||||
json.get("username"),
|
||||
json.get("password"),
|
||||
) {
|
||||
let login = pgdb::try_login(cnn, license, username, password).await;
|
||||
if let Ok(login) = login {
|
||||
let lr = LoginResult {
|
||||
msg: "loginOk".to_string(),
|
||||
token: login.token,
|
||||
name: login.name,
|
||||
license_key: license.to_string(),
|
||||
};
|
||||
if let Ok(login) = serde_json::to_string(&lr) {
|
||||
let msg = Message::Text(login);
|
||||
socket.send(msg).await.unwrap();
|
||||
return Some(lr);
|
||||
}
|
||||
} else {
|
||||
let lr = LoginResult {
|
||||
msg: "loginFail".to_string(),
|
||||
token: String::new(),
|
||||
name: String::new(),
|
||||
license_key: license.to_string(),
|
||||
};
|
||||
if let Ok(login) = serde_json::to_string(&lr) {
|
||||
let msg = Message::Text(login);
|
||||
socket.send(msg).await.unwrap();
|
||||
}
|
||||
}
|
||||
pub async fn on_login(license: &str, username: &str, password: &str, socket: &mut WebSocket, cnn: Pool<Postgres>) -> Option<LoginResult> {
|
||||
let login = pgdb::try_login(cnn, license, username, password).await;
|
||||
if let Ok(login) = login {
|
||||
let lr = WasmResponse::LoginOk {
|
||||
token: login.token.clone(),
|
||||
name: login.name.clone(),
|
||||
license_key: license.to_string(),
|
||||
};
|
||||
send_response(socket, lr).await;
|
||||
return Some(LoginResult {
|
||||
msg: "Login Ok".to_string(),
|
||||
token: login.token.to_string(),
|
||||
name: login.name.to_string(),
|
||||
license_key: license.to_string(),
|
||||
});
|
||||
} else {
|
||||
let lr = WasmResponse::LoginFail;
|
||||
send_response(socket, lr).await;
|
||||
}
|
||||
None
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn on_token_auth(json: &Value, socket: &mut WebSocket, cnn: Pool<Postgres>) -> Option<LoginResult> {
|
||||
let token_id = json.get("token").unwrap().as_str().unwrap();
|
||||
pub async fn on_token_auth(token_id: &str, socket: &mut WebSocket, cnn: Pool<Postgres>) -> Option<LoginResult> {
|
||||
let login = pgdb::token_to_credentials(cnn, token_id).await;
|
||||
if let Ok(login) = login {
|
||||
let lr = LoginResult {
|
||||
msg: "authOk".to_string(),
|
||||
token: login.token,
|
||||
name: login.name,
|
||||
license_key: login.license,
|
||||
let lr = WasmResponse::AuthOk {
|
||||
token: login.token.clone(),
|
||||
name: login.name.clone(),
|
||||
license_key: login.license.clone(),
|
||||
};
|
||||
if let Ok(login) = serde_json::to_string(&lr) {
|
||||
let msg = Message::Text(login);
|
||||
socket.send(msg).await.unwrap();
|
||||
return Some(lr);
|
||||
}
|
||||
send_response(socket, lr).await;
|
||||
return Some(LoginResult {
|
||||
msg: "Login Ok".to_string(),
|
||||
token: login.token.to_string(),
|
||||
name: login.name.to_string(),
|
||||
license_key: login.license.to_string(),
|
||||
});
|
||||
} else {
|
||||
let lr = LoginResult {
|
||||
msg: "authFail".to_string(),
|
||||
token: String::new(),
|
||||
name: String::new(),
|
||||
license_key: String::new(),
|
||||
};
|
||||
if let Ok(login) = serde_json::to_string(&lr) {
|
||||
let msg = Message::Text(login);
|
||||
socket.send(msg).await.unwrap();
|
||||
}
|
||||
send_response(socket, WasmResponse::AuthFail).await;
|
||||
}
|
||||
None
|
||||
}
|
@ -3,17 +3,17 @@ use crate::web::wss::queries::{
|
||||
send_packets_for_node, send_perf_for_node, send_rtt_for_all_nodes, send_rtt_for_all_nodes_site,
|
||||
send_rtt_for_node, send_site_info, send_site_parents, send_throughput_for_all_nodes,
|
||||
send_throughput_for_all_nodes_by_site, send_throughput_for_node, site_heat_map,
|
||||
site_tree::send_site_tree, send_throughput_for_all_nodes_by_circuit, send_rtt_for_all_nodes_circuit, send_site_stack_map,
|
||||
site_tree::send_site_tree, send_throughput_for_all_nodes_by_circuit, send_rtt_for_all_nodes_circuit, send_site_stack_map, time_period::InfluxTimePeriod,
|
||||
};
|
||||
use axum::{
|
||||
extract::{
|
||||
ws::{WebSocket, WebSocketUpgrade},
|
||||
ws::{WebSocket, WebSocketUpgrade, Message},
|
||||
State,
|
||||
},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde_json::Value;
|
||||
use wasm_pipe_types::{WasmRequest, WasmResponse};
|
||||
mod login;
|
||||
mod nodes;
|
||||
mod queries;
|
||||
@ -31,8 +31,308 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool<Postgres>) {
|
||||
while let Some(msg) = socket.recv().await {
|
||||
let cnn = cnn.clone();
|
||||
let msg = msg.unwrap();
|
||||
|
||||
// Get the binary message and decompress it
|
||||
log::info!("Received a message: {:?}", msg);
|
||||
if let Ok(text) = msg.into_text() {
|
||||
let raw = msg.into_data();
|
||||
let uncompressed = miniz_oxide::inflate::decompress_to_vec(&raw).unwrap();
|
||||
let msg = lts_client::cbor::from_slice::<WasmRequest>(&uncompressed).unwrap();
|
||||
log::info!("{msg:?}");
|
||||
|
||||
// Update the token credentials (if there are any)
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = pgdb::refresh_token(cnn.clone(), &credentials.token).await;
|
||||
}
|
||||
|
||||
// Handle the message by type
|
||||
match msg {
|
||||
// Handle login with just a token
|
||||
WasmRequest::Auth { token } => {
|
||||
let result = login::on_token_auth(&token, &mut socket, cnn).await;
|
||||
if let Some(result) = result {
|
||||
credentials = Some(result);
|
||||
}
|
||||
}
|
||||
// Handle login with a username and password
|
||||
WasmRequest::Login { license, username, password } => {
|
||||
let result = login::on_login(&license, &username, &password, &mut socket, cnn).await;
|
||||
if let Some(result) = result {
|
||||
credentials = Some(result);
|
||||
}
|
||||
}
|
||||
// Node status for dashboard
|
||||
WasmRequest::GetNodeStatus => {
|
||||
if let Some(credentials) = &credentials {
|
||||
nodes::node_status(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Node status requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Packet chart for dashboard
|
||||
WasmRequest::PacketChart { period } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_packets_for_all_nodes(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Packet chart for individual node
|
||||
WasmRequest::PacketChartSingle { period, node_id, node_name } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_packets_for_node(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
node_id,
|
||||
node_name,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Throughput chart for the dashboard
|
||||
WasmRequest::ThroughputChart { period } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_throughput_for_all_nodes(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Throughput chart for a single shaper node
|
||||
WasmRequest::ThroughputChartSingle { period, node_id, node_name } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_throughput_for_node(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
node_id,
|
||||
node_name,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
},
|
||||
WasmRequest::ThroughputChartSite { period, site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_throughput_for_all_nodes_by_site(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
site_id,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
WasmRequest::ThroughputChartCircuit { period, circuit_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_throughput_for_all_nodes_by_circuit(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
circuit_id,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Rtt Chart
|
||||
WasmRequest::RttChart { period } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_rtt_for_all_nodes(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
WasmRequest::RttChartSite { period, site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_rtt_for_all_nodes_site(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
site_id,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
WasmRequest::RttChartSingle { period, node_id, node_name } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_rtt_for_node(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
node_id,
|
||||
node_name,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
WasmRequest::RttChartCircuit { period, circuit_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_rtt_for_all_nodes_circuit(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
circuit_id,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
// Site Stack
|
||||
WasmRequest::SiteStack { period, site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_site_stack_map(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
site_id,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
},
|
||||
WasmRequest::RootHeat { period } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = root_heat_map(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
},
|
||||
WasmRequest::SiteHeat { period, site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = site_heat_map(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&site_id,
|
||||
InfluxTimePeriod::new(&period),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
}
|
||||
WasmRequest::NodePerfChart { period, node_id, node_name } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = send_perf_for_node(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
InfluxTimePeriod::new(&period),
|
||||
node_id,
|
||||
node_name,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::info!("Throughput requested but no credentials provided");
|
||||
}
|
||||
},
|
||||
WasmRequest::Tree { parent } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
send_site_tree(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&parent,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
},
|
||||
WasmRequest::SiteInfo { site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
send_site_info(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&site_id,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
WasmRequest::SiteParents { site_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
send_site_parents(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&site_id,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
WasmRequest::Search { term } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
let _ = omnisearch(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&term,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
WasmRequest::CircuitInfo { circuit_id } => {
|
||||
if let Some(credentials) = &credentials {
|
||||
send_circuit_info(
|
||||
cnn.clone(),
|
||||
&mut socket,
|
||||
&credentials.license_key,
|
||||
&circuit_id,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if let Ok(text) = msg.into_text() {
|
||||
let json = serde_json::from_str::<Value>(&text);
|
||||
if json.is_err() {
|
||||
log::warn!("Unable to parse JSON: {}", json.err().unwrap());
|
||||
@ -331,6 +631,16 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool<Postgres>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_resposne(response: WasmResponse) -> Vec<u8> {
|
||||
let cbor = lts_client::cbor::to_vec(&response).unwrap();
|
||||
miniz_oxide::deflate::compress_to_vec(&cbor, 8)
|
||||
}
|
||||
|
||||
pub async fn send_response(socket: &mut WebSocket, response: WasmResponse) {
|
||||
let serialized = serialize_resposne(response);
|
||||
socket.send(Message::Binary(serialized)).await.unwrap();
|
||||
}
|
@ -1,27 +1,14 @@
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use wasm_pipe_types::Node;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct NodeStatus {
|
||||
msg: String,
|
||||
nodes: Vec<Node>,
|
||||
}
|
||||
use crate::web::wss::send_response;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Node {
|
||||
node_id: String,
|
||||
node_name: String,
|
||||
last_seen: i32,
|
||||
}
|
||||
|
||||
impl From<pgdb::NodeStatus> for Node {
|
||||
fn from(ns: pgdb::NodeStatus) -> Self {
|
||||
Self {
|
||||
node_id: ns.node_id,
|
||||
node_name: ns.node_name,
|
||||
last_seen: ns.last_seen,
|
||||
}
|
||||
fn convert(ns: pgdb::NodeStatus) -> Node {
|
||||
Node {
|
||||
node_id: ns.node_id,
|
||||
node_name: ns.node_name,
|
||||
last_seen: ns.last_seen,
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,13 +17,8 @@ pub async fn node_status(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str)
|
||||
let nodes = pgdb::node_status(cnn, key).await;
|
||||
match nodes {
|
||||
Ok(nodes) => {
|
||||
let nodes: Vec<Node> = nodes.into_iter().map(|n| n.into()).collect();
|
||||
let status = NodeStatus {
|
||||
msg: "nodeStatus".to_string(),
|
||||
nodes};
|
||||
let reply = serde_json::to_string(&status).unwrap();
|
||||
let msg = axum::extract::ws::Message::Text(reply);
|
||||
socket.send(msg).await.unwrap();
|
||||
let nodes: Vec<Node> = nodes.into_iter().map(convert).collect();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::NodeStatus { nodes }).await;
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Unable to obtain node status: {}", e);
|
||||
|
@ -1,58 +1,29 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use wasm_pipe_types::CircuitList;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct CircuitInfoMessage {
|
||||
msg: String,
|
||||
data: Vec<CircuitList>,
|
||||
}
|
||||
use crate::web::wss::send_response;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CircuitList {
|
||||
pub circuit_name: String,
|
||||
pub device_id: String,
|
||||
pub device_name: String,
|
||||
pub parent_node: String,
|
||||
pub mac: String,
|
||||
pub download_min_mbps: i32,
|
||||
pub download_max_mbps: i32,
|
||||
pub upload_min_mbps: i32,
|
||||
pub upload_max_mbps: i32,
|
||||
pub comment: String,
|
||||
pub ip_range: String,
|
||||
pub subnet: i32,
|
||||
}
|
||||
|
||||
impl From<pgdb::CircuitInfo> for CircuitList {
|
||||
fn from(circuit: pgdb::CircuitInfo) -> Self {
|
||||
Self {
|
||||
circuit_name: circuit.circuit_name,
|
||||
device_id: circuit.device_id,
|
||||
device_name: circuit.device_name,
|
||||
parent_node: circuit.parent_node,
|
||||
mac: circuit.mac,
|
||||
download_min_mbps: circuit.download_min_mbps,
|
||||
download_max_mbps: circuit.download_max_mbps,
|
||||
upload_min_mbps: circuit.upload_min_mbps,
|
||||
upload_max_mbps: circuit.upload_max_mbps,
|
||||
comment: circuit.comment,
|
||||
ip_range: circuit.ip_range,
|
||||
subnet: circuit.subnet,
|
||||
}
|
||||
fn from(circuit: pgdb::CircuitInfo) -> CircuitList {
|
||||
CircuitList {
|
||||
circuit_name: circuit.circuit_name,
|
||||
device_id: circuit.device_id,
|
||||
device_name: circuit.device_name,
|
||||
parent_node: circuit.parent_node,
|
||||
mac: circuit.mac,
|
||||
download_min_mbps: circuit.download_min_mbps,
|
||||
download_max_mbps: circuit.download_max_mbps,
|
||||
upload_min_mbps: circuit.upload_min_mbps,
|
||||
upload_max_mbps: circuit.upload_max_mbps,
|
||||
comment: circuit.comment,
|
||||
ip_range: circuit.ip_range,
|
||||
subnet: circuit.subnet,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_circuit_info(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, circuit_id: &str) {
|
||||
if let Ok(hosts) = pgdb::get_circuit_info(cnn, key, circuit_id).await {
|
||||
let hosts = hosts.into_iter().map(CircuitList::from).collect::<Vec<_>>();
|
||||
let msg = CircuitInfoMessage {
|
||||
msg: "circuit_info".to_string(),
|
||||
data: hosts,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
if let Err(e) = socket.send(Message::Text(json)).await {
|
||||
tracing::error!("Error sending message: {}", e);
|
||||
}
|
||||
let hosts = hosts.into_iter().map(from).collect::<Vec<_>>();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::CircuitInfo { data: hosts }).await;
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use influxdb2::{Client, FromDataPoint, models::Query};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use crate::submissions::get_org_details;
|
||||
use wasm_pipe_types::{PerfHost, Perf};
|
||||
use crate::{submissions::get_org_details, web::wss::send_response};
|
||||
use super::time_period::InfluxTimePeriod;
|
||||
|
||||
#[derive(Debug, FromDataPoint)]
|
||||
@ -27,27 +27,6 @@ impl Default for PerfRow {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct PerfHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub stats: Vec<Perf>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct Perf {
|
||||
pub date: String,
|
||||
pub cpu: f64,
|
||||
pub cpu_max: f64,
|
||||
pub ram: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct PacketChart {
|
||||
pub msg: String,
|
||||
pub nodes: Vec<PerfHost>,
|
||||
}
|
||||
|
||||
pub async fn send_perf_for_node(
|
||||
cnn: Pool<Postgres>,
|
||||
socket: &mut WebSocket,
|
||||
@ -57,13 +36,7 @@ pub async fn send_perf_for_node(
|
||||
node_name: String,
|
||||
) -> anyhow::Result<()> {
|
||||
let node = get_perf_for_node(cnn, key, node_id, node_name, period).await?;
|
||||
|
||||
let chart = PacketChart {
|
||||
msg: "nodePerfChart".to_string(),
|
||||
nodes: vec![node],
|
||||
};
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::NodePerfChart { nodes: vec![node] }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,24 @@
|
||||
//! Packet-per-second data queries
|
||||
mod packet_host;
|
||||
mod packet_row;
|
||||
use self::{packet_host::{Packets, PacketHost, PacketChart}, packet_row::PacketRow};
|
||||
use crate::submissions::get_org_details;
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use self::packet_row::PacketRow;
|
||||
use crate::{submissions::get_org_details, web::wss::send_response};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use futures::future::join_all;
|
||||
use influxdb2::{models::Query, Client};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use wasm_pipe_types::{PacketHost, Packets};
|
||||
use super::time_period::InfluxTimePeriod;
|
||||
|
||||
pub async fn send_packets_for_all_nodes(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, period: InfluxTimePeriod) -> anyhow::Result<()> {
|
||||
let nodes = get_packets_for_all_nodes(cnn, key, period).await?;
|
||||
|
||||
let chart = PacketChart { msg: "packetChart".to_string(), nodes };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::PacketChart { nodes }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_packets_for_node(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, period: InfluxTimePeriod, node_id: String, node_name: String) -> anyhow::Result<()> {
|
||||
let node = get_packets_for_node(cnn, key, node_id, node_name, period).await?;
|
||||
|
||||
let chart = PacketChart { msg: "packetChart".to_string(), nodes: vec![node] };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::PacketChart { nodes: vec![node] }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct PacketHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub down: Vec<Packets>,
|
||||
pub up: Vec<Packets>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct Packets {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct PacketChart {
|
||||
pub msg: String,
|
||||
pub nodes: Vec<PacketHost>,
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use futures::future::join_all;
|
||||
use influxdb2::{Client, models::Query};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use crate::{submissions::get_org_details, web::wss::queries::rtt::rtt_row::RttCircuitRow};
|
||||
use self::{rtt_row::{RttRow, RttSiteRow}, rtt_host::{Rtt, RttHost, RttChart}};
|
||||
use wasm_pipe_types::{RttHost, Rtt};
|
||||
use crate::{submissions::get_org_details, web::wss::{queries::rtt::rtt_row::RttCircuitRow, send_response}};
|
||||
use self::rtt_row::{RttRow, RttSiteRow};
|
||||
|
||||
use super::time_period::InfluxTimePeriod;
|
||||
mod rtt_row;
|
||||
mod rtt_host;
|
||||
|
||||
pub async fn send_rtt_for_all_nodes(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, period: InfluxTimePeriod) -> anyhow::Result<()> {
|
||||
let nodes = get_rtt_for_all_nodes(cnn, key, period).await?;
|
||||
@ -19,10 +19,8 @@ pub async fn send_rtt_for_all_nodes(cnn: Pool<Postgres>, socket: &mut WebSocket,
|
||||
histogram[bucket] += 1;
|
||||
}
|
||||
}
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::RttChart { nodes, histogram }).await;
|
||||
|
||||
let chart = RttChart { msg: "rttChart".to_string(), nodes, histogram };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -37,9 +35,7 @@ pub async fn send_rtt_for_all_nodes_site(cnn: Pool<Postgres>, socket: &mut WebSo
|
||||
}
|
||||
}
|
||||
|
||||
let chart = RttChart { msg: "rttChartSite".to_string(), nodes, histogram };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::RttChartSite { nodes, histogram }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -54,9 +50,7 @@ pub async fn send_rtt_for_all_nodes_circuit(cnn: Pool<Postgres>, socket: &mut We
|
||||
}
|
||||
}
|
||||
|
||||
let chart = RttChart { msg: "rttChartCircuit".to_string(), nodes, histogram };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::RttChartCircuit { nodes, histogram }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -72,9 +66,7 @@ pub async fn send_rtt_for_node(cnn: Pool<Postgres>, socket: &mut WebSocket, key:
|
||||
}
|
||||
}
|
||||
|
||||
let chart = RttChart { msg: "rttChart".to_string(), nodes, histogram };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::RttChart { nodes, histogram }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct Rtt {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct RttHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub rtt: Vec<Rtt>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct RttChart {
|
||||
pub msg: String,
|
||||
pub nodes: Vec<RttHost>,
|
||||
pub histogram: Vec<u32>,
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use wasm_pipe_types::SearchResult;
|
||||
|
||||
use crate::web::wss::send_response;
|
||||
|
||||
pub async fn omnisearch(
|
||||
cnn: Pool<Postgres>,
|
||||
@ -23,31 +25,11 @@ pub async fn omnisearch(
|
||||
hits.dedup_by(|a,b| a.name == b.name && a.url == b.url);
|
||||
hits.sort_by(|a,b| a.score.partial_cmp(&b.score).unwrap());
|
||||
|
||||
let msg = SearchMessage {
|
||||
msg: "search".to_string(),
|
||||
hits
|
||||
};
|
||||
log::warn!("{msg:?}");
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::SearchResult { hits }).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct SearchMessage {
|
||||
msg: String,
|
||||
hits: Vec<SearchResult>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct SearchResult {
|
||||
name: String,
|
||||
url: String,
|
||||
score: f64,
|
||||
icon: String,
|
||||
}
|
||||
|
||||
async fn search_devices(
|
||||
cnn: Pool<Postgres>,
|
||||
key: &str,
|
||||
|
@ -1,12 +1,14 @@
|
||||
use super::time_period::InfluxTimePeriod;
|
||||
use crate::submissions::get_org_details;
|
||||
use axum::extract::ws::{Message, WebSocket};
|
||||
use crate::web::wss::send_response;
|
||||
use axum::extract::ws::WebSocket;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use influxdb2::Client;
|
||||
use influxdb2::{models::Query, FromDataPoint};
|
||||
use pgdb::OrganizationDetails;
|
||||
use pgdb::sqlx::{query, Pool, Postgres, Row};
|
||||
use serde::Serialize;
|
||||
use wasm_pipe_types::WasmResponse;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub async fn root_heat_map(
|
||||
@ -69,12 +71,7 @@ pub async fn root_heat_map(
|
||||
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();
|
||||
send_response(socket, WasmResponse::RootHeat { data: sorter}).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,13 +229,7 @@ pub async fn site_heat_map(
|
||||
}
|
||||
|
||||
site_circuits_heat_map(cnn, key, site_name, period, &mut sorter, client, &org).await?;
|
||||
|
||||
let msg = HeatMessage {
|
||||
msg: "siteHeat".to_string(),
|
||||
data: sorter,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, WasmResponse::SiteHeat { data: sorter }).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
use super::site_tree::SiteTree;
|
||||
use wasm_pipe_types::{SiteTree, WasmResponse};
|
||||
use crate::web::wss::send_response;
|
||||
use super::site_tree::tree_to_host;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SiteInfoMessage {
|
||||
@ -12,14 +14,7 @@ struct SiteInfoMessage {
|
||||
|
||||
pub async fn send_site_info(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, site_id: &str) {
|
||||
if let Ok(host) = pgdb::get_site_info(cnn, key, site_id).await {
|
||||
let host = SiteTree::from(host);
|
||||
let msg = SiteInfoMessage {
|
||||
msg: "site_info".to_string(),
|
||||
data: host,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
if let Err(e) = socket.send(Message::Text(json)).await {
|
||||
tracing::error!("Error sending message: {}", e);
|
||||
}
|
||||
let host = tree_to_host(host);
|
||||
send_response(socket, WasmResponse::SiteInfo { data: host }).await;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::web::wss::send_response;
|
||||
|
||||
pub async fn send_site_parents(
|
||||
cnn: Pool<Postgres>,
|
||||
@ -9,39 +10,13 @@ pub async fn send_site_parents(
|
||||
site_name: &str,
|
||||
) {
|
||||
if let Ok(parents) = pgdb::get_parent_list(cnn.clone(), key, site_name).await {
|
||||
let msg = TreeMessage {
|
||||
msg: "site_parents".to_string(),
|
||||
data: parents,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
if let Err(e) = socket.send(Message::Text(json)).await {
|
||||
tracing::error!("Error sending message: {}", e);
|
||||
}
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::SiteParents { data: parents }).await;
|
||||
}
|
||||
|
||||
let child_result = pgdb::get_child_list(cnn, key, site_name).await;
|
||||
if let Ok(children) = child_result {
|
||||
let msg = TreeChildMessage {
|
||||
msg: "site_children".to_string(),
|
||||
data: children,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
if let Err(e) = socket.send(Message::Text(json)).await {
|
||||
tracing::error!("Error sending message: {}", e);
|
||||
}
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::SiteChildren { data: children }).await;
|
||||
} else {
|
||||
log::error!("Error getting children: {:?}", child_result);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TreeMessage {
|
||||
msg: String,
|
||||
data: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TreeChildMessage {
|
||||
msg: String,
|
||||
data: Vec<(String, String, String)>,
|
||||
}
|
||||
|
@ -1,57 +1,31 @@
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::{
|
||||
sqlx::{Pool, Postgres},
|
||||
TreeNode,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use wasm_pipe_types::SiteTree;
|
||||
use crate::web::wss::send_response;
|
||||
|
||||
pub async fn send_site_tree(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, parent: &str) {
|
||||
let tree = pgdb::get_site_tree(cnn, key, parent).await.unwrap();
|
||||
let tree = tree
|
||||
.into_iter()
|
||||
.map(|row| row.into())
|
||||
.map(tree_to_host)
|
||||
.collect::<Vec<SiteTree>>();
|
||||
let msg = TreeMessage {
|
||||
msg: "site_tree".to_string(),
|
||||
data: tree,
|
||||
};
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
if let Err(e) = socket.send(Message::Text(json)).await {
|
||||
tracing::error!("Error sending message: {}", e);
|
||||
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::SiteTree { data: tree }).await;
|
||||
}
|
||||
|
||||
pub(crate) fn tree_to_host(row: TreeNode) -> SiteTree {
|
||||
SiteTree {
|
||||
index: row.index,
|
||||
site_name: row.site_name,
|
||||
site_type: row.site_type,
|
||||
parent: row.parent,
|
||||
max_down: row.max_down,
|
||||
max_up: row.max_up,
|
||||
current_down: row.current_down,
|
||||
current_up: row.current_up,
|
||||
current_rtt: row.current_rtt,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct SiteTree {
|
||||
pub index: i32,
|
||||
pub site_name: String,
|
||||
pub site_type: String,
|
||||
pub parent: i32,
|
||||
pub max_down: i32,
|
||||
pub max_up: i32,
|
||||
pub current_down: i32,
|
||||
pub current_up: i32,
|
||||
pub current_rtt: i32,
|
||||
}
|
||||
|
||||
impl From<TreeNode> for SiteTree {
|
||||
fn from(row: TreeNode) -> Self {
|
||||
SiteTree {
|
||||
index: row.index,
|
||||
site_name: row.site_name,
|
||||
site_type: row.site_type,
|
||||
parent: row.parent,
|
||||
max_down: row.max_down,
|
||||
max_up: row.max_up,
|
||||
current_down: row.current_down,
|
||||
current_up: row.current_up,
|
||||
current_rtt: row.current_rtt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TreeMessage {
|
||||
msg: String,
|
||||
data: Vec<SiteTree>,
|
||||
}
|
||||
|
@ -1,49 +1,38 @@
|
||||
use std::collections::HashMap;
|
||||
mod site_stack;
|
||||
use axum::extract::ws::{WebSocket, Message};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use futures::future::join_all;
|
||||
use influxdb2::{Client, models::Query};
|
||||
use pgdb::sqlx::{Pool, Postgres};
|
||||
use crate::submissions::get_org_details;
|
||||
use self::{throughput_host::{ThroughputHost, Throughput, ThroughputChart}, throughput_row::{ThroughputRow, ThroughputRowBySite, ThroughputRowByCircuit}};
|
||||
use wasm_pipe_types::{ThroughputHost, Throughput};
|
||||
use crate::{submissions::get_org_details, web::wss::send_response};
|
||||
use self::throughput_row::{ThroughputRow, ThroughputRowBySite, ThroughputRowByCircuit};
|
||||
use super::time_period::InfluxTimePeriod;
|
||||
mod throughput_host;
|
||||
mod throughput_row;
|
||||
pub use site_stack::send_site_stack_map;
|
||||
|
||||
pub async fn send_throughput_for_all_nodes(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, period: InfluxTimePeriod) -> anyhow::Result<()> {
|
||||
let nodes = get_throughput_for_all_nodes(cnn, key, period).await?;
|
||||
|
||||
let chart = ThroughputChart { msg: "bitsChart".to_string(), nodes };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::BitsChart { nodes }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_throughput_for_all_nodes_by_site(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, site_name: String, period: InfluxTimePeriod) -> anyhow::Result<()> {
|
||||
let nodes = get_throughput_for_all_nodes_by_site(cnn, key, period, &site_name).await?;
|
||||
|
||||
let chart = ThroughputChart { msg: "bitsChartSite".to_string(), nodes };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::BitsChart { nodes }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_throughput_for_all_nodes_by_circuit(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, circuit_id: String, period: InfluxTimePeriod) -> anyhow::Result<()> {
|
||||
let nodes = get_throughput_for_all_nodes_by_circuit(cnn, key, period, &circuit_id).await?;
|
||||
|
||||
let chart = ThroughputChart { msg: "bitsChartCircuit".to_string(), nodes };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::BitsChart { nodes }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_throughput_for_node(cnn: Pool<Postgres>, socket: &mut WebSocket, key: &str, period: InfluxTimePeriod, node_id: String, node_name: String) -> anyhow::Result<()> {
|
||||
let node = get_throughput_for_node(cnn, key, node_id, node_name, period).await?;
|
||||
|
||||
let chart = ThroughputChart { msg: "bitsChart".to_string(), nodes: vec![node] };
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::BitsChart { nodes: vec![node] }).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::web::wss::queries::{
|
||||
throughput::throughput_host::ThroughputChart, time_period::InfluxTimePeriod,
|
||||
};
|
||||
use axum::extract::ws::{Message, WebSocket};
|
||||
use crate::web::wss::{queries::{
|
||||
time_period::InfluxTimePeriod,
|
||||
}, send_response};
|
||||
use axum::extract::ws::WebSocket;
|
||||
use pgdb::sqlx::{Pool, Postgres, Row};
|
||||
|
||||
use super::{get_throughput_for_all_nodes_by_circuit, get_throughput_for_all_nodes_by_site};
|
||||
@ -58,12 +58,7 @@ pub async fn send_site_stack_map(
|
||||
}
|
||||
//println!("{result:?}");
|
||||
|
||||
let chart = ThroughputChart {
|
||||
msg: "siteStack".to_string(),
|
||||
nodes: result,
|
||||
};
|
||||
let json = serde_json::to_string(&chart).unwrap();
|
||||
socket.send(Message::Text(json)).await.unwrap();
|
||||
send_response(socket, wasm_pipe_types::WasmResponse::SiteStack { nodes: result }).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct ThroughputHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub down: Vec<Throughput>,
|
||||
pub up: Vec<Throughput>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct Throughput {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct ThroughputChart {
|
||||
pub msg: String,
|
||||
pub nodes: Vec<ThroughputHost>,
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InfluxTimePeriod {
|
||||
start: String,
|
||||
@ -7,41 +5,34 @@ pub struct InfluxTimePeriod {
|
||||
}
|
||||
|
||||
impl InfluxTimePeriod {
|
||||
pub fn new(period: Option<Value>) -> Self {
|
||||
if let Some(period) = period {
|
||||
let start = match period.as_str() {
|
||||
Some("5m") => "-5m",
|
||||
Some("15m") => "-15m",
|
||||
Some("1h") => "-60m",
|
||||
Some("6h") => "-360m",
|
||||
Some("12h") => "-720m",
|
||||
Some("24h") => "-1440m",
|
||||
Some("7d") => "-10080m",
|
||||
Some("28d") => "-40320m",
|
||||
_ => "-5m",
|
||||
};
|
||||
pub fn new(period: &str) -> Self {
|
||||
let start = match period {
|
||||
"5m" => "-5m",
|
||||
"15m" => "-15m",
|
||||
"1h" => "-60m",
|
||||
"6h" => "-360m",
|
||||
"12h" => "-720m",
|
||||
"24h" => "-1440m",
|
||||
"7d" => "-10080m",
|
||||
"28d" => "-40320m",
|
||||
_ => "-5m",
|
||||
};
|
||||
|
||||
let aggregate = match period.as_str() {
|
||||
Some("5m") => "10s",
|
||||
Some("15m") => "10s",
|
||||
Some("1h") => "10s",
|
||||
Some("6h") => "1m",
|
||||
Some("12h") => "2m",
|
||||
Some("24h") => "4m",
|
||||
Some("7d") => "30m",
|
||||
Some("28d") => "1h",
|
||||
_ => "10s"
|
||||
};
|
||||
let aggregate = match period {
|
||||
"5m" => "10s",
|
||||
"15m" => "10s",
|
||||
"1h" => "10s",
|
||||
"6h" => "1m",
|
||||
"12h" => "2m",
|
||||
"24h" => "4m",
|
||||
"7d" => "30m",
|
||||
"28d" => "1h",
|
||||
_ => "10s",
|
||||
};
|
||||
|
||||
Self {
|
||||
start: start.to_string(),
|
||||
aggregate: aggregate.to_string(),
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
start: "-5m".to_string(),
|
||||
aggregate: "10s".to_string(),
|
||||
}
|
||||
Self {
|
||||
start: start.to_string(),
|
||||
aggregate: aggregate.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +41,9 @@ impl InfluxTimePeriod {
|
||||
}
|
||||
|
||||
pub fn aggregate_window(&self) -> String {
|
||||
format!("aggregateWindow(every: {}, fn: mean, createEmpty: false)", self.aggregate)
|
||||
format!(
|
||||
"aggregateWindow(every: {}, fn: mean, createEmpty: false)",
|
||||
self.aggregate
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
src/rust/long_term_stats/lts_node/web/wasm_pipe_bg.wasm
Normal file
BIN
src/rust/long_term_stats/lts_node/web/wasm_pipe_bg.wasm
Normal file
Binary file not shown.
@ -8,5 +8,6 @@ await esbuild.build({
|
||||
sourcemap: true,
|
||||
// target: ['chrome58', 'firefox57', 'safari11', 'edge16'],
|
||||
outdir: 'output/',
|
||||
loader: { '.html': 'text'}
|
||||
loader: { '.html': 'text'},
|
||||
format: 'esm',
|
||||
})
|
||||
|
@ -1,9 +1,14 @@
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import 'bootstrap/dist/js/bootstrap.js';
|
||||
import { SiteRouter } from './router';
|
||||
import { Bus } from './bus';
|
||||
import { Bus, onAuthFail, onAuthOk, onMessage } from './bus';
|
||||
import { Auth } from './auth';
|
||||
|
||||
import init from '../wasm/wasm_pipe.js';
|
||||
|
||||
await init();
|
||||
console.log("WASM loaded");
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
router: SiteRouter;
|
||||
@ -14,6 +19,9 @@ declare global {
|
||||
changeGraphPeriod: any;
|
||||
}
|
||||
}
|
||||
(window as any).onAuthFail = onAuthFail;
|
||||
(window as any).onAuthOk = onAuthOk;
|
||||
(window as any).onMessage = onMessage;
|
||||
|
||||
window.auth = new Auth;
|
||||
window.bus = new Bus();
|
||||
@ -29,6 +37,7 @@ window.graphPeriod = graphPeriod;
|
||||
window.changeGraphPeriod = (period: string) => changeGraphPeriod(period);
|
||||
|
||||
window.setInterval(() => {
|
||||
console.log("tick");
|
||||
window.router.ontick();
|
||||
window.bus.updateConnected();
|
||||
}, 1000);
|
||||
@ -36,4 +45,4 @@ window.setInterval(() => {
|
||||
function changeGraphPeriod(period: string) {
|
||||
window.graphPeriod = period;
|
||||
localStorage.setItem('graphPeriod', period);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { connect_wasm_pipe, is_wasm_connected } from "../wasm/wasm_pipe";
|
||||
import { Auth } from "./auth";
|
||||
import { SiteRouter } from "./router";
|
||||
|
||||
@ -6,12 +7,15 @@ export class Bus {
|
||||
connected: boolean;
|
||||
|
||||
constructor() {
|
||||
const currentUrlWithoutAnchors = window.location.href.split('#')[0].replace("https://", "").replace("http://", "");
|
||||
const url = "ws://" + currentUrlWithoutAnchors + "ws";
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
updateConnected() {
|
||||
//console.log("Connection via WASM: " + is_wasm_connected());
|
||||
let indicator = document.getElementById("connStatus");
|
||||
if (indicator && this.connected) {
|
||||
if (indicator && is_wasm_connected()) {
|
||||
indicator.style.color = "green";
|
||||
} else if (indicator) {
|
||||
indicator.style.color = "red";
|
||||
@ -22,77 +26,17 @@ export class Bus {
|
||||
connect() {
|
||||
const currentUrlWithoutAnchors = window.location.href.split('#')[0].replace("https://", "").replace("http://", "");
|
||||
const url = "ws://" + currentUrlWithoutAnchors + "ws";
|
||||
this.ws = new WebSocket(url);
|
||||
this.ws.onopen = () => {
|
||||
this.connected = true;
|
||||
this.sendToken();
|
||||
};
|
||||
this.ws.onclose = (e) => {
|
||||
this.connected = false;
|
||||
console.log("close", e)
|
||||
};
|
||||
this.ws.onerror = (e) => {
|
||||
console.log("error", e)
|
||||
this.connected = false;
|
||||
};
|
||||
this.ws.onmessage = (e) => {
|
||||
//console.log("message", e.data)
|
||||
let json = JSON.parse(e.data);
|
||||
if (json.msg && json.msg == "authOk") {
|
||||
window.auth.hasCredentials = true;
|
||||
window.login = json;
|
||||
window.auth.token = json.token;
|
||||
} else if (json.msg && json.msg == "authFail") {
|
||||
window.auth.hasCredentials = false;
|
||||
window.login = null;
|
||||
window.auth.token = null;
|
||||
localStorage.removeItem("token");
|
||||
window.router.goto("login");
|
||||
}
|
||||
window.router.onMessage(json);
|
||||
};
|
||||
connect_wasm_pipe(url);
|
||||
}
|
||||
|
||||
sendToken() {
|
||||
getToken(): string {
|
||||
if (window.auth.hasCredentials && window.auth.token) {
|
||||
this.ws.send(formatToken(window.auth.token));
|
||||
return window.auth.token;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
requestNodeStatus() {
|
||||
this.ws.send("{ \"msg\": \"nodeStatus\" }");
|
||||
}
|
||||
|
||||
requestPacketChart() {
|
||||
this.ws.send("{ \"msg\": \"packetChart\", \"period\": \"" + window.graphPeriod + "\" }");
|
||||
}
|
||||
|
||||
requestPacketChartSingle(node_id: string, node_name: string) {
|
||||
let request = {
|
||||
msg: "packetChartSingle",
|
||||
period: window.graphPeriod,
|
||||
node_id: node_id,
|
||||
node_name: node_name,
|
||||
};
|
||||
let json = JSON.stringify(request);
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestThroughputChart() {
|
||||
this.ws.send("{ \"msg\": \"throughputChart\", \"period\": \"" + window.graphPeriod + "\" }");
|
||||
}
|
||||
|
||||
requestThroughputChartSingle(node_id: string, node_name: string) {
|
||||
let request = {
|
||||
msg: "throughputChartSingle",
|
||||
period: window.graphPeriod,
|
||||
node_id: node_id,
|
||||
node_name: node_name,
|
||||
};
|
||||
let json = JSON.stringify(request);
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestThroughputChartCircuit(circuit_id: string) {
|
||||
let request = {
|
||||
msg: "throughputChartCircuit",
|
||||
@ -113,31 +57,6 @@ export class Bus {
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestThroughputStackSite(site_id: string) {
|
||||
let request = {
|
||||
msg: "throughputStackSite",
|
||||
period: window.graphPeriod,
|
||||
site_id: decodeURI(site_id),
|
||||
};
|
||||
let json = JSON.stringify(request);
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestRttChart() {
|
||||
this.ws.send("{ \"msg\": \"rttChart\", \"period\": \"" + window.graphPeriod + "\" }");
|
||||
}
|
||||
|
||||
requestRttChartSingle(node_id: string, node_name: string) {
|
||||
let request = {
|
||||
msg: "rttChartSingle",
|
||||
period: window.graphPeriod,
|
||||
node_id: node_id,
|
||||
node_name: node_name,
|
||||
};
|
||||
let json = JSON.stringify(request);
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestRttChartSite(site_id: string) {
|
||||
let request = {
|
||||
msg: "rttChartSite",
|
||||
@ -158,21 +77,6 @@ export class Bus {
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestNodePerfChart(node_id: string, node_name: string) {
|
||||
let request = {
|
||||
msg: "nodePerf",
|
||||
period: window.graphPeriod,
|
||||
node_id: node_id,
|
||||
node_name: node_name,
|
||||
};
|
||||
let json = JSON.stringify(request);
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestSiteRootHeat() {
|
||||
this.ws.send("{ \"msg\": \"siteRootHeat\", \"period\": \"" + window.graphPeriod + "\" }");
|
||||
}
|
||||
|
||||
requestSiteHeat(site_id: string) {
|
||||
let request = {
|
||||
msg: "siteHeat",
|
||||
@ -192,10 +96,6 @@ export class Bus {
|
||||
this.ws.send(json);
|
||||
}
|
||||
|
||||
requestTree(parent: string) {
|
||||
this.ws.send("{ \"msg\": \"siteTree\", \"parent\": \"" + parent + "\" }");
|
||||
}
|
||||
|
||||
requestSiteInfo(site_id: string) {
|
||||
let request = {
|
||||
msg: "siteInfo",
|
||||
@ -224,12 +124,33 @@ export class Bus {
|
||||
}
|
||||
}
|
||||
|
||||
function formatToken(token: string) {
|
||||
return "{ \"msg\": \"auth\", \"token\": \"" + token + "\" }";
|
||||
}
|
||||
|
||||
function retryConnect() {
|
||||
if (!window.bus.connected) {
|
||||
window.bus.connect();
|
||||
}
|
||||
}
|
||||
|
||||
// WASM callback
|
||||
export function onAuthFail() {
|
||||
window.auth.hasCredentials = false;
|
||||
window.login = null;
|
||||
window.auth.token = null;
|
||||
localStorage.removeItem("token");
|
||||
window.router.goto("login");
|
||||
}
|
||||
|
||||
// WASM callback
|
||||
export function onAuthOk(token: string, name: string, license_key: string) {
|
||||
window.auth.hasCredentials = true;
|
||||
window.login = { msg: "authOk", token: token, name: name, license_key: license_key };
|
||||
window.auth.token = token;
|
||||
}
|
||||
|
||||
// WASM Callback
|
||||
export function onMessage(rawJson: string) {
|
||||
let json = JSON.parse(rawJson);
|
||||
//console.log(json);
|
||||
//console.log(Object.keys(json));
|
||||
json.msg = Object.keys(json)[0];
|
||||
window.router.onMessage(json);
|
||||
}
|
@ -1,45 +1,46 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { mbps_to_bps } from "../site_tree/site_tree";
|
||||
import { Component } from "./component";
|
||||
import { request_circuit_info } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class CircuitInfo implements Component {
|
||||
circuitId: string;
|
||||
count: number = 0;
|
||||
|
||||
constructor(siteId: string) {
|
||||
this.circuitId = siteId;
|
||||
this.circuitId = decodeURI(siteId);
|
||||
}
|
||||
|
||||
wireup(): void {
|
||||
window.bus.requestCircuitInfo(this.circuitId);
|
||||
request_circuit_info(this.circuitId);
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
this.count++;
|
||||
if (this.count % 10 == 0) {
|
||||
window.bus.requestCircuitInfo(this.circuitId);
|
||||
request_circuit_info(this.circuitId);
|
||||
}
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "circuit_info") {
|
||||
//console.log(event.data);
|
||||
if (event.msg == "CircuitInfo") {
|
||||
//console.log(event.CircuitInfo.data);
|
||||
let div = document.getElementById("circuitInfo") as HTMLDivElement;
|
||||
let html = "";
|
||||
html += "<table class='table table-striped'>";
|
||||
html += "<tr><td>Circuit Name:</td><td>" + event.data[0].circuit_name + "</td></tr>";
|
||||
html += "<tr><td>Min (CIR) Limits:</td><td>" + event.data[0].download_min_mbps + " / " + event.data[0].upload_min_mbps + " Mbps</td></tr>";
|
||||
html += "<tr><td>Max (Ceiling) Limits:</td><td>" + event.data[0].download_max_mbps + " / " + event.data[0].upload_max_mbps + " Mbps</td></tr>";
|
||||
html += "<tr><td>Circuit Name:</td><td>" + event.CircuitInfo.data[0].circuit_name + "</td></tr>";
|
||||
html += "<tr><td>Min (CIR) Limits:</td><td>" + event.CircuitInfo.data[0].download_min_mbps + " / " + event.CircuitInfo.data[0].upload_min_mbps + " Mbps</td></tr>";
|
||||
html += "<tr><td>Max (Ceiling) Limits:</td><td>" + event.CircuitInfo.data[0].download_max_mbps + " / " + event.CircuitInfo.data[0].upload_max_mbps + " Mbps</td></tr>";
|
||||
html += "</table>";
|
||||
div.innerHTML = html;
|
||||
|
||||
div = document.getElementById("circuitDevices") as HTMLDivElement;
|
||||
html = "";
|
||||
html += "<table class='table table-striped'>";
|
||||
for (let i=0; i<event.data.length; i++) {
|
||||
for (let i=0; i<event.CircuitInfo.data.length; i++) {
|
||||
html += "<tr>";
|
||||
html += "<td>Device:</td><td>" + event.data[i].device_name + "</td>";
|
||||
html += "<td>IP:</td><td>" + event.data[i].ip_range + "/" + event.data[i].subnet + "</td>";
|
||||
html += "<td>Device:</td><td>" + event.CircuitInfo.data[i].device_name + "</td>";
|
||||
html += "<td>IP:</td><td>" + event.CircuitInfo.data[i].ip_range + "/" + event.CircuitInfo.data[i].subnet + "</td>";
|
||||
html += "</tr>";
|
||||
}
|
||||
html += "</table>";
|
||||
|
@ -25,7 +25,7 @@ export class NodeCpuChart implements Component {
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "nodePerfChart") {
|
||||
if (event.msg == "NodePerfChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -33,8 +33,8 @@ export class NodeCpuChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.NodePerfChart.nodes.length; i++) {
|
||||
let node = event.NodePerfChart.nodes[i];
|
||||
legend.push(node.node_name + " CPU %");
|
||||
legend.push(node.node_name + " Single Core Peak");
|
||||
//console.log(node);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component } from "./component";
|
||||
import { request_node_status } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class NodeList implements Component {
|
||||
wireup(): void {
|
||||
@ -6,11 +7,11 @@ export class NodeList implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestNodeStatus();
|
||||
request_node_status();
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "nodeStatus") {
|
||||
if (event.msg == "NodeStatus") {
|
||||
let status = document.getElementById("nodeList");
|
||||
let html = "";
|
||||
if (status) {
|
||||
@ -18,8 +19,8 @@ export class NodeList implements Component {
|
||||
html += "<thead>";
|
||||
html += "<th>Node ID</th><th>Node Name</th><th>Last Seen</th>";
|
||||
html += "</thead><tbody>";
|
||||
for (let i = 0; i < event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i = 0; i < event.NodeStatus.nodes.length; i++) {
|
||||
let node = event.NodeStatus.nodes[i];
|
||||
let url = "\"shaperNode:" + node.node_id + ":" + node.node_name.replace(':', '_') + "\"";
|
||||
let oc = "onclick='window.router.goto(" + url + ")'";
|
||||
html += "<tr>";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_node_perf_chart } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -21,11 +22,11 @@ export class NodeRamChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestNodePerfChart(this.node_id, this.node_name);
|
||||
request_node_perf_chart(window.graphPeriod, this.node_id, this.node_name);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "nodePerfChart") {
|
||||
if (event.msg == "NodePerfChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -33,8 +34,8 @@ export class NodeRamChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.NodePerfChart.nodes.length; i++) {
|
||||
let node = event.NodePerfChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_node_status } from "../../wasm/wasm_pipe";
|
||||
import { Component } from "./component";
|
||||
|
||||
export class NodeStatus implements Component {
|
||||
@ -6,16 +7,16 @@ export class NodeStatus implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestNodeStatus();
|
||||
request_node_status();
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "nodeStatus") {
|
||||
if (event.msg == "NodeStatus") {
|
||||
let status = document.getElementById("nodeStatus");
|
||||
let html = "";
|
||||
if (status) {
|
||||
for (let i = 0; i < event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i = 0; i < event.NodeStatus.nodes.length; i++) {
|
||||
let node = event.NodeStatus.nodes[i];
|
||||
let color = "danger";
|
||||
if (node.last_seen > 86400) {
|
||||
color = "secondary";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_packet_chart } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -17,11 +18,11 @@ export class PacketsChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestPacketChart();
|
||||
request_packet_chart(window.graphPeriod);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "packetChart") {
|
||||
if (event.msg == "PacketChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -29,8 +30,8 @@ export class PacketsChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.PacketChart.nodes.length; i++) {
|
||||
let node = event.PacketChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_packet_chart_for_node } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -21,11 +22,11 @@ export class PacketsChartSingle implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestPacketChartSingle(this.node_id, this.node_name);
|
||||
request_packet_chart_for_node(window.graphPeriod, this.node_id, this.node_name);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "packetChart") {
|
||||
if (event.msg == "PacketChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -33,8 +34,8 @@ export class PacketsChartSingle implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.PacketChart.nodes.length; i++) {
|
||||
let node = event.PacketChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_root_heat } from "../../wasm/wasm_pipe";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
@ -13,17 +14,17 @@ export class RootHeat implements Component {
|
||||
}
|
||||
|
||||
wireup(): void {
|
||||
window.bus.requestSiteRootHeat();
|
||||
request_root_heat(window.graphPeriod);
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
this.counter++;
|
||||
if (this.counter % 10 == 0)
|
||||
window.bus.requestSiteRootHeat();
|
||||
request_root_heat(window.graphPeriod);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rootHeat") {
|
||||
if (event.msg == "RootHeat") {
|
||||
this.myChart.hideLoading();
|
||||
|
||||
let categories: string[] = [];
|
||||
@ -32,7 +33,7 @@ export class RootHeat implements Component {
|
||||
let count = 0;
|
||||
let data: any[] = [];
|
||||
let keys: string[] = [];
|
||||
for (const key in event.data) {
|
||||
for (const key in event.RootHeat.data) {
|
||||
keys.push(key);
|
||||
}
|
||||
keys = keys.sort().reverse();
|
||||
@ -45,14 +46,14 @@ export class RootHeat implements Component {
|
||||
// Push the X axis values
|
||||
if (first) {
|
||||
first = false;
|
||||
for (let i=0; i<event.data[key].length; i++) {
|
||||
x.push(event.data[key][i][0]);
|
||||
for (let i=0; i<event.RootHeat.data[key].length; i++) {
|
||||
x.push(event.RootHeat.data[key][i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create all the series entries for this category
|
||||
for (let i=0; i<event.data[key].length; i++) {
|
||||
data.push([i, count, event.data[key][i][1].toFixed(1)]);
|
||||
for (let i=0; i<event.RootHeat.data[key].length; i++) {
|
||||
data.push([i, count, event.RootHeat.data[key][i][1].toFixed(1)]);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_rtt_chart_for_circuit } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class RttChartCircuit implements Component {
|
||||
div: HTMLElement;
|
||||
@ -9,7 +10,7 @@ export class RttChartCircuit implements Component {
|
||||
circuitId: string;
|
||||
|
||||
constructor(circuitId: string) {
|
||||
this.circuitId = circuitId;
|
||||
this.circuitId = decodeURI(circuitId);
|
||||
this.div = document.getElementById("rttChart") as HTMLElement;
|
||||
this.myChart = echarts.init(this.div);
|
||||
this.myChart.showLoading();
|
||||
@ -19,11 +20,11 @@ export class RttChartCircuit implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestRttChartCircuit(this.circuitId);
|
||||
request_rtt_chart_for_circuit(window.graphPeriod, this.circuitId);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChartCircuit") {
|
||||
if (event.msg == "RttChartCircuit") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -31,8 +32,8 @@ export class RttChartCircuit implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.RttChartCircuit.nodes.length; i++) {
|
||||
let node = event.RttChartCircuit.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_rtt_chart } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class RttChart implements Component {
|
||||
div: HTMLElement;
|
||||
@ -17,11 +18,11 @@ export class RttChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestRttChart();
|
||||
request_rtt_chart(window.graphPeriod);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChart") {
|
||||
if (event.msg == "RttChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -29,8 +30,8 @@ export class RttChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.RttChart.nodes.length; i++) {
|
||||
let node = event.RttChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_rtt_chart_for_node } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -21,11 +22,11 @@ export class RttChartSingle implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestRttChartSingle(this.node_id, this.node_name);
|
||||
request_rtt_chart_for_node(window.graphPeriod, this.node_id, this.node_name);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChart") {
|
||||
if (event.msg == "RttChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -33,8 +34,8 @@ export class RttChartSingle implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.RttChart.nodes.length; i++) {
|
||||
let node = event.RttChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
|
@ -22,12 +22,12 @@ export class RttHisto implements Component {
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChart") {
|
||||
if (event.msg == "RttChart") {
|
||||
//console.log(event);
|
||||
this.download = [];
|
||||
this.x = [];
|
||||
for (let i = 0; i < event.histogram.length; i++) {
|
||||
this.download.push(event.histogram[i]);
|
||||
for (let i = 0; i < event.RttChart.histogram.length; i++) {
|
||||
this.download.push(event.RttChart.histogram[i]);
|
||||
this.x.push(i * 10);
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,12 @@ export class RttHistoSite implements Component {
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChartSite") {
|
||||
if (event.msg == "RttChartSite") {
|
||||
//console.log(event);
|
||||
this.download = [];
|
||||
this.x = [];
|
||||
for (let i = 0; i < event.histogram.length; i++) {
|
||||
this.download.push(event.histogram[i]);
|
||||
for (let i = 0; i < event.RttChartSite.histogram.length; i++) {
|
||||
this.download.push(event.RttChartSite.histogram[i]);
|
||||
this.x.push(i * 10);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_rtt_chart_for_site } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class RttChartSite implements Component {
|
||||
div: HTMLElement;
|
||||
@ -19,11 +20,11 @@ export class RttChartSite implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestRttChartSite(this.siteId);
|
||||
request_rtt_chart_for_site(window.graphPeriod, this.siteId);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "rttChartSite") {
|
||||
if (event.msg == "RttChartSite") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -31,8 +32,8 @@ export class RttChartSite implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.RttChartSite.nodes.length; i++) {
|
||||
let node = event.RttChartSite.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//console.log(node);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_site_parents } from "../../wasm/wasm_pipe";
|
||||
import { makeUrl } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
|
||||
@ -9,18 +10,18 @@ export class SiteBreadcrumbs implements Component {
|
||||
}
|
||||
|
||||
wireup(): void {
|
||||
window.bus.requestSiteParents(this.siteId);
|
||||
request_site_parents(this.siteId);
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "site_parents") {
|
||||
if (event.msg == "SiteParents") {
|
||||
//console.log(event.data);
|
||||
let div = document.getElementById("siteName") as HTMLDivElement;
|
||||
let html = "";
|
||||
let crumbs = event.data.reverse();
|
||||
let crumbs = event.SiteParents.data.reverse();
|
||||
for (let i = 0; i < crumbs.length-1; i++) {
|
||||
let url = makeUrl(crumbs[i][0], crumbs[i][1]);
|
||||
html += "<a href='#" + url + "' onclick='window.router.goto(\"" + url + "\")'>" + crumbs[i][1] + "</a> | ";
|
||||
@ -28,11 +29,11 @@ export class SiteBreadcrumbs implements Component {
|
||||
html += crumbs[crumbs.length-1][1] + " | ";
|
||||
html += "<select id='siteChildren'></select>";
|
||||
div.innerHTML = html;
|
||||
} else if (event.msg == "site_children") {
|
||||
} else if (event.msg == "SiteChildren") {
|
||||
//console.log(event.data);
|
||||
let html = "<option value=''>-- Children --</option>";
|
||||
for (let i=0; i<event.data.length; i++) {
|
||||
html += "<option value='" + makeUrl(event.data[i][0], event.data[i][1]) + "'>" + event.data[i][2] + "</option>";
|
||||
for (let i=0; i<event.SiteChildren.data.length; i++) {
|
||||
html += "<option value='" + makeUrl(event.SiteChildren.data[i][0], event.SiteChildren.data[i][1]) + "'>" + event.SiteChildren.data[i][2] + "</option>";
|
||||
}
|
||||
let select = document.getElementById("siteChildren") as HTMLSelectElement;
|
||||
select.innerHTML = html;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_site_heat } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class SiteHeat implements Component {
|
||||
div: HTMLElement;
|
||||
@ -8,24 +9,26 @@ export class SiteHeat implements Component {
|
||||
siteId: string;
|
||||
|
||||
constructor(siteId: string) {
|
||||
this.siteId = siteId;
|
||||
this.siteId = decodeURI(siteId);
|
||||
this.div = document.getElementById("rootHeat") as HTMLElement;
|
||||
this.myChart = echarts.init(this.div);
|
||||
this.myChart.showLoading();
|
||||
}
|
||||
|
||||
wireup(): void {
|
||||
window.bus.requestSiteHeat(this.siteId);
|
||||
console.log("SiteHeat wireup");
|
||||
request_site_heat(window.graphPeriod, this.siteId);
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
console.log("SiteHeat ontick");
|
||||
this.counter++;
|
||||
if (this.counter % 10 == 0)
|
||||
window.bus.requestSiteHeat(this.siteId);
|
||||
request_site_heat(window.graphPeriod, this.siteId);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "siteHeat") {
|
||||
if (event.msg == "SiteHeat") {
|
||||
this.myChart.hideLoading();
|
||||
|
||||
let categories: string[] = [];
|
||||
@ -34,7 +37,7 @@ export class SiteHeat implements Component {
|
||||
let count = 0;
|
||||
let data: any[] = [];
|
||||
let keys: string[] = [];
|
||||
for (const key in event.data) {
|
||||
for (const key in event.SiteHeat.data) {
|
||||
keys.push(key);
|
||||
}
|
||||
keys = keys.sort().reverse();
|
||||
@ -47,14 +50,14 @@ export class SiteHeat implements Component {
|
||||
// Push the X axis values
|
||||
if (first) {
|
||||
first = false;
|
||||
for (let i=0; i<event.data[key].length; i++) {
|
||||
x.push(event.data[key][i][0]);
|
||||
for (let i=0; i<event.SiteHeat.data[key].length; i++) {
|
||||
x.push(event.SiteHeat.data[key][i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create all the series entries for this category
|
||||
for (let i=0; i<event.data[key].length; i++) {
|
||||
data.push([i, count, event.data[key][i][1].toFixed(1)]);
|
||||
for (let i=0; i<event.SiteHeat.data[key].length; i++) {
|
||||
data.push([i, count, event.SiteHeat.data[key][i][1].toFixed(1)]);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { mbps_to_bps } from "../site_tree/site_tree";
|
||||
import { Component } from "./component";
|
||||
import { request_site_info } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class SiteInfo implements Component {
|
||||
siteId: string;
|
||||
@ -11,25 +12,25 @@ export class SiteInfo implements Component {
|
||||
}
|
||||
|
||||
wireup(): void {
|
||||
window.bus.requestSiteInfo(this.siteId);
|
||||
request_site_info(decodeURI(this.siteId));
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
this.count++;
|
||||
if (this.count % 10 == 0) {
|
||||
window.bus.requestSiteInfo(this.siteId);
|
||||
request_site_info(decodeURI(this.siteId));
|
||||
}
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "site_info") {
|
||||
if (event.msg == "SiteInfo") {
|
||||
//console.log(event.data);
|
||||
let div = document.getElementById("siteInfo") as HTMLDivElement;
|
||||
let html = "";
|
||||
html += "<table class='table table-striped'>";
|
||||
html += "<tr><td>Max:</td><td>" + scaleNumber(event.data.max_down * mbps_to_bps) + " / " + scaleNumber(event.data.max_up * mbps_to_bps) + "</td></tr>";
|
||||
html += "<tr><td>Current:</td><td>" + scaleNumber(event.data.current_down) + " / " + scaleNumber(event.data.current_up) + "</td></tr>";
|
||||
html += "<tr><td>Current RTT:</td><td>" + event.data.current_rtt / 100.0 + " ms</td></tr>";
|
||||
html += "<tr><td>Max:</td><td>" + scaleNumber(event.SiteInfo.data.max_down * mbps_to_bps) + " / " + scaleNumber(event.SiteInfo.data.max_up * mbps_to_bps) + "</td></tr>";
|
||||
html += "<tr><td>Current:</td><td>" + scaleNumber(event.SiteInfo.data.current_down) + " / " + scaleNumber(event.SiteInfo.data.current_up) + "</td></tr>";
|
||||
html += "<tr><td>Current RTT:</td><td>" + event.SiteInfo.data.current_rtt / 100.0 + " ms</td></tr>";
|
||||
html += "</table>";
|
||||
div.innerHTML = html;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_site_stack } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -7,6 +8,7 @@ export class SiteStackChart implements Component {
|
||||
myChart: echarts.ECharts;
|
||||
chartMade: boolean = false;
|
||||
siteId: string;
|
||||
counter: number = 0;
|
||||
|
||||
constructor(siteId: string) {
|
||||
this.siteId = siteId;
|
||||
@ -19,11 +21,14 @@ export class SiteStackChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestThroughputStackSite(this.siteId);
|
||||
this.counter++;
|
||||
if (this.counter % 10 == 0 || this.counter == 0) {
|
||||
request_site_stack(window.graphPeriod, this.siteId);
|
||||
}
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "siteStack") {
|
||||
if (event.msg == "SiteStack") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -31,8 +36,8 @@ export class SiteStackChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i = 0; i < event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i = 0; i < event.SiteStack.nodes.length; i++) {
|
||||
let node = event.SiteStack.nodes[i];
|
||||
if (node.node_name != "Root") {
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_throughput_chart } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -17,11 +18,11 @@ export class ThroughputChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestThroughputChart();
|
||||
request_throughput_chart(window.graphPeriod);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "bitsChart") {
|
||||
if (event.msg == "BitsChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -29,8 +30,8 @@ export class ThroughputChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.BitsChart.nodes.length; i++) {
|
||||
let node = event.BitsChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_throughput_chart_for_circuit } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class ThroughputCircuitChart implements Component {
|
||||
div: HTMLElement;
|
||||
@ -19,11 +20,11 @@ export class ThroughputCircuitChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestThroughputChartCircuit(this.circuitId);
|
||||
request_throughput_chart_for_circuit(window.graphPeriod, this.circuitId);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "bitsChartCircuit") {
|
||||
if (event.msg == "BitsChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -31,8 +32,8 @@ export class ThroughputCircuitChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.BitsChart.nodes.length; i++) {
|
||||
let node = event.BitsChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { request_throughput_chart_for_node } from "../../wasm/wasm_pipe";
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
@ -21,11 +22,11 @@ export class ThroughputChartSingle implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestThroughputChartSingle(this.node_id, this.node_name);
|
||||
request_throughput_chart_for_node(window.graphPeriod, this.node_id, this.node_name);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "bitsChart") {
|
||||
if (event.msg == "BitsChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -33,8 +34,8 @@ export class ThroughputChartSingle implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.BitsChart.nodes.length; i++) {
|
||||
let node = event.BitsChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { scaleNumber } from "../helpers";
|
||||
import { Component } from "./component";
|
||||
import * as echarts from 'echarts';
|
||||
import { request_throughput_chart_for_site } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class ThroughputSiteChart implements Component {
|
||||
div: HTMLElement;
|
||||
@ -19,11 +20,11 @@ export class ThroughputSiteChart implements Component {
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
window.bus.requestThroughputChartSite(this.siteId);
|
||||
request_throughput_chart_for_site(window.graphPeriod, this.siteId);
|
||||
}
|
||||
|
||||
onmessage(event: any): void {
|
||||
if (event.msg == "bitsChartSite") {
|
||||
if (event.msg == "BitsChart") {
|
||||
let series: echarts.SeriesOption[] = [];
|
||||
|
||||
// Iterate all provides nodes and create a set of series for each,
|
||||
@ -31,8 +32,8 @@ export class ThroughputSiteChart implements Component {
|
||||
let x: any[] = [];
|
||||
let first = true;
|
||||
let legend: string[] = [];
|
||||
for (let i=0; i<event.nodes.length; i++) {
|
||||
let node = event.nodes[i];
|
||||
for (let i=0; i<event.BitsChart.nodes.length; i++) {
|
||||
let node = event.BitsChart.nodes[i];
|
||||
legend.push(node.node_name);
|
||||
//legend.push(node.node_name + " UL");
|
||||
//console.log(node);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import html from './template.html';
|
||||
import { Page } from '../page'
|
||||
import { getValueFromForm } from '../helpers';
|
||||
import { send_login } from '../../wasm/wasm_pipe';
|
||||
|
||||
export class LoginPage implements Page {
|
||||
constructor() {
|
||||
@ -61,26 +62,19 @@ export class LoginPage implements Page {
|
||||
btn.innerHTML = "<i class=\"fa-solid fa-spinner fa-spin\"></i>";
|
||||
}
|
||||
|
||||
let data = {
|
||||
msg: "login",
|
||||
license: license,
|
||||
username: username,
|
||||
password: password,
|
||||
};
|
||||
let json: string = JSON.stringify(data);
|
||||
window.bus.ws.send(json);
|
||||
send_login(license, username, password);
|
||||
}
|
||||
|
||||
onmessage(event: any) {
|
||||
if (event.msg) {
|
||||
if (event.msg == "loginOk") {
|
||||
if (event.msg == "LoginOk") {
|
||||
// TODO: Store the credentials globally
|
||||
window.login = event;
|
||||
window.login = event.LoginOk;
|
||||
window.auth.hasCredentials = true;
|
||||
window.auth.token = event.token;
|
||||
localStorage.setItem("token", event.token);
|
||||
window.auth.token = event.LoginOk.token;
|
||||
localStorage.setItem("token", event.LoginOk.token);
|
||||
window.router.goto("dashboard");
|
||||
} else if (event.msg = "loginFail") {
|
||||
} else if (event.msg = "LoginFail") {
|
||||
alert("Login failed");
|
||||
let btn = document.getElementById('btnLogin');
|
||||
if (btn) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import html from './template.html';
|
||||
import { Page } from '../page'
|
||||
import { siteIcon } from '../helpers';
|
||||
import { request_search } from "../../wasm/wasm_pipe";
|
||||
|
||||
export class MenuPage implements Page {
|
||||
activePanel: string;
|
||||
@ -56,7 +57,7 @@ export class MenuPage implements Page {
|
||||
if (r) {
|
||||
r.style.display = "none";
|
||||
}
|
||||
window.bus.sendSearch(term);
|
||||
request_search(term);
|
||||
}
|
||||
|
||||
onmessage(event: any) {
|
||||
@ -72,8 +73,8 @@ export class MenuPage implements Page {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case "search": {
|
||||
this.searchResult(event.hits);
|
||||
case "SearchResult": {
|
||||
this.searchResult(event.SearchResult.hits);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ export class SitePage implements Page {
|
||||
this.components.forEach(component => {
|
||||
component.wireup();
|
||||
});
|
||||
window.bus.requestThroughputStackSite(this.siteId);
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
|
@ -4,6 +4,7 @@ import { MenuPage } from '../menu/menu';
|
||||
import { Component } from '../components/component';
|
||||
import mermaid from 'mermaid';
|
||||
import { makeUrl, rttColor, scaleNumber, siteIcon, usageColor } from '../helpers';
|
||||
import { request_node_status, request_tree } from '../../wasm/wasm_pipe';
|
||||
|
||||
export class SiteTreePage implements Page {
|
||||
menu: MenuPage;
|
||||
@ -26,7 +27,7 @@ export class SiteTreePage implements Page {
|
||||
this.components.forEach(component => {
|
||||
component.wireup();
|
||||
});
|
||||
window.bus.requestNodeStatus();
|
||||
request_node_status();
|
||||
}
|
||||
|
||||
ontick(): void {
|
||||
@ -48,20 +49,20 @@ export class SiteTreePage implements Page {
|
||||
component.onmessage(event);
|
||||
});
|
||||
|
||||
if (event.msg == "nodeStatus") {
|
||||
if (event.msg == "NodeStatus") {
|
||||
let drop_down = document.getElementById("shaper_node_select") as HTMLSelectElement;
|
||||
if (drop_down) {
|
||||
let items = "";
|
||||
for (let i = 0; i < event.nodes.length; i++) {
|
||||
for (let i = 0; i < event.NodeStatus.nodes.length; i++) {
|
||||
let isSelected = "";
|
||||
if (i ==0 || this.selectedNode == event.nodes[i].node_id) {
|
||||
if (i ==0 || this.selectedNode == event.NodeStatus.nodes[i].node_id) {
|
||||
isSelected = "selected";
|
||||
if (i == 0) {
|
||||
this.selectedNode = event.nodes[i].node_id;
|
||||
this.selectedNode = event.NodeStatus.nodes[i].node_id;
|
||||
fetchTree(this.selectedNode);
|
||||
}
|
||||
}
|
||||
items += "<option " + isSelected + " value='" + event.nodes[i].node_id + "'>" + event.nodes[i].node_name + "</option>";
|
||||
items += "<option " + isSelected + " value='" + event.NodeStatus.nodes[i].node_id + "'>" + event.NodeStatus.nodes[i].node_name + "</option>";
|
||||
}
|
||||
drop_down.innerHTML = items;
|
||||
drop_down.onchange = () => {
|
||||
@ -72,15 +73,15 @@ export class SiteTreePage implements Page {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.msg == "site_tree") {
|
||||
buildTree(event.data);
|
||||
if (event.msg == "SiteTree") {
|
||||
buildTree(event.SiteTree.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchTree(parent: string) {
|
||||
window.bus.requestTree(parent);
|
||||
request_tree(parent);
|
||||
}
|
||||
|
||||
class TreeItem {
|
||||
|
170
src/rust/long_term_stats/site_build/wasm/wasm_pipe.d.ts
vendored
Normal file
170
src/rust/long_term_stats/site_build/wasm/wasm_pipe.d.ts
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
export function connect_wasm_pipe(url: string): void;
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function is_wasm_connected(): boolean;
|
||||
/**
|
||||
* @param {string} token
|
||||
*/
|
||||
export function send_token(token: string): void;
|
||||
/**
|
||||
* @param {string} license
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
*/
|
||||
export function send_login(license: string, username: string, password: string): void;
|
||||
/**
|
||||
*/
|
||||
export function request_node_status(): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_packet_chart(period: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_packet_chart_for_node(period: string, node_id: string, node_name: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_throughput_chart(period: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_throughput_chart_for_site(period: string, site_id: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_throughput_chart_for_node(period: string, node_id: string, node_name: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_throughput_chart_for_circuit(period: string, circuit_id: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_stack(period: string, site_id: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_rtt_chart(period: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_rtt_chart_for_site(period: string, site_id: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_rtt_chart_for_node(period: string, node_id: string, node_name: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_rtt_chart_for_circuit(period: string, circuit_id: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_node_perf_chart(period: string, node_id: string, node_name: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_root_heat(period: string): void;
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_heat(period: string, site_id: string): void;
|
||||
/**
|
||||
* @param {string} parent
|
||||
*/
|
||||
export function request_tree(parent: string): void;
|
||||
/**
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_info(site_id: string): void;
|
||||
/**
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_parents(site_id: string): void;
|
||||
/**
|
||||
* @param {string} term
|
||||
*/
|
||||
export function request_search(term: string): void;
|
||||
/**
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_circuit_info(circuit_id: string): void;
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly connect_wasm_pipe: (a: number, b: number) => void;
|
||||
readonly is_wasm_connected: () => number;
|
||||
readonly send_token: (a: number, b: number) => void;
|
||||
readonly send_login: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly request_node_status: () => void;
|
||||
readonly request_packet_chart: (a: number, b: number) => void;
|
||||
readonly request_packet_chart_for_node: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly request_throughput_chart: (a: number, b: number) => void;
|
||||
readonly request_throughput_chart_for_site: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_throughput_chart_for_node: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly request_throughput_chart_for_circuit: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_site_stack: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_rtt_chart: (a: number, b: number) => void;
|
||||
readonly request_rtt_chart_for_site: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_rtt_chart_for_node: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly request_rtt_chart_for_circuit: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_node_perf_chart: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||
readonly request_root_heat: (a: number, b: number) => void;
|
||||
readonly request_site_heat: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly request_tree: (a: number, b: number) => void;
|
||||
readonly request_site_info: (a: number, b: number) => void;
|
||||
readonly request_site_parents: (a: number, b: number) => void;
|
||||
readonly request_search: (a: number, b: number) => void;
|
||||
readonly request_circuit_info: (a: number, b: number) => void;
|
||||
readonly __wbindgen_malloc: (a: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
|
||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h66d1b1d022c5cd85: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
||||
readonly __wbindgen_exn_store: (a: number) => void;
|
||||
}
|
||||
|
||||
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||
/**
|
||||
* Instantiates the given `module`, which can either be bytes or
|
||||
* a precompiled `WebAssembly.Module`.
|
||||
*
|
||||
* @param {SyncInitInput} module
|
||||
*
|
||||
* @returns {InitOutput}
|
||||
*/
|
||||
export function initSync(module: SyncInitInput): InitOutput;
|
||||
|
||||
/**
|
||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||
*
|
||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||
*
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
692
src/rust/long_term_stats/site_build/wasm/wasm_pipe.js
Normal file
692
src/rust/long_term_stats/site_build/wasm/wasm_pipe.js
Normal file
@ -0,0 +1,692 @@
|
||||
let wasm;
|
||||
|
||||
const heap = new Array(128).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
function getObject(idx) { return heap[idx]; }
|
||||
|
||||
function debugString(val) {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
if (type == 'number' || type == 'boolean' || val == null) {
|
||||
return `${val}`;
|
||||
}
|
||||
if (type == 'string') {
|
||||
return `"${val}"`;
|
||||
}
|
||||
if (type == 'symbol') {
|
||||
const description = val.description;
|
||||
if (description == null) {
|
||||
return 'Symbol';
|
||||
} else {
|
||||
return `Symbol(${description})`;
|
||||
}
|
||||
}
|
||||
if (type == 'function') {
|
||||
const name = val.name;
|
||||
if (typeof name == 'string' && name.length > 0) {
|
||||
return `Function(${name})`;
|
||||
} else {
|
||||
return 'Function';
|
||||
}
|
||||
}
|
||||
// objects
|
||||
if (Array.isArray(val)) {
|
||||
const length = val.length;
|
||||
let debug = '[';
|
||||
if (length > 0) {
|
||||
debug += debugString(val[0]);
|
||||
}
|
||||
for(let i = 1; i < length; i++) {
|
||||
debug += ', ' + debugString(val[i]);
|
||||
}
|
||||
debug += ']';
|
||||
return debug;
|
||||
}
|
||||
// Test for built-in
|
||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||
let className;
|
||||
if (builtInMatches.length > 1) {
|
||||
className = builtInMatches[1];
|
||||
} else {
|
||||
// Failed to match the standard '[object ClassName]'
|
||||
return toString.call(val);
|
||||
}
|
||||
if (className == 'Object') {
|
||||
// we're a user defined class or Object
|
||||
// JSON.stringify avoids problems with cycles, and is generally much
|
||||
// easier than looping through ownProperties of `val`.
|
||||
try {
|
||||
return 'Object(' + JSON.stringify(val) + ')';
|
||||
} catch (_) {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
// errors
|
||||
if (val instanceof Error) {
|
||||
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||
}
|
||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||
return className;
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
let cachedUint8Memory0 = null;
|
||||
|
||||
function getUint8Memory0() {
|
||||
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
|
||||
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8Memory0;
|
||||
}
|
||||
|
||||
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
||||
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length) >>> 0;
|
||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len) >>> 0;
|
||||
|
||||
const mem = getUint8Memory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;
|
||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let cachedInt32Memory0 = null;
|
||||
|
||||
function getInt32Memory0() {
|
||||
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
|
||||
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedInt32Memory0;
|
||||
}
|
||||
|
||||
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||
|
||||
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function dropObject(idx) {
|
||||
if (idx < 132) return;
|
||||
heap[idx] = heap_next;
|
||||
heap_next = idx;
|
||||
}
|
||||
|
||||
function takeObject(idx) {
|
||||
const ret = getObject(idx);
|
||||
dropObject(idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
function makeMutClosure(arg0, arg1, dtor, f) {
|
||||
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||
const real = (...args) => {
|
||||
// First up with a closure we increment the internal reference
|
||||
// count. This ensures that the Rust closure environment won't
|
||||
// be deallocated while we're invoking it.
|
||||
state.cnt++;
|
||||
const a = state.a;
|
||||
state.a = 0;
|
||||
try {
|
||||
return f(a, state.b, ...args);
|
||||
} finally {
|
||||
if (--state.cnt === 0) {
|
||||
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
|
||||
|
||||
} else {
|
||||
state.a = a;
|
||||
}
|
||||
}
|
||||
};
|
||||
real.original = state;
|
||||
|
||||
return real;
|
||||
}
|
||||
function __wbg_adapter_12(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h66d1b1d022c5cd85(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function notDefined(what) { return () => { throw new Error(`${what} is not defined`); }; }
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
export function connect_wasm_pipe(url) {
|
||||
const ptr0 = passStringToWasm0(url, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.connect_wasm_pipe(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function is_wasm_connected() {
|
||||
const ret = wasm.is_wasm_connected();
|
||||
return ret !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} token
|
||||
*/
|
||||
export function send_token(token) {
|
||||
const ptr0 = passStringToWasm0(token, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.send_token(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} license
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
*/
|
||||
export function send_login(license, username, password) {
|
||||
const ptr0 = passStringToWasm0(license, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(username, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
wasm.send_login(ptr0, len0, ptr1, len1, ptr2, len2);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
export function request_node_status() {
|
||||
wasm.request_node_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_packet_chart(period) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_packet_chart(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_packet_chart_for_node(period, node_id, node_name) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(node_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(node_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
wasm.request_packet_chart_for_node(ptr0, len0, ptr1, len1, ptr2, len2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_throughput_chart(period) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_throughput_chart(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_throughput_chart_for_site(period, site_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_throughput_chart_for_site(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_throughput_chart_for_node(period, node_id, node_name) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(node_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(node_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
wasm.request_throughput_chart_for_node(ptr0, len0, ptr1, len1, ptr2, len2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_throughput_chart_for_circuit(period, circuit_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(circuit_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_throughput_chart_for_circuit(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_stack(period, site_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_site_stack(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_rtt_chart(period) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_rtt_chart(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_rtt_chart_for_site(period, site_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_rtt_chart_for_site(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_rtt_chart_for_node(period, node_id, node_name) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(node_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(node_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
wasm.request_rtt_chart_for_node(ptr0, len0, ptr1, len1, ptr2, len2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_rtt_chart_for_circuit(period, circuit_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(circuit_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_rtt_chart_for_circuit(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} node_id
|
||||
* @param {string} node_name
|
||||
*/
|
||||
export function request_node_perf_chart(period, node_id, node_name) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(node_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(node_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
wasm.request_node_perf_chart(ptr0, len0, ptr1, len1, ptr2, len2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
*/
|
||||
export function request_root_heat(period) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_root_heat(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} period
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_heat(period, site_id) {
|
||||
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
wasm.request_site_heat(ptr0, len0, ptr1, len1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} parent
|
||||
*/
|
||||
export function request_tree(parent) {
|
||||
const ptr0 = passStringToWasm0(parent, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_tree(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_info(site_id) {
|
||||
const ptr0 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_site_info(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} site_id
|
||||
*/
|
||||
export function request_site_parents(site_id) {
|
||||
const ptr0 = passStringToWasm0(site_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_site_parents(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} term
|
||||
*/
|
||||
export function request_search(term) {
|
||||
const ptr0 = passStringToWasm0(term, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_search(ptr0, len0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} circuit_id
|
||||
*/
|
||||
export function request_circuit_info(circuit_id) {
|
||||
const ptr0 = passStringToWasm0(circuit_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
wasm.request_circuit_info(ptr0, len0);
|
||||
}
|
||||
|
||||
function handleError(f, args) {
|
||||
try {
|
||||
return f.apply(this, args);
|
||||
} catch (e) {
|
||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
||||
}
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
async function __wbg_load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function __wbg_get_imports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||
const ret = debugString(getObject(arg1));
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getInt32Memory0()[arg0 / 4 + 1] = len1;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbg_log_cd48b3599daf93ee = function(arg0, arg1) {
|
||||
console.log(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_windowbusgetToken_eab6ac8f06d69af2 = function(arg0) {
|
||||
const ret = window.bus.getToken();
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getInt32Memory0()[arg0 / 4 + 1] = len1;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
|
||||
};
|
||||
imports.wbg.__wbg_send_737fddb36434277e = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
getObject(arg0).send(getArrayU8FromWasm0(arg1, arg2));
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_data_ef47af9c565d228b = function(arg0) {
|
||||
const ret = getObject(arg0).data;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_instanceof_ArrayBuffer_de688b806c28ff28 = function(arg0) {
|
||||
let result;
|
||||
try {
|
||||
result = getObject(arg0) instanceof ArrayBuffer;
|
||||
} catch {
|
||||
result = false;
|
||||
}
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new_bc5d9aad3f9ac80e = function(arg0) {
|
||||
const ret = new Uint8Array(getObject(arg0));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_length_d9c4ded7e708c6a1 = function(arg0) {
|
||||
const ret = getObject(arg0).length;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
const ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_buffer_fcbfb6d88b2732e9 = function(arg0) {
|
||||
const ret = getObject(arg0).buffer;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_set_4b3aa8445ac1e91c = function(arg0, arg1, arg2) {
|
||||
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
|
||||
};
|
||||
imports.wbg.__wbg_windowonMessage_5c5b80d5376153dc = function(arg0, arg1) {
|
||||
let deferred0_0;
|
||||
let deferred0_1;
|
||||
try {
|
||||
deferred0_0 = arg0;
|
||||
deferred0_1 = arg1;
|
||||
window.onMessage(getStringFromWasm0(arg0, arg1));
|
||||
} finally {
|
||||
wasm.__wbindgen_free(deferred0_0, deferred0_1);
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbg_windowonAuthFail_ddfdfcd594ff15b8 = typeof window.onAuthFail == 'function' ? window.onAuthFail : notDefined('window.onAuthFail');
|
||||
imports.wbg.__wbg_windowonAuthOk_9cd9fb8f74884ca4 = function(arg0, arg1, arg2, arg3, arg4, arg5) {
|
||||
let deferred0_0;
|
||||
let deferred0_1;
|
||||
let deferred1_0;
|
||||
let deferred1_1;
|
||||
let deferred2_0;
|
||||
let deferred2_1;
|
||||
try {
|
||||
deferred0_0 = arg0;
|
||||
deferred0_1 = arg1;
|
||||
deferred1_0 = arg2;
|
||||
deferred1_1 = arg3;
|
||||
deferred2_0 = arg4;
|
||||
deferred2_1 = arg5;
|
||||
window.onAuthOk(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5));
|
||||
} finally {
|
||||
wasm.__wbindgen_free(deferred0_0, deferred0_1);
|
||||
wasm.__wbindgen_free(deferred1_0, deferred1_1);
|
||||
wasm.__wbindgen_free(deferred2_0, deferred2_1);
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbg_new_39e958ac9d5cae7d = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = new WebSocket(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||
const ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_setbinaryType_2e2320b177c86b17 = function(arg0, arg1) {
|
||||
getObject(arg0).binaryType = takeObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbg_setonmessage_493b82147081ec7e = function(arg0, arg1) {
|
||||
getObject(arg0).onmessage = getObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbg_setonclose_6b22bc5d93628786 = function(arg0, arg1) {
|
||||
getObject(arg0).onclose = getObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbg_setonerror_9f7532626d7a9ce2 = function(arg0, arg1) {
|
||||
getObject(arg0).onerror = getObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbg_setonopen_6fd8b28538150568 = function(arg0, arg1) {
|
||||
getObject(arg0).onopen = getObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper1710 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_12);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper1711 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_12);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
function __wbg_init_memory(imports, maybe_memory) {
|
||||
|
||||
}
|
||||
|
||||
function __wbg_finalize_init(instance, module) {
|
||||
wasm = instance.exports;
|
||||
__wbg_init.__wbindgen_wasm_module = module;
|
||||
cachedInt32Memory0 = null;
|
||||
cachedUint8Memory0 = null;
|
||||
|
||||
|
||||
return wasm;
|
||||
}
|
||||
|
||||
function initSync(module) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
__wbg_init_memory(imports);
|
||||
|
||||
if (!(module instanceof WebAssembly.Module)) {
|
||||
module = new WebAssembly.Module(module);
|
||||
}
|
||||
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
async function __wbg_init(input) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
if (typeof input === 'undefined') {
|
||||
input = new URL('wasm_pipe_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
__wbg_init_memory(imports);
|
||||
|
||||
const { instance, module } = await __wbg_load(await input, imports);
|
||||
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
export { initSync }
|
||||
export default __wbg_init;
|
BIN
src/rust/long_term_stats/site_build/wasm/wasm_pipe_bg.wasm
Normal file
BIN
src/rust/long_term_stats/site_build/wasm/wasm_pipe_bg.wasm
Normal file
Binary file not shown.
33
src/rust/long_term_stats/site_build/wasm/wasm_pipe_bg.wasm.d.ts
vendored
Normal file
33
src/rust/long_term_stats/site_build/wasm/wasm_pipe_bg.wasm.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export function connect_wasm_pipe(a: number, b: number): void;
|
||||
export function is_wasm_connected(): number;
|
||||
export function send_token(a: number, b: number): void;
|
||||
export function send_login(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
||||
export function request_node_status(): void;
|
||||
export function request_packet_chart(a: number, b: number): void;
|
||||
export function request_packet_chart_for_node(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
||||
export function request_throughput_chart(a: number, b: number): void;
|
||||
export function request_throughput_chart_for_site(a: number, b: number, c: number, d: number): void;
|
||||
export function request_throughput_chart_for_node(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
||||
export function request_throughput_chart_for_circuit(a: number, b: number, c: number, d: number): void;
|
||||
export function request_site_stack(a: number, b: number, c: number, d: number): void;
|
||||
export function request_rtt_chart(a: number, b: number): void;
|
||||
export function request_rtt_chart_for_site(a: number, b: number, c: number, d: number): void;
|
||||
export function request_rtt_chart_for_node(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
||||
export function request_rtt_chart_for_circuit(a: number, b: number, c: number, d: number): void;
|
||||
export function request_node_perf_chart(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
||||
export function request_root_heat(a: number, b: number): void;
|
||||
export function request_site_heat(a: number, b: number, c: number, d: number): void;
|
||||
export function request_tree(a: number, b: number): void;
|
||||
export function request_site_info(a: number, b: number): void;
|
||||
export function request_site_parents(a: number, b: number): void;
|
||||
export function request_search(a: number, b: number): void;
|
||||
export function request_circuit_info(a: number, b: number): void;
|
||||
export function __wbindgen_malloc(a: number): number;
|
||||
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
||||
export const __wbindgen_export_2: WebAssembly.Table;
|
||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h66d1b1d022c5cd85(a: number, b: number, c: number): void;
|
||||
export function __wbindgen_free(a: number, b: number): void;
|
||||
export function __wbindgen_exn_store(a: number): void;
|
27
src/rust/long_term_stats/wasm_pipe/Cargo.toml
Normal file
27
src/rust/long_term_stats/wasm_pipe/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "wasm_pipe"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.86"
|
||||
js-sys = "0.3"
|
||||
miniz_oxide = "0.7.1"
|
||||
serde_cbor = "0" # For RFC8949/7409 format C binary objects
|
||||
wasm_pipe_types = { path = "../wasm_pipe_types" }
|
||||
serde_json = "1.0.96"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.22"
|
||||
features = [
|
||||
"BinaryType",
|
||||
"Blob",
|
||||
"ErrorEvent",
|
||||
"FileReader",
|
||||
"MessageEvent",
|
||||
"ProgressEvent",
|
||||
"WebSocket",
|
||||
]
|
5
src/rust/long_term_stats/wasm_pipe/build.sh
Executable file
5
src/rust/long_term_stats/wasm_pipe/build.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
cargo build --target wasm32-unknown-unknown --release
|
||||
wasm-bindgen --target web --out-dir staging/ ../../target/wasm32-unknown-unknown/release/wasm_pipe.wasm
|
||||
cp staging/* ../site_build/wasm
|
||||
cp staging/wasm_pipe_bg.wasm ../lts_node/web
|
224
src/rust/long_term_stats/wasm_pipe/src/lib.rs
Normal file
224
src/rust/long_term_stats/wasm_pipe/src/lib.rs
Normal file
@ -0,0 +1,224 @@
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_pipe_types::{WasmRequest, WasmResponse};
|
||||
use web_sys::{BinaryType, ErrorEvent, MessageEvent, WebSocket};
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
|
||||
#[wasm_bindgen(js_name = "window.bus.getToken")]
|
||||
fn get_token() -> String;
|
||||
|
||||
#[wasm_bindgen(js_name = "window.onAuthOk")]
|
||||
fn onAuthOk(token: String, name: String, license_key: String);
|
||||
|
||||
#[wasm_bindgen(js_name = "window.onAuthFail")]
|
||||
fn onAuthFail();
|
||||
|
||||
#[wasm_bindgen(js_name = "window.onMessage")]
|
||||
fn onMessage(json: String);
|
||||
}
|
||||
|
||||
static mut CONNECTED: bool = false;
|
||||
static mut WS: Option<WebSocket> = None;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn connect_wasm_pipe(url: String) {
|
||||
unsafe {
|
||||
if CONNECTED {
|
||||
log("Already connected");
|
||||
return;
|
||||
}
|
||||
WS = Some(WebSocket::new(&url).unwrap());
|
||||
if let Some(ws) = &mut WS {
|
||||
ws.set_binary_type(BinaryType::Arraybuffer);
|
||||
|
||||
ws.set_binary_type(BinaryType::Arraybuffer);
|
||||
let onmessage_callback = Closure::<dyn FnMut(_)>::new(move |e: MessageEvent| {
|
||||
log("Message Received");
|
||||
if let Ok(abuf) = e.data().dyn_into::<js_sys::ArrayBuffer>() {
|
||||
let array = js_sys::Uint8Array::new(&abuf);
|
||||
//let len = array.byte_length() as usize;
|
||||
let raw = array.to_vec();
|
||||
let decompressed = miniz_oxide::inflate::decompress_to_vec(&raw).unwrap();
|
||||
let msg: WasmResponse = serde_cbor::from_slice(&decompressed).unwrap();
|
||||
//log(&format!("Message: {:?}", msg));
|
||||
|
||||
match msg {
|
||||
WasmResponse::AuthOk { token, name, license_key } => {
|
||||
onAuthOk(token, name, license_key);
|
||||
}
|
||||
WasmResponse::AuthFail => {
|
||||
onAuthFail();
|
||||
}
|
||||
_ => {
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
onMessage(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let onerror_callback = Closure::<dyn FnMut(_)>::new(move |e: ErrorEvent| {
|
||||
log(&format!("Error Received: {e:?}"));
|
||||
CONNECTED = false;
|
||||
});
|
||||
let onclose_callback = Closure::<dyn FnMut(_)>::new(move |_e: ErrorEvent| {
|
||||
log("Close Received");
|
||||
CONNECTED = false;
|
||||
});
|
||||
let onopen_callback = Closure::<dyn FnMut(_)>::new(move |_e: ErrorEvent| {
|
||||
log("Open Received");
|
||||
CONNECTED = true;
|
||||
let token = get_token();
|
||||
send_token(token);
|
||||
});
|
||||
ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
|
||||
ws.set_onclose(Some(onclose_callback.as_ref().unchecked_ref()));
|
||||
ws.set_onerror(Some(onerror_callback.as_ref().unchecked_ref()));
|
||||
ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
|
||||
// Prevent closures from recursing
|
||||
onopen_callback.forget();
|
||||
onclose_callback.forget();
|
||||
onerror_callback.forget();
|
||||
onmessage_callback.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn is_wasm_connected() -> bool {
|
||||
unsafe { CONNECTED && WS.is_some() }
|
||||
}
|
||||
|
||||
fn build_message(msg: WasmRequest) -> Vec<u8> {
|
||||
let cbor = serde_cbor::to_vec(&msg).unwrap();
|
||||
miniz_oxide::deflate::compress_to_vec(&cbor, 8)
|
||||
}
|
||||
|
||||
fn send_message(msg: WasmRequest) {
|
||||
log(&format!("Sending message: {msg:?}"));
|
||||
let msg = build_message(msg);
|
||||
unsafe {
|
||||
if let Some(ws) = &mut WS {
|
||||
ws.send_with_u8_array(&msg).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn send_token(token: String) {
|
||||
//log(&format!("Sending token: {token}"));
|
||||
if token.is_empty() {
|
||||
log("Token is empty");
|
||||
return;
|
||||
}
|
||||
send_message(WasmRequest::Auth { token });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn send_login(license: String, username: String, password: String) {
|
||||
let msg = WasmRequest::Login { license, username, password };
|
||||
send_message(msg);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_node_status() {
|
||||
send_message(WasmRequest::GetNodeStatus);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_packet_chart(period: String) {
|
||||
send_message(WasmRequest::PacketChart { period });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_packet_chart_for_node(period: String, node_id: String, node_name: String) {
|
||||
send_message(WasmRequest::PacketChartSingle { period, node_id, node_name });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_throughput_chart(period: String) {
|
||||
send_message(WasmRequest::ThroughputChart { period });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_throughput_chart_for_site(period: String, site_id: String) {
|
||||
send_message(WasmRequest::ThroughputChartSite { period, site_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_throughput_chart_for_node(period: String, node_id: String, node_name: String) {
|
||||
send_message(WasmRequest::ThroughputChartSingle { period, node_id, node_name });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_throughput_chart_for_circuit(period: String, circuit_id: String) {
|
||||
send_message(WasmRequest::ThroughputChartCircuit { period, circuit_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_site_stack(period: String, site_id: String) {
|
||||
send_message(WasmRequest::SiteStack { period, site_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_rtt_chart(period: String) {
|
||||
send_message(WasmRequest::RttChart { period });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_rtt_chart_for_site(period: String, site_id: String) {
|
||||
send_message(WasmRequest::RttChartSite { period, site_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_rtt_chart_for_node(period: String, node_id: String, node_name: String) {
|
||||
send_message(WasmRequest::RttChartSingle { period, node_id, node_name });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_rtt_chart_for_circuit(period: String, circuit_id: String) {
|
||||
send_message(WasmRequest::RttChartCircuit { period, circuit_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_node_perf_chart(period: String, node_id: String, node_name: String) {
|
||||
send_message(WasmRequest::NodePerfChart { period, node_id, node_name });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_root_heat(period: String) {
|
||||
send_message(WasmRequest::RootHeat { period });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_site_heat(period: String, site_id: String) {
|
||||
send_message(WasmRequest::SiteHeat { period, site_id });
|
||||
}
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_tree(parent: String) {
|
||||
send_message(WasmRequest::Tree { parent });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_site_info(site_id: String) {
|
||||
send_message(WasmRequest::SiteInfo { site_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_site_parents(site_id: String) {
|
||||
send_message(WasmRequest::SiteParents { site_id });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_search(term: String) {
|
||||
send_message(WasmRequest::Search { term });
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn request_circuit_info(circuit_id: String) {
|
||||
send_message(WasmRequest::CircuitInfo { circuit_id });
|
||||
}
|
10
src/rust/long_term_stats/wasm_pipe_types/Cargo.toml
Normal file
10
src/rust/long_term_stats/wasm_pipe_types/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "wasm_pipe_types"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
chrono = { version = "0", features = [ "serde" ] }
|
165
src/rust/long_term_stats/wasm_pipe_types/src/lib.rs
Normal file
165
src/rust/long_term_stats/wasm_pipe_types/src/lib.rs
Normal file
@ -0,0 +1,165 @@
|
||||
use std::collections::HashMap;
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum WasmRequest {
|
||||
Auth { token: String },
|
||||
Login { license: String, username: String, password: String },
|
||||
GetNodeStatus,
|
||||
PacketChart { period: String },
|
||||
PacketChartSingle { period: String, node_id: String, node_name: String },
|
||||
ThroughputChart { period: String },
|
||||
ThroughputChartSingle { period: String, node_id: String, node_name: String },
|
||||
ThroughputChartSite { period: String, site_id: String },
|
||||
ThroughputChartCircuit { period: String, circuit_id: String },
|
||||
RttChart { period: String },
|
||||
RttChartSingle { period: String, node_id: String, node_name: String },
|
||||
RttChartSite { period: String, site_id: String },
|
||||
RttChartCircuit { period: String, circuit_id: String },
|
||||
SiteStack { period: String, site_id: String },
|
||||
RootHeat { period: String },
|
||||
SiteHeat { period: String, site_id: String },
|
||||
NodePerfChart { period: String, node_id: String, node_name: String },
|
||||
Tree { parent: String },
|
||||
SiteInfo { site_id: String },
|
||||
SiteParents { site_id: String },
|
||||
Search { term: String },
|
||||
CircuitInfo { circuit_id: String },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum WasmResponse {
|
||||
AuthOk { token: String, name: String, license_key: String },
|
||||
AuthFail,
|
||||
LoginOk { token: String, name: String, license_key: String },
|
||||
LoginFail,
|
||||
NodeStatus { nodes: Vec<Node> },
|
||||
PacketChart { nodes: Vec<PacketHost> },
|
||||
BitsChart { nodes: Vec<ThroughputHost> },
|
||||
RttChart { nodes: Vec<RttHost>, histogram: Vec<u32> },
|
||||
RttChartSite { nodes: Vec<RttHost>, histogram: Vec<u32> },
|
||||
RttChartCircuit { nodes: Vec<RttHost>, histogram: Vec<u32> },
|
||||
SiteStack { nodes: Vec<ThroughputHost> },
|
||||
RootHeat { data: HashMap<String, Vec<(DateTime<FixedOffset>, f64)>>},
|
||||
SiteHeat { data: HashMap<String, Vec<(DateTime<FixedOffset>, f64)>>},
|
||||
NodePerfChart { nodes: Vec<PerfHost> },
|
||||
SiteTree { data: Vec<SiteTree> },
|
||||
SiteInfo { data: SiteTree },
|
||||
SiteParents { data: Vec<(String, String)> },
|
||||
SiteChildren { data: Vec<(String, String, String)> },
|
||||
SearchResult { hits: Vec<SearchResult> },
|
||||
CircuitInfo { data: Vec<CircuitList> },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Node {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub last_seen: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct PacketHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub down: Vec<Packets>,
|
||||
pub up: Vec<Packets>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Packets {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ThroughputHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub down: Vec<Throughput>,
|
||||
pub up: Vec<Throughput>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Throughput {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ThroughputChart {
|
||||
pub msg: String,
|
||||
pub nodes: Vec<ThroughputHost>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Rtt {
|
||||
pub value: f64,
|
||||
pub date: String,
|
||||
pub l: f64,
|
||||
pub u: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct RttHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub rtt: Vec<Rtt>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct PerfHost {
|
||||
pub node_id: String,
|
||||
pub node_name: String,
|
||||
pub stats: Vec<Perf>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Perf {
|
||||
pub date: String,
|
||||
pub cpu: f64,
|
||||
pub cpu_max: f64,
|
||||
pub ram: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SiteTree {
|
||||
pub index: i32,
|
||||
pub site_name: String,
|
||||
pub site_type: String,
|
||||
pub parent: i32,
|
||||
pub max_down: i32,
|
||||
pub max_up: i32,
|
||||
pub current_down: i32,
|
||||
pub current_up: i32,
|
||||
pub current_rtt: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SearchResult {
|
||||
pub name: String,
|
||||
pub url: String,
|
||||
pub score: f64,
|
||||
pub icon: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CircuitList {
|
||||
pub circuit_name: String,
|
||||
pub device_id: String,
|
||||
pub device_name: String,
|
||||
pub parent_node: String,
|
||||
pub mac: String,
|
||||
pub download_min_mbps: i32,
|
||||
pub download_max_mbps: i32,
|
||||
pub upload_min_mbps: i32,
|
||||
pub upload_max_mbps: i32,
|
||||
pub comment: String,
|
||||
pub ip_range: String,
|
||||
pub subnet: i32,
|
||||
}
|
Loading…
Reference in New Issue
Block a user