From a77eda6028facbf718e73b23dbf062eadd887f38 Mon Sep 17 00:00:00 2001 From: Stan Bondi Date: Fri, 26 Apr 2024 16:51:42 +0400 Subject: [PATCH] feat(webui): display connections user agent (#1019) Description --- Display user agent in connections pages for VN and indexer Update bindings Fix displayDuration function Motivation and Context --- ![image](https://github.com/tari-project/tari-dan/assets/1057902/5976ee94-fcee-4b80-b3c7-743615c8b9e9) How Has This Been Tested? --- Manually What process can a PR reviewer use to test or verify this change? --- Connections in web uis Breaking Changes --- - [x] None - [ ] Requires data directory to be deleted - [ ] Other - Please specify --- .../tari_indexer/src/json_rpc/handlers.rs | 1 + .../src/routes/VN/Components/Connections.tsx | 30 ++++--------------- .../tari_indexer_web_ui/src/utils/helpers.tsx | 27 +++++++++++++++++ .../src/json_rpc/handlers.rs | 1 + .../src/routes/VN/Components/Connections.tsx | 28 ++++------------- .../src/utils/helpers.tsx | 8 +++-- .../types/tari-indexer-client/Connection.ts | 1 + .../types/validator-node-client/Connection.ts | 1 + clients/tari_indexer_client/src/types.rs | 3 +- clients/validator_node_client/src/types.rs | 3 +- networking/core/src/connection.rs | 6 +++- networking/core/src/worker.rs | 15 ++++++++++ 12 files changed, 71 insertions(+), 53 deletions(-) diff --git a/applications/tari_indexer/src/json_rpc/handlers.rs b/applications/tari_indexer/src/json_rpc/handlers.rs index 9bba2e049..2190368c6 100644 --- a/applications/tari_indexer/src/json_rpc/handlers.rs +++ b/applications/tari_indexer/src/json_rpc/handlers.rs @@ -256,6 +256,7 @@ impl JsonRpcHandlers { }, age: conn.age(), ping_latency: conn.ping_latency, + user_agent: conn.user_agent, }) .collect(); diff --git a/applications/tari_indexer_web_ui/src/routes/VN/Components/Connections.tsx b/applications/tari_indexer_web_ui/src/routes/VN/Components/Connections.tsx index 8d9accc40..0a9afde94 100644 --- a/applications/tari_indexer_web_ui/src/routes/VN/Components/Connections.tsx +++ b/applications/tari_indexer_web_ui/src/routes/VN/Components/Connections.tsx @@ -37,11 +37,8 @@ import { Form } from "react-router-dom"; import Fade from "@mui/material/Fade"; import CopyToClipboard from "../../../Components/CopyToClipboard"; import type { Connection } from "@tariproject/typescript-bindings/tari-indexer-client"; +import { displayDuration } from "../../../utils/helpers"; -interface Duration { - secs: number; - nanos: number; -} const useInterval = (fn: () => Promise, ms: number) => { const timeout = useRef(); @@ -132,16 +129,17 @@ function Connections() { - Peer id + Peer ID Address Age Direction Latency + User Agent {connections && - connections.map(({ connection_id, address, age, direction, peer_id, ping_latency }) => ( + connections.map(({ connection_id, address, age, direction, peer_id, ping_latency, user_agent }) => ( {peer_id ? shortenString(peer_id) : "--"} @@ -151,6 +149,7 @@ function Connections() { {displayDuration(age)} {direction} {ping_latency ? displayDuration(ping_latency) : "--"} + {user_agent ? user_agent.replace(/^\/tari\//, "") : "--"} ))} @@ -159,23 +158,4 @@ function Connections() { ); } -function displayDuration(duration: Duration) { - if (duration.secs === 0) { - if (duration.nanos > 1000000) { - return `${(duration.nanos / 1000000).toFixed(2)}ms`; - } - if (duration.nanos > 1000) { - return `${(duration.nanos / 1000).toFixed(2)}µs`; - } - return `${duration.nanos / 1000}ns`; - } - if (duration.secs > 60 * 60) { - return `${(duration.secs / 60 / 60).toFixed(0)}h${(duration.secs / 60).toFixed(0)}m`; - } - if (duration.secs > 60) { - return `${(duration.secs / 60).toFixed(0)}m${(duration.secs % 60).toFixed(0)}s`; - } - return `${duration.secs}.${(duration.nanos / 1000000).toFixed(0)}s`; -} - export default Connections; diff --git a/applications/tari_indexer_web_ui/src/utils/helpers.tsx b/applications/tari_indexer_web_ui/src/utils/helpers.tsx index 96a0a9ecb..483cbbed4 100644 --- a/applications/tari_indexer_web_ui/src/utils/helpers.tsx +++ b/applications/tari_indexer_web_ui/src/utils/helpers.tsx @@ -58,4 +58,31 @@ const renderJson = (json: any) => { } }; +export interface Duration { + secs: number; + nanos: number; +} + +export function displayDuration(duration: Duration) { + if (duration.secs === 0) { + if (duration.nanos > 1000000) { + return `${(duration.nanos / 1000000).toFixed(2)}ms`; + } + if (duration.nanos > 1000) { + return `${(duration.nanos / 1000).toFixed(2)}µs`; + } + return `${duration.nanos}ns`; + } + if (duration.secs >= 60 * 60) { + const minutes_secs = duration.secs - Math.floor(duration.secs / 60 / 60) * 60 * 60; + return `${(duration.secs / 60 / 60).toFixed(0)}h${Math.floor(minutes_secs / 60)}m`; + } + if (duration.secs >= 60) { + const secs = duration.secs - Math.floor(duration.secs / 60) * 60; + return `${(duration.secs / 60).toFixed(0)}m${secs.toFixed(0)}s`; + } + return `${duration.secs}s`; +} + + export { renderJson }; diff --git a/applications/tari_validator_node/src/json_rpc/handlers.rs b/applications/tari_validator_node/src/json_rpc/handlers.rs index 1bf6230e3..1ce31c3e8 100644 --- a/applications/tari_validator_node/src/json_rpc/handlers.rs +++ b/applications/tari_validator_node/src/json_rpc/handlers.rs @@ -528,6 +528,7 @@ impl JsonRpcHandlers { }, age: conn.age(), ping_latency: conn.ping_latency, + user_agent: conn.user_agent, }) .collect(); diff --git a/applications/tari_validator_node_web_ui/src/routes/VN/Components/Connections.tsx b/applications/tari_validator_node_web_ui/src/routes/VN/Components/Connections.tsx index 4feeddc95..df7ad668b 100644 --- a/applications/tari_validator_node_web_ui/src/routes/VN/Components/Connections.tsx +++ b/applications/tari_validator_node_web_ui/src/routes/VN/Components/Connections.tsx @@ -37,6 +37,7 @@ import { Form } from "react-router-dom"; import Fade from "@mui/material/Fade"; import CopyToClipboard from "../../../Components/CopyToClipboard"; import type { Connection } from "@tariproject/typescript-bindings/validator-node-client"; +import { displayDuration } from "../../../utils/helpers"; const useInterval = (fn: () => Promise, ms: number) => { const timeout = useRef(); @@ -128,18 +129,19 @@ function Connections() {
- Peer id + Peer ID Address Age Direction Latency + User Agent {connections && - connections.map(({ connection_id, address, age, direction, peer_id, ping_latency }) => ( + connections.map(({ connection_id, address, age, direction, peer_id, ping_latency, user_agent }) => ( - + {peer_id ? shortenString(peer_id) : "--"} @@ -147,6 +149,7 @@ function Connections() { {displayDuration(age)} {direction} {ping_latency ? displayDuration(ping_latency) : "--"} + {user_agent ? user_agent.replace(/^\/tari\//, "") : "--"} ))} @@ -156,23 +159,4 @@ function Connections() { ); } -function displayDuration(duration: { secs: number; nanos: number }) { - if (duration.secs === 0) { - if (duration.nanos > 1000000) { - return `${(duration.nanos / 1000000).toFixed(2)}ms`; - } - if (duration.nanos > 1000) { - return `${(duration.nanos / 1000).toFixed(2)}µs`; - } - return `${duration.nanos / 1000}ns`; - } - if (duration.secs > 60 * 60) { - return `${(duration.secs / 60 / 60).toFixed(0)}h${(duration.secs / 60).toFixed(0)}m`; - } - if (duration.secs > 60) { - return `${(duration.secs / 60).toFixed(0)}m${(duration.secs % 60).toFixed(0)}s`; - } - return `${duration.secs}.${(duration.nanos / 1000000).toFixed(0)}s`; -} - export default Connections; diff --git a/applications/tari_validator_node_web_ui/src/utils/helpers.tsx b/applications/tari_validator_node_web_ui/src/utils/helpers.tsx index 03ca2cdf4..da81c4d0b 100644 --- a/applications/tari_validator_node_web_ui/src/utils/helpers.tsx +++ b/applications/tari_validator_node_web_ui/src/utils/helpers.tsx @@ -121,10 +121,12 @@ export function displayDuration(duration: Duration) { return `${duration.nanos}ns`; } if (duration.secs >= 60 * 60) { - return `${(duration.secs / 60 / 60).toFixed(0)}h${(duration.secs / 60).toFixed(0)}m`; + const minutes_secs = duration.secs - Math.floor(duration.secs / 60 / 60) * 60 * 60; + return `${(duration.secs / 60 / 60).toFixed(0)}h${Math.floor(minutes_secs / 60)}m`; } if (duration.secs >= 60) { - return `${(duration.secs / 60).toFixed(0)}m${(duration.secs % 60).toFixed(0)}s`; + const secs = duration.secs - Math.floor(duration.secs / 60) * 60; + return `${(duration.secs / 60).toFixed(0)}m${secs.toFixed(0)}s`; } - return `${duration.secs}.${(duration.nanos / 1000000).toFixed(0).padStart(3, "0").replace(/0+$/, "")}s`; + return `${duration.secs}s`; } diff --git a/bindings/src/types/tari-indexer-client/Connection.ts b/bindings/src/types/tari-indexer-client/Connection.ts index e45fd8801..a51952229 100644 --- a/bindings/src/types/tari-indexer-client/Connection.ts +++ b/bindings/src/types/tari-indexer-client/Connection.ts @@ -8,4 +8,5 @@ export interface Connection { direction: ConnectionDirection; age: { secs: number; nanos: number }; ping_latency: { secs: number; nanos: number } | null; + user_agent: string | null; } diff --git a/bindings/src/types/validator-node-client/Connection.ts b/bindings/src/types/validator-node-client/Connection.ts index e45fd8801..a51952229 100644 --- a/bindings/src/types/validator-node-client/Connection.ts +++ b/bindings/src/types/validator-node-client/Connection.ts @@ -8,4 +8,5 @@ export interface Connection { direction: ConnectionDirection; age: { secs: number; nanos: number }; ping_latency: { secs: number; nanos: number } | null; + user_agent: string | null; } diff --git a/clients/tari_indexer_client/src/types.rs b/clients/tari_indexer_client/src/types.rs index 60f79080d..5e89520cc 100644 --- a/clients/tari_indexer_client/src/types.rs +++ b/clients/tari_indexer_client/src/types.rs @@ -1,7 +1,7 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use std::time::Duration; +use std::{sync::Arc, time::Duration}; use multiaddr::Multiaddr; use serde::{Deserialize, Serialize}; @@ -438,6 +438,7 @@ pub struct Connection { pub age: Duration, #[cfg_attr(feature = "ts", ts(type = "{secs: number, nanos: number} | null"))] pub ping_latency: Option, + pub user_agent: Option>, } #[derive(Serialize, Debug)] diff --git a/clients/validator_node_client/src/types.rs b/clients/validator_node_client/src/types.rs index ff2a404c3..4ea069b80 100644 --- a/clients/validator_node_client/src/types.rs +++ b/clients/validator_node_client/src/types.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{ops::RangeInclusive, time::Duration}; +use std::{ops::RangeInclusive, sync::Arc, time::Duration}; use multiaddr::Multiaddr; use serde::{Deserialize, Serialize}; @@ -731,6 +731,7 @@ pub struct Connection { pub age: Duration, #[cfg_attr(feature = "ts", ts(type = "{secs: number, nanos: number} | null"))] pub ping_latency: Option, + pub user_agent: Option>, } #[derive(Serialize, Debug)] diff --git a/networking/core/src/connection.rs b/networking/core/src/connection.rs index 6c038ed07..611f671a6 100644 --- a/networking/core/src/connection.rs +++ b/networking/core/src/connection.rs @@ -1,7 +1,10 @@ // Copyright 2023 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use std::time::{Duration, Instant}; +use std::{ + sync::Arc, + time::{Duration, Instant}, +}; use libp2p::{core::ConnectedPoint, swarm::ConnectionId, PeerId}; @@ -15,6 +18,7 @@ pub struct Connection { pub num_concurrent_dial_errors: usize, pub established_in: Duration, pub ping_latency: Option, + pub user_agent: Option>, } impl Connection { diff --git a/networking/core/src/worker.rs b/networking/core/src/worker.rs index 5b8ec6b0e..b73226230 100644 --- a/networking/core/src/worker.rs +++ b/networking/core/src/worker.rs @@ -4,6 +4,7 @@ use std::{ collections::{hash_map::Entry, HashMap}, hash::Hash, + sync::Arc, time::{Duration, Instant}, }; @@ -764,6 +765,7 @@ where num_concurrent_dial_errors, established_in, ping_latency: None, + user_agent: None, }); let Some(waiters) = self.pending_dial_requests.remove(&peer_id) else { @@ -793,6 +795,8 @@ where return Ok(()); } + self.update_connected_peers(&peer_id, &info); + let is_relay = info.protocols.iter().any(|p| *p == relay::HOP_PROTOCOL_NAME); let is_connected_through_relay = self @@ -840,6 +844,17 @@ where Ok(()) } + fn update_connected_peers(&mut self, peer_id: &PeerId, info: &identify::Info) { + let Some(conns_mut) = self.active_connections.get_mut(peer_id) else { + return; + }; + + let user_agent = Arc::new(info.agent_version.clone()); + for conn_mut in conns_mut { + conn_mut.user_agent = Some(user_agent.clone()); + } + } + /// Establishes a relay circuit for the given peer if the it is the selected relay peer. Returns true if the circuit /// was established from this call. fn establish_relay_circuit_on_connect(&mut self, peer_id: &PeerId) -> bool {