From 70c6dbbbe6a80222b9e69f2dfae2fcd8f02783f8 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 06:52:03 +0000 Subject: [PATCH 1/9] update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0d70b50..ea87e6a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,9 +17,9 @@ RUN npm update --legacy-peer-deps RUN npm run build --release FROM alpine:3.18 -MAINTAINER Jens Thiel +LABEL maintainer="zn-luo" WORKDIR /opt/nats -VOLUME /data +#VOLUME /data RUN apk update && apk upgrade && \ apk add --no-cache libgcc libssl1.1 libcrypto1.1 ca-certificates sqlite-libs && \ update-ca-certificates && \ From f0f48cbce02516839d81a1d6a5a6f1d38b4606e7 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 06:54:26 +0000 Subject: [PATCH 2/9] udpate server_name to Option --- src/datatypes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datatypes.rs b/src/datatypes.rs index 5cdffbe..59d9899 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -97,7 +97,7 @@ pub struct Publication { #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ServerVarz { pub server_id: String, - pub server_name: String, + pub server_name: Option, pub version: String, pub proto: i32, pub go: String, From 9a3218d9a3d0df7a0ba31aa410081a7d41945009 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 06:56:21 +0000 Subject: [PATCH 3/9] udpate tls_timeout from i64 to f64 --- src/datatypes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/datatypes.rs b/src/datatypes.rs index 59d9899..f97e5fa 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -125,7 +125,7 @@ pub struct ServerVarz { pub websocket: Option, #[serde(default)] pub jetstream: Option, - pub tls_timeout: i64, + pub tls_timeout: f64, pub write_deadline: i64, pub start: String, pub now: String, @@ -163,7 +163,7 @@ pub struct ClusterInfo { #[serde(default)] pub auth_timeout: Option, #[serde(default)] - pub tls_timeout: Option, + pub tls_timeout: Option, #[serde(default)] pub tls_required: Option, #[serde(default)] @@ -178,7 +178,7 @@ pub struct ClusterInfo { pub struct MqttConfig { pub host: String, pub port: u16, - pub tls_timeout: i64, + pub tls_timeout: f64, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] From 65482cbb47e97bf14f68bedcbddccf659e0e8138 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 06:57:33 +0000 Subject: [PATCH 4/9] update gomaxprocs to Option --- src/datatypes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datatypes.rs b/src/datatypes.rs index f97e5fa..1c8237b 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -132,7 +132,7 @@ pub struct ServerVarz { pub uptime: String, pub mem: i64, pub cores: i32, - pub gomaxprocs: i32, + pub gomaxprocs: Option, pub cpu: f64, pub connections: i64, pub total_connections: i64, From 6565dea89db832445e8456669013f0ff8a5f0f8c Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 07:01:34 +0000 Subject: [PATCH 5/9] update leafnodes to Option --- src/datatypes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datatypes.rs b/src/datatypes.rs index 1c8237b..fa37e2b 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -138,7 +138,7 @@ pub struct ServerVarz { pub total_connections: i64, pub routes: i64, pub remotes: i64, - pub leafnodes: i64, + pub leafnodes: Option, pub in_msgs: i64, pub out_msgs: i64, pub in_bytes: i64, From ef3264b2ccac8217b30d6561364e362abaf81dc7 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 07:03:31 +0000 Subject: [PATCH 6/9] udpate slow_consumer_stats to Option --- src/datatypes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datatypes.rs b/src/datatypes.rs index fa37e2b..cab7105 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -149,7 +149,7 @@ pub struct ServerVarz { pub config_load_time: String, #[serde(default)] pub system_account: Option, - pub slow_consumer_stats: SlowConsumerStats, + pub slow_consumer_stats: Option, #[serde(default)] pub git_commit: Option, } From 6e0508ea0d06c82d4edc80a349813c4af112a12f Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 09:03:24 +0000 Subject: [PATCH 7/9] udpate port --- Dockerfile | 2 +- src/main.rs | 4 ++-- web/src/App.vue | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index ea87e6a..0070ccd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,5 +28,5 @@ RUN apk update && apk upgrade && \ COPY --from=backend-builder /usr/src/NATS-WebUI/target/release/nats-webui /opt/nats/nats-webui COPY --from=frontend-builder /usr/src/NATS-WebUI/web/dist/ /opt/nats/web/dist USER 1000:1000 -EXPOSE 80 +EXPOSE 8600 ENTRYPOINT ["/opt/nats/nats-webui"] diff --git a/src/main.rs b/src/main.rs index 48f58a6..b199859 100755 --- a/src/main.rs +++ b/src/main.rs @@ -206,8 +206,8 @@ async fn main() -> rusqlite::Result<()> { .or(client_subscribe_route) .with(warp::log("web")); - debug!("Starting server on 0.0.0.0:80"); - warp::serve(route).run(([0, 0, 0, 0], 80)).await; + debug!("Starting server on 0.0.0.0:8600"); + warp::serve(route).run(([0, 0, 0, 0], 8600)).await; Ok(()) } diff --git a/web/src/App.vue b/web/src/App.vue index 998004d..df1e3e1 100755 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -41,7 +41,7 @@ - sphqxe, thielj github.com/thielj/NATS-WebUI + sphqxe, thielj github.com/zn-luo/NATS-WebUI From 7bd8cf2a5a72d806ab0ed223538b8cbf7e369d8f Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 27 Mar 2025 09:31:10 +0000 Subject: [PATCH 8/9] update web/src/App.vue --- web/src/App.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/App.vue b/web/src/App.vue index df1e3e1..be48403 100755 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -41,7 +41,7 @@ - sphqxe, thielj github.com/zn-luo/NATS-WebUI + sphqxe, thielj, zn-luo github.com/zn-luo/NATS-WebUI From 0fa3417af25de8762f8131526b2829fdc7e01b0e Mon Sep 17 00:00:00 2001 From: Pratik G Date: Sat, 29 Mar 2025 15:40:40 +0530 Subject: [PATCH 9/9] fix for host (not the actual error). --- README.md | 182 ++++++++++------ src/datatypes.rs | 541 +++++++++++++++++++++++------------------------ 2 files changed, 391 insertions(+), 332 deletions(-) diff --git a/README.md b/README.md index 980fb57..dc7baf4 100755 --- a/README.md +++ b/README.md @@ -1,59 +1,123 @@ -This fork fixes some issues with the original release and produces a smallish alpine-based image. -To persist the settings, mount a volume to /data. For example: - -``` -mkdir ./nats-webui && chown 1000:1000 -docker run --rm -p 8080:80 -v "${PWD}/nats-webui:/data" ghcr.io/thielj/nats-webui:latest -``` - -Original README follows... - ---- - -

- NATS WebUI Logo -

- -NATS-WebUI -========== -NATS-WebUI is a web app for monitoring messages on [NATS](https://nats.io/) publications as well as [NATS Server](https://nats.io/) diagnostics. This project was built to explore building web-backends in Rust and uses the following stack: - -- HTTP Server and WebSockets in Rust via [Warp Web Framework](https://github.com/seanmonstar/warp) -- SQLite DB via [rusqlite](https://github.com/jgallagher/rusqlite) -- VueJS -- HTTP Requests via [reqwest](https://github.com/seanmonstar/reqwest) -- [Rants](https://github.com/davidMcneil/rants) Async NATS client - -## Screenshots -![Screenshot 4](/screenshots/screenshot4.png) ![Screenshot 3](/screenshots/screenshot3.png) - -## Installation -```docker run -d -p 80:80 sphqxe/nats-webui:latest``` - -## Usage -- Add a server by entering its hostname, port, and monitoring port. The monitoring endpoint is called server-side, so the NATS server host must be resolvable and reachable from the server hosting the WebUI. -- In order to subscribe and receive messages from publications, the subjects must be added to the subject hierarchy on the server dashboard. The hierarchy is represented as a subject tree where each node in the tree contains a single subject token. The editor takes input as a tab-spaced tree. For example, to represent the following subjects: - ```` - time.us - time.us.east - time.us.east.atlanta - time.eu.east - time.eu.warsaw - ```` - Input the subject tree as such: - ```` - time - us - east - atlanta - eu - east - warsaw - ```` -- Create a client to monitor publications. Once the subjects have been entered as previously stated, they should show up on the right side of the client screen. Select the subjects to subscribe to and click the "link" icon to start receiving messages. - -## License -MIT - -## Authors -Theodore Lee (@sphqxe) +# NATS WebUI + +A web interface for monitoring and interacting with NATS messaging system. + +## Setup Guide (Windows) + +### Prerequisites +- Docker installed +- Git repository cloned + +### Step 1: Run NATS Server +```powershell +docker run --name nats-server -p 4222:4222 -p 8222:8222 nats:latest +``` + +### Step 2: Build NATS WebUI Docker Image +```powershell +docker build -t nats-webui:latest . +``` + +### Step 3: Create Data Directory +```powershell +mkdir nats-webui +``` + +### Step 4: Run NATS WebUI Container +```powershell +docker run --rm -p 8080:8600 -v "${PWD}/nats-webui:/data" nats-webui +``` + +The WebUI will now be accessible at http://localhost:8080 + +## Connection Tips + +To get the Docker container IP address (useful for connecting to NATS server): +```powershell +docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq) +``` + +For monitoring NATS connections: +```powershell +Invoke-RestMethod -Uri "http://localhost:8222/connz?json=true" | ConvertTo-Json +``` + +## Troubleshooting + +### Missing Host Field Error + +When encountering: +``` +Failed to fetch varz: reqwest::Error { kind: Decode, source: Error("missing field `host`") } +``` + +The issue was resolved by updating the `ServerVarz` struct in `datatypes.rs` to properly match the actual JSON structure returned by the NATS server monitoring endpoint. + +Check varz +```powershell +Invoke-RestMethod -Uri "http://localhost:8222/varz?json=true" | ConvertTo-Json +``` + +### Note About WebUI Clients + +WebUI client connections may not appear in standard `connz` monitoring endpoints, which is expected behavior (not sure what is the fix). + +## Publishing Test Messages + +To publish messages to subjects that WebUI clients are subscribed to: +``` +nats pub [subject] [message] +``` + + +# Original README follows... + +--- + +

+ NATS WebUI Logo +

+ +NATS-WebUI +========== +NATS-WebUI is a web app for monitoring messages on [NATS](https://nats.io/) publications as well as [NATS Server](https://nats.io/) diagnostics. This project was built to explore building web-backends in Rust and uses the following stack: + +- HTTP Server and WebSockets in Rust via [Warp Web Framework](https://github.com/seanmonstar/warp) +- SQLite DB via [rusqlite](https://github.com/jgallagher/rusqlite) +- VueJS +- HTTP Requests via [reqwest](https://github.com/seanmonstar/reqwest) +- [Rants](https://github.com/davidMcneil/rants) Async NATS client + +## Screenshots +![Screenshot 4](/screenshots/screenshot4.png) ![Screenshot 3](/screenshots/screenshot3.png) + +## Installation +```docker run -d -p 80:80 sphqxe/nats-webui:latest``` + +## Usage +- Add a server by entering its hostname, port, and monitoring port. The monitoring endpoint is called server-side, so the NATS server host must be resolvable and reachable from the server hosting the WebUI. +- In order to subscribe and receive messages from publications, the subjects must be added to the subject hierarchy on the server dashboard. The hierarchy is represented as a subject tree where each node in the tree contains a single subject token. The editor takes input as a tab-spaced tree. For example, to represent the following subjects: + ```` + time.us + time.us.east + time.us.east.atlanta + time.eu.east + time.eu.warsaw + ```` + Input the subject tree as such: + ```` + time + us + east + atlanta + eu + east + warsaw + ```` +- Create a client to monitor publications. Once the subjects have been entered as previously stated, they should show up on the right side of the client screen. Select the subjects to subscribe to and click the "link" icon to start receiving messages. + +## License +MIT + +## Authors +Theodore Lee (@sphqxe) diff --git a/src/datatypes.rs b/src/datatypes.rs index cab7105..c4921ab 100644 --- a/src/datatypes.rs +++ b/src/datatypes.rs @@ -1,273 +1,268 @@ -use log::{debug, error}; -use reqwest; -use serde::{Deserialize, Serialize}; - -#[derive(Default, Clone, Serialize, Deserialize, Debug)] -pub struct App { - pub servers: Vec, - pub clients: Vec, -} - -impl App { - pub fn set_servers(&mut self, servers: Vec) { - self.servers = servers; - } - - pub fn set_clients(&mut self, clients: Vec) { - self.clients = clients; - } -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct NatsServer { - pub id: Option, - pub name: String, - pub host: String, - pub port: u16, - pub monitoring_port: u16, - pub token: Option, - pub varz: Option, - pub subjects: Vec, - pub publications: Vec, -} - -impl NatsServer { - pub async fn get_varz( - id: i64, - host: String, - port: u16, - client: &reqwest::Client, - ) -> Result { - let response = client - .get(&format!("http://{}:{}/varz", host, port)) - .send() - .await?; - - response.error_for_status_ref()?; - - let json_text = response.text().await?; - debug!("Raw VARZ JSON: {}", json_text); - - let varz: ServerVarz = serde_json::from_str(&json_text).map_err(|e| { - error!("Failed to parse VARZ JSON: {:?}", e); - VarzError::from(e) - })?; - - Ok(VarzBroadcastMessage { - server_id: id, - varz, - }) - } -} - -#[derive(Debug, Clone, Serialize)] -pub struct VarzBroadcastMessage { - pub server_id: i64, - varz: ServerVarz, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] -pub struct SubjectTreeNode { - id: String, - subject_str: String, - subjects: Vec, - selected: bool, -} - -impl SubjectTreeNode { - pub fn flatten(&self) -> Vec { - let mut result = vec![self.subject_str.clone()]; - for child in &self.subjects { - result.extend(child.flatten()); - } - result - } - - pub fn get_subscriptions(&self) -> Vec { - self.flatten() - } -} - -#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct Publication { - subject: String, - message: String, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct ServerVarz { - pub server_id: String, - pub server_name: Option, - pub version: String, - pub proto: i32, - pub go: String, - pub host: String, - pub port: u16, - pub max_connections: i64, - pub ping_interval: i64, - pub ping_max: i64, - pub http_host: String, - pub http_port: u16, - pub https_port: u16, - pub auth_timeout: i64, - pub max_control_line: i64, - pub max_payload: i64, - pub max_pending: i64, - #[serde(default)] - pub cluster: Option, - #[serde(default)] - pub gateway: Option, - #[serde(default)] - pub leaf: Option, - #[serde(default)] - pub mqtt: Option, - #[serde(default)] - pub websocket: Option, - #[serde(default)] - pub jetstream: Option, - pub tls_timeout: f64, - pub write_deadline: i64, - pub start: String, - pub now: String, - pub uptime: String, - pub mem: i64, - pub cores: i32, - pub gomaxprocs: Option, - pub cpu: f64, - pub connections: i64, - pub total_connections: i64, - pub routes: i64, - pub remotes: i64, - pub leafnodes: Option, - pub in_msgs: i64, - pub out_msgs: i64, - pub in_bytes: i64, - pub out_bytes: i64, - pub slow_consumers: i64, - pub subscriptions: i64, - pub http_req_stats: HttpReqStats, - pub config_load_time: String, - #[serde(default)] - pub system_account: Option, - pub slow_consumer_stats: Option, - #[serde(default)] - pub git_commit: Option, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct ClusterInfo { - #[serde(default)] - pub addr: Option, - #[serde(default)] - pub cluster_port: Option, - #[serde(default)] - pub auth_timeout: Option, - #[serde(default)] - pub tls_timeout: Option, - #[serde(default)] - pub tls_required: Option, - #[serde(default)] - pub tls_verify: Option, - #[serde(default)] - pub name: Option, - #[serde(default)] - pub urls: Option>, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct MqttConfig { - pub host: String, - pub port: u16, - pub tls_timeout: f64, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct JetstreamConfig { - pub config: JetstreamServerConfig, - pub stats: JetstreamStats, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct JetstreamServerConfig { - pub max_memory: i64, - pub max_storage: i64, - pub store_dir: String, - pub sync_interval: i64, - pub compress_ok: bool, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct JetstreamStats { - pub memory: i64, - pub storage: i64, - pub reserved_memory: i64, - pub reserved_storage: i64, - pub accounts: i64, - pub ha_assets: i64, - pub api: JetstreamApiStats, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct JetstreamApiStats { - pub total: i64, - pub errors: i64, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct HttpReqStats { - #[serde(rename = "/varz")] - pub varz: i64, -} - -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] -pub struct SlowConsumerStats { - pub clients: i64, - pub routes: i64, - pub gateways: i64, - pub leafs: i64, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct NatsClient { - pub id: Option, - pub name: String, - pub server_id: i64, - pub subjects: Vec, - pub info: bool, - pub ping: bool, - pub pong: bool, - pub ok: bool, - pub err: bool, - pub publ: bool, - pub sub: bool, - pub unsub: bool, - pub connect: bool, - pub msg: bool, -} - -impl NatsClient { - pub fn get_subscriptions(&self) -> Vec { - self.subjects - .iter() - .flat_map(|s| s.get_subscriptions()) - .collect() - } -} - -#[derive(Debug)] -pub enum VarzError { - RequestError(reqwest::Error), - JsonError(serde_json::Error), -} - -impl From for VarzError { - fn from(err: reqwest::Error) -> Self { - VarzError::RequestError(err) - } -} - -impl From for VarzError { - fn from(err: serde_json::Error) -> Self { - VarzError::JsonError(err) - } -} +use log::{debug, error}; +use reqwest; +use serde::{Deserialize, Serialize}; + +#[derive(Default, Clone, Serialize, Deserialize, Debug)] +pub struct App { + pub servers: Vec, + pub clients: Vec, +} + +impl App { + pub fn set_servers(&mut self, servers: Vec) { + self.servers = servers; + } + + pub fn set_clients(&mut self, clients: Vec) { + self.clients = clients; + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct NatsServer { + pub id: Option, + pub name: String, + pub host: String, + pub port: u16, + pub monitoring_port: u16, + pub token: Option, + pub varz: Option, + pub subjects: Vec, + pub publications: Vec, +} + +impl NatsServer { + pub async fn get_varz( + id: i64, + host: String, + port: u16, + client: &reqwest::Client, + ) -> Result { + let response = client + .get(&format!("http://{}:{}/varz", host, port)) + .send() + .await?; + + let varz: ServerVarz = serde_json::from_str(&response.text().await?) + .map_err(|e| VarzError::JsonError(e))?; + + Ok(VarzBroadcastMessage { + server_id: id, + varz, + }) + } +} + +#[derive(Debug, Clone, Serialize)] +pub struct VarzBroadcastMessage { + pub server_id: i64, + varz: ServerVarz, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +pub struct SubjectTreeNode { + id: String, + subject_str: String, + subjects: Vec, + selected: bool, +} + +impl SubjectTreeNode { + pub fn flatten(&self) -> Vec { + let mut result = vec![self.subject_str.clone()]; + for child in &self.subjects { + result.extend(child.flatten()); + } + result + } + + pub fn get_subscriptions(&self) -> Vec { + self.flatten() + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct Publication { + subject: String, + message: String, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct ServerVarz { + pub server_id: String, + pub server_name: String, + pub version: String, + pub proto: i32, + pub go: String, + pub host: String, + pub port: u16, + pub max_connections: i64, + pub ping_interval: i64, + pub ping_max: i64, + pub http_host: String, + pub http_port: u16, + pub http_base_path: String, + pub https_port: u16, + pub auth_timeout: i64, + pub max_control_line: i64, + pub max_payload: i64, + pub max_pending: i64, + #[serde(default)] + pub cluster: Option, + // #[serde(default)] + // pub gateway: Option, + // #[serde(default)] + // pub leaf: Option, + // #[serde(default)] + // pub mqtt: Option, + // #[serde(default)] + // pub websocket: Option, + // #[serde(default)] + // pub jetstream: Option, + pub tls_timeout: f64, + pub write_deadline: i64, + pub start: String, + pub now: String, + pub uptime: String, + pub mem: i64, + pub cores: i32, + pub gomaxprocs: Option, + pub cpu: f64, + pub connections: i64, + pub total_connections: i64, + pub routes: i64, + pub remotes: i64, + pub leafnodes: Option, + pub in_msgs: i64, + pub out_msgs: i64, + pub in_bytes: i64, + pub out_bytes: i64, + pub slow_consumers: i64, + pub subscriptions: i64, + pub http_req_stats: HttpReqStats, + pub config_load_time: String, + pub config_digest: String, + #[serde(default)] + pub system_account: Option, + pub slow_consumer_stats: Option, + #[serde(default)] + pub git_commit: Option, +} + +#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct ClusterInfo { + #[serde(default)] + pub addr: Option, + #[serde(default)] + pub cluster_port: Option, + #[serde(default)] + pub auth_timeout: Option, + #[serde(default)] + pub tls_timeout: Option, + #[serde(default)] + pub tls_required: Option, + #[serde(default)] + pub tls_verify: Option, + #[serde(default)] + pub name: Option, + #[serde(default)] + pub urls: Option>, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct MqttConfig { + pub host: String, + pub port: u16, + pub tls_timeout: f64, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct JetstreamConfig { + pub config: JetstreamServerConfig, + pub stats: JetstreamStats, +} + +#[derive(Default,Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct JetstreamServerConfig { + pub max_memory: i64, + pub max_storage: i64, + pub store_dir: String, + pub sync_interval: i64, + pub compress_ok: bool, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct JetstreamStats { + pub memory: i64, + pub storage: i64, + pub reserved_memory: i64, + pub reserved_storage: i64, + pub accounts: i64, + pub ha_assets: i64, + pub api: JetstreamApiStats, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct JetstreamApiStats { + pub total: i64, + pub errors: i64, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct HttpReqStats { + #[serde(rename = "/varz")] + pub varz: i64, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct SlowConsumerStats { + pub clients: i64, + pub routes: i64, + pub gateways: i64, + pub leafs: i64, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct NatsClient { + pub id: Option, + pub name: String, + pub server_id: i64, + pub subjects: Vec, + pub info: bool, + pub ping: bool, + pub pong: bool, + pub ok: bool, + pub err: bool, + pub publ: bool, + pub sub: bool, + pub unsub: bool, + pub connect: bool, + pub msg: bool, +} + +impl NatsClient { + pub fn get_subscriptions(&self) -> Vec { + self.subjects + .iter() + .flat_map(|s| s.get_subscriptions()) + .collect() + } +} + +#[derive(Debug)] +pub enum VarzError { + RequestError(reqwest::Error), + JsonError(serde_json::Error), +} + +impl From for VarzError { + fn from(err: reqwest::Error) -> Self { + VarzError::RequestError(err) + } +} + +impl From for VarzError { + fn from(err: serde_json::Error) -> Self { + VarzError::JsonError(err) + } +}