Skip to content
This repository has been archived by the owner on Aug 1, 2022. It is now read-only.

Commit

Permalink
Add a network diagnostics screen
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Good <alex@memoryandthought.me>
  • Loading branch information
FintanH authored and alexjg committed May 21, 2021
1 parent ea93a31 commit eb30877
Show file tree
Hide file tree
Showing 17 changed files with 505 additions and 13 deletions.
15 changes: 8 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
"radicle-contracts": "github:radicle-dev/radicle-contracts#commit=752cf0767c6ba7428c626abf91ae1874de613f26",
"semver": "^7.3.5",
"stream-browserify": "^3.0.0",
"svelte-json-tree": "^0.1.0",
"svelte-persistent-store": "^0.1.6",
"timeago.js": "^4.0.2",
"twemoji": "13.0.2",
Expand Down
4 changes: 2 additions & 2 deletions proxy/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ warp = { version = "0.3", default-features = false }

[dependencies.radicle-daemon]
git = "https://github.com/radicle-dev/radicle-link.git"
rev = "49562b86e14889bbf8f96d846d46d94bc32468c0"
rev = "f9fa8303cd33096d7818f0dcb0a24d3a9f618fab"

[dependencies.radicle-git-ext]
git = "https://github.com/radicle-dev/radicle-link.git"
rev = "49562b86e14889bbf8f96d846d46d94bc32468c0"
rev = "f9fa8303cd33096d7818f0dcb0a24d3a9f618fab"

[dependencies.radicle-avatar]
git = "https://github.com/radicle-dev/radicle-avatar.git"
Expand Down
51 changes: 51 additions & 0 deletions proxy/api/src/notification.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Machinery to signal significant events to clients.

use radicle_daemon::request::{RequestState, SomeRequest, Status as PeerRequestStatus};
use radicle_git_ext::Oid;
use std::{
collections::HashMap,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
time::SystemTime,
};

use serde::Serialize;
Expand Down Expand Up @@ -63,6 +66,12 @@ pub enum LocalPeer {
/// The new [`PeerStatus`].
new: PeerStatus,
},
WaitingRoomTransition {
event: radicle_daemon::peer::WaitingRoomEvent,
state_before: SerializableWaitingRoomState,
state_after: SerializableWaitingRoomState,
timestamp: u128,
},
}

#[allow(clippy::wildcard_enum_match_arm)]
Expand Down Expand Up @@ -90,6 +99,18 @@ impl MaybeFrom<PeerEvent> for Notification {
PeerEvent::StatusChanged { old, new } => {
Some(Self::LocalPeer(LocalPeer::StatusChanged { old, new }))
},
PeerEvent::WaitingRoomTransition(t) => {
let since_the_epoch = t
.timestamp
.duration_since(std::time::UNIX_EPOCH)
.expect("Time went backwards");
Some(Self::LocalPeer(LocalPeer::WaitingRoomTransition {
event: t.event,
state_before: t.state_before.into(),
state_after: t.state_after.into(),
timestamp: since_the_epoch.as_millis(),
}))
},
_ => None,
}
}
Expand Down Expand Up @@ -129,3 +150,33 @@ impl Subscriptions {
receiver
}
}

#[derive(Clone, Debug, Serialize)]
pub struct SerializableWaitingRoomState(HashMap<String, SerializedRequestState>);

#[derive(Debug, Clone, Serialize)]
pub struct SerializedRequestState {
state: String,
peers: HashMap<PeerId, PeerRequestStatus>,
}

impl From<HashMap<Oid, SomeRequest<SystemTime>>> for SerializableWaitingRoomState {
fn from(raw: HashMap<Oid, SomeRequest<SystemTime>>) -> Self {
let inner: HashMap<String, SerializedRequestState> = raw
.iter()
.map(|(urn, request)| {
(
urn.to_string(),
SerializedRequestState {
state: RequestState::from(request).to_string(),
peers: request
.peers()
.cloned()
.unwrap_or_else(std::collections::HashMap::new),
},
)
})
.collect();
Self(inner)
}
}
2 changes: 2 additions & 0 deletions ui/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import Project from "./Screen/Project.svelte";
import Settings from "./Screen/Settings.svelte";
import UserProfile from "./Screen/UserProfile.svelte";
import NetworkDiagnostics from "./Screen/NetworkDiagnostics.svelte";
const routes = {
"/": Blank,
Expand All @@ -44,6 +45,7 @@
"/user/:urn": UserProfile,
"/user/:urn/*": UserProfile,
"/design-system-guide": DesignSystemGuide,
"/network-diagnostics/*": NetworkDiagnostics,
"*": NotFound,
};
Expand Down
10 changes: 9 additions & 1 deletion ui/DesignSystem/Component/ConnectionStatusIndicator.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import Syncing from "./ConnectionStatusIndicator/Syncing.svelte";
import Offline from "./ConnectionStatusIndicator/Offline.svelte";
const connectedPeerCount = (peers: { [peerId: string]: string[] }) => {
const count = Object.keys(peers).length;
peerCount(count);
};
const peerCount = (count: number) => {
if (count === 1) {
return "1 peer";
Expand All @@ -31,7 +36,10 @@

<div>
{#if $status.type === StatusType.Online}
<Tooltip value={`You’re connected to ${peerCount($status.connected)}`}>
<Tooltip
value={`You’re connected to ${connectedPeerCount(
$status.connectedPeers
)}`}>
<div class="item indicator" data-cy="connection-status-online">
<Icon.Network />
</div>
Expand Down
3 changes: 3 additions & 0 deletions ui/Hotkeys.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
case hotkeys.ShortcutKey.NewProjects:
toggleModal(ModalNewProject);
break;
case hotkeys.ShortcutKey.NetworkDiagnostics:
toggle(path.networkDiagnosticsConnectedPeers());
break;
}
};
</script>
Expand Down
61 changes: 61 additions & 0 deletions ui/Screen/NetworkDiagnostics.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script lang="typescript">
import Router from "svelte-spa-router";
import { status as store } from "ui/src/localPeer";
import * as path from "ui/src/path";
import ActionBar from "ui/DesignSystem/Component/ActionBar.svelte";
import Header from "ui/DesignSystem/Component/Header.svelte";
import HorizontalMenu from "ui/DesignSystem/Component/HorizontalMenu.svelte";
import SidebarLayout from "ui/DesignSystem/Component/SidebarLayout.svelte";
import IconNetwork from "ui/DesignSystem/Primitive/Icon/Network.svelte";
import IconRoad from "ui/DesignSystem/Primitive/Icon/Road.svelte";
import ConnectedPeers from "./NetworkDiagnostics/ConnectedPeers.svelte";
import WaitingRoom from "./NetworkDiagnostics/WaitingRoom.svelte";
const screenRoutes = {
[path.networkDiagnosticsConnectedPeers()]: ConnectedPeers,
[path.networkDiagnosticsWaitingRoom()]: WaitingRoom,
};
const topbarMenuItems = [
{
icon: IconNetwork,
title: "Peers",
href: path.networkDiagnosticsConnectedPeers(),
looseActiveStateMatching: true,
},
{
icon: IconRoad,
title: "Requests",
href: path.networkDiagnosticsWaitingRoom(),
looseActiveStateMatching: true,
},
];
</script>

<style>
.title {
display: flex;
flex-direction: column;
justify-content: center;
}
</style>

<SidebarLayout>
<Header>
<div slot="left" class="title">
<h1>Status: {$store.type}</h1>
</div>
</Header>

<ActionBar>
<div slot="left">
<HorizontalMenu items={topbarMenuItems} />
</div>
</ActionBar>

<Router routes={screenRoutes} />
</SidebarLayout>
47 changes: 47 additions & 0 deletions ui/Screen/NetworkDiagnostics/ConnectedPeers.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script lang="typescript">
import { StatusType, status } from "ui/src/localPeer";
let isOnline = false;
let connectedPeers: { [peerId: string]: string[] } = {};
$: if ($status.type === StatusType.Online) {
isOnline = true;
connectedPeers = $status.connectedPeers;
}
</script>

<style>
table {
table-layout: fixed;
width: 100%;
border-collapse: collapse;
border: 3px solid purple;
}
</style>

{#if isOnline}
<div>
<h2>Connected Peers</h2>
<table>
<thead>
<tr>
<td>Peer</td>
<td>Connections</td>
</tr>
</thead>
<tbody>
{#each Object.keys(connectedPeers).sort() as peerId}
<tr>
<td>{peerId}</td>
<td>
<ul>
{#each connectedPeers[peerId].sort() as address}
<li>{address}</li>
{/each}
</ul>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
43 changes: 43 additions & 0 deletions ui/Screen/NetworkDiagnostics/StateTable.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="typescript">
import type { RoomState } from "ui/src/waitingRoom";
import StyledCopyable from "ui/DesignSystem/Component/StyledCopyable.svelte";
export let state: RoomState;
</script>

<table>
<thead>
<tr>
<td>Urn</td>
<td>State</td>
<td>Peer States</td>
</tr>
</thead>
<tbody>
{#each Object.keys(state).sort() as urn}
<tr>
<td>
<StyledCopyable value={urn} truncate={true} expandable={false} />
</td>
<td>{state[urn].state}</td>
<td>
<table>
<tbody>
{#each Object.keys(state[urn].peers).sort() as peerId}
<tr>
<td>
<StyledCopyable
value={peerId}
truncate={true}
expandable={false} />
</td>
<td>{JSON.stringify(state[urn].peers[peerId])}</td>
</tr>
{/each}
</tbody>
</table>
</td>
</tr>
{/each}
</tbody>
</table>
Loading

0 comments on commit eb30877

Please sign in to comment.