mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2024-12-22 11:39:25 +00:00
Better network charts
This commit is contained in:
parent
388021b25b
commit
80e0a5091b
6 changed files with 103 additions and 60 deletions
|
@ -400,6 +400,14 @@ export class DaemonService {
|
|||
|
||||
console.log("Starting daemon");
|
||||
|
||||
if (!this.restarting && !this.enablingSync) {
|
||||
window.electronAPI.showNotification({
|
||||
title: 'Daemon starting',
|
||||
body: 'Monero daemon is starting',
|
||||
closeButtonText: 'Dismiss'
|
||||
});
|
||||
}
|
||||
|
||||
this.settings = customSettings ? customSettings : await this.getSettings();
|
||||
|
||||
if (!this.settings.noSync && !this.settings.syncOnWifi && await this.isWifiConnected()) {
|
||||
|
|
|
@ -47,7 +47,23 @@ export abstract class BasePageComponent implements AfterContentInit, OnDestroy {
|
|||
this.setTableInitialized(id, $table);
|
||||
}
|
||||
|
||||
protected loadTable(id: string, rows: any[]): void {
|
||||
protected setTableLoading(id: string, loading: boolean = true): void {
|
||||
if (!this.isTableInitialized(id)) {
|
||||
this.initTable(id, loading);
|
||||
return;
|
||||
}
|
||||
|
||||
const $table = this.initializedTables[id];
|
||||
|
||||
if (!$table) {
|
||||
console.warn(`Could not set table loading to ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
$table.bootstrapTable('showLoading');
|
||||
}
|
||||
|
||||
protected loadTable(id: string, rows: any[], loading: boolean = false): void {
|
||||
if (!this.isTableInitialized(id)) {
|
||||
this.initTable(id);
|
||||
}
|
||||
|
@ -60,10 +76,11 @@ export abstract class BasePageComponent implements AfterContentInit, OnDestroy {
|
|||
const $table = this.initializedTables[id] as JQuery<HTMLElement>;
|
||||
|
||||
$table.bootstrapTable('load', rows);
|
||||
$table.bootstrapTable('hideLoading');
|
||||
if (loading) $table.bootstrapTable('showLoading');
|
||||
else $table.bootstrapTable('hideLoading');
|
||||
}
|
||||
|
||||
private destroyTable(id: string): void {
|
||||
protected destroyTable(id: string): void {
|
||||
const $table = this.initializedTables[id];
|
||||
|
||||
if (!$table) {
|
||||
|
@ -76,7 +93,7 @@ export abstract class BasePageComponent implements AfterContentInit, OnDestroy {
|
|||
this.initializedTables[id] = undefined;
|
||||
}
|
||||
|
||||
private destroyTables(): void {
|
||||
protected destroyTables(): void {
|
||||
for(const key in this.initializedTables) {
|
||||
this.destroyTable(key);
|
||||
}
|
||||
|
|
|
@ -150,13 +150,13 @@ export class DetailComponent extends BasePageComponent implements AfterViewInit
|
|||
|
||||
this.ngZone.run(() => {
|
||||
this.cards = this.createCards();
|
||||
this.loadTables(true);
|
||||
});
|
||||
});
|
||||
|
||||
const syncInfoRefreshEndSub: Subscription = this.daemonData.syncInfoRefreshEnd.subscribe(() => {
|
||||
this.loadTables();
|
||||
|
||||
this.cards = this.createCards();
|
||||
this.loadTables();
|
||||
});
|
||||
|
||||
this.subscriptions.push(syncStartSub, syncInfoRefreshEndSub);
|
||||
|
@ -169,17 +169,17 @@ export class DetailComponent extends BasePageComponent implements AfterViewInit
|
|||
});
|
||||
}
|
||||
|
||||
private loadPeersTable(): void {
|
||||
this.loadTable('peersTable', this.getPeers());
|
||||
private loadPeersTable(loading: boolean = false): void {
|
||||
this.loadTable('peersTable', this.getPeers(), loading);
|
||||
}
|
||||
|
||||
private loadSpansTable(): void {
|
||||
this.loadTable('spansTable', this.getSpans());
|
||||
private loadSpansTable(loading: boolean = false): void {
|
||||
this.loadTable('spansTable', this.getSpans(), loading);
|
||||
}
|
||||
|
||||
private loadTables(): void {
|
||||
this.loadPeersTable();
|
||||
this.loadSpansTable();
|
||||
private loadTables(loading: boolean = false): void {
|
||||
this.loadPeersTable(loading);
|
||||
this.loadSpansTable(loading);
|
||||
}
|
||||
|
||||
private createCards(): SimpleBootstrapCard[] {
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<div *ngIf="daemonRunning && !daemonStopping" class="tab-content" id="pills-tabContent">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-net-stats" role="tabpanel" aria-labelledby="pills-net-stats-tab" tabindex="0">
|
||||
<h2>Bytes In</h2>
|
||||
<h2><i class="bi bi-cloud-arrow-down m-4"></i> Download ({{ currentNetStats.totalGigaBytesIn.toFixed(2) }} GB)</h2>
|
||||
<canvas class="my-4 w-100" id="netStatsBytesInChart" width="900" height="380"></canvas>
|
||||
|
||||
<h2>Bytes Out</h2>
|
||||
<h2><i class="bi bi-cloud-arrow-up m-4"></i> Upload ({{ currentNetStats.totalGigaBytesOut.toFixed(2) }} GB)</h2>
|
||||
<canvas class="my-4 w-100" id="netStatsBytesOutChart" width="900" height="380"></canvas>
|
||||
</div>
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
|||
id="connectionsTable"
|
||||
data-toggle="connectionsTable"
|
||||
data-toolbar="#toolbar"
|
||||
|
||||
data-pagination="true"
|
||||
>
|
||||
<thead>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
|||
import { DaemonDataService, DaemonService } from '../../core/services';
|
||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||
import { Chart, ChartData } from 'chart.js/auto'
|
||||
import { NetStatsHistoryEntry } from '../../../common';
|
||||
import { NetStats, NetStatsHistoryEntry } from '../../../common';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { BasePageComponent } from '../base-page/base-page.component';
|
||||
|
||||
|
@ -32,6 +32,8 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
public setLimitSuccess: boolean = false;
|
||||
public setLimitError: string = '';
|
||||
|
||||
public currentNetStats: NetStats;
|
||||
|
||||
constructor(navbarService: NavbarService, private daemonService: DaemonService, private daemonData: DaemonDataService) {
|
||||
super(navbarService);
|
||||
this.setLinks([
|
||||
|
@ -40,6 +42,9 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
new NavbarLink('pills-limits-tab', '#pills-limit', 'pills-limit', false, 'Limit')
|
||||
]);
|
||||
|
||||
const lastNetStats = this.daemonData.netStatsHistory.last;
|
||||
this.currentNetStats = lastNetStats ? lastNetStats.netStats : new NetStats(0, 0, 0, 0);
|
||||
|
||||
const netStatsRefreshStartSub: Subscription = this.daemonData.netStatsRefreshEnd.subscribe(() => {
|
||||
this.refreshNetStatsHistory();
|
||||
});
|
||||
|
@ -54,6 +59,10 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
this.netStatsBytesInChart.destroy();
|
||||
this.netStatsBytesInChart = undefined;
|
||||
}
|
||||
if (this.netStatsBytesOutChart) {
|
||||
this.netStatsBytesOutChart.destroy();
|
||||
this.netStatsBytesOutChart = undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.initNetStatsHistoryChart();
|
||||
|
@ -78,7 +87,7 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
const data: number[] = [];
|
||||
this.daemonData.netStatsHistory.history.forEach((entry: NetStatsHistoryEntry) => {
|
||||
labels.push(`${entry.date.toLocaleTimeString()} ${entry.date.toLocaleDateString()}`);
|
||||
data.push(entry.netStats.totalBytesIn);
|
||||
data.push(entry.netStats.totalGigaBytesIn);
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -86,9 +95,10 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
datasets: [{
|
||||
data: data,
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: '#007bff',
|
||||
borderColor: '#ff5733',
|
||||
borderWidth: 4,
|
||||
pointBackgroundColor: '#007bff'
|
||||
pointBackgroundColor: '#ff5733',
|
||||
radius: 0
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
@ -98,7 +108,7 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
const data: number[] = [];
|
||||
this.daemonData.netStatsHistory.history.forEach((entry: NetStatsHistoryEntry) => {
|
||||
labels.push(`${entry.date.toLocaleTimeString()} ${entry.date.toLocaleDateString()}`);
|
||||
data.push(entry.netStats.totalBytesOut);
|
||||
data.push(entry.netStats.totalGigaBytesOut);
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -106,9 +116,10 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
datasets: [{
|
||||
data: data,
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: '#007bff',
|
||||
borderColor: '#ff5733',
|
||||
borderWidth: 4,
|
||||
pointBackgroundColor: '#007bff'
|
||||
pointBackgroundColor: '#ff5733',
|
||||
radius: 0
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
@ -166,32 +177,28 @@ export class NetworkComponent extends BasePageComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
private refreshNetStatsHistory(): void {
|
||||
if (!this.netStatsBytesInChart) {
|
||||
return;
|
||||
}
|
||||
|
||||
const last = this.daemonData.netStatsHistory.last;
|
||||
|
||||
if (!this.netStatsBytesInChart || !this.netStatsBytesOutChart) {
|
||||
this.initNetStatsHistoryChart();
|
||||
}
|
||||
else if (last) {
|
||||
const label = `${last.date.toLocaleTimeString()} ${last.date.toLocaleDateString()}`;
|
||||
const label = `${last.date.toLocaleDateString()} ${last.date.toLocaleTimeString()}`;
|
||||
|
||||
this.netStatsBytesInChart.data.labels?.push(label);
|
||||
this.netStatsBytesInChart.data.datasets.forEach((dataset) => {
|
||||
dataset.data.push(last.netStats.totalBytesIn);
|
||||
dataset.data.push(last.netStats.totalGigaBytesIn);
|
||||
});
|
||||
|
||||
this.netStatsBytesOutChart.data.labels?.push(label);
|
||||
this.netStatsBytesOutChart.data.datasets.forEach((dataset) => {
|
||||
dataset.data.push(last.netStats.totalBytesOut);
|
||||
dataset.data.push(last.netStats.totalGigaBytesOut);
|
||||
});
|
||||
|
||||
this.netStatsBytesInChart.update();
|
||||
this.netStatsBytesOutChart.update();
|
||||
this.currentNetStats = last.netStats;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async setLimit(): Promise<void> {
|
||||
|
|
|
@ -1,34 +1,46 @@
|
|||
export class NetStats {
|
||||
public readonly startTime: number;
|
||||
public readonly totalPacketsIn: number;
|
||||
public readonly totalBytesIn: number;
|
||||
public readonly totalBytesOut: number;
|
||||
public readonly startTime: number;
|
||||
public readonly totalPacketsIn: number;
|
||||
public readonly totalBytesIn: number;
|
||||
public readonly totalBytesOut: number;
|
||||
|
||||
constructor(startTime: number, totalPacketsIn: number, totalBytesIn: number, totalBytesOut: number) {
|
||||
this.startTime = startTime;
|
||||
this.totalPacketsIn = totalPacketsIn;
|
||||
this.totalBytesIn = totalBytesIn;
|
||||
this.totalBytesOut = totalBytesOut;
|
||||
}
|
||||
public get totalKiloBytesIn(): number {
|
||||
return this.totalBytesIn / 1000;
|
||||
}
|
||||
|
||||
public static parse(netStats: any): NetStats {
|
||||
const startTime: number = netStats.start_time;
|
||||
const totalPacketsIn: number = netStats.total_packets_in;
|
||||
const totalBytesIn: number = netStats.total_bytes_in;
|
||||
const totalBytesOut: number = netStats.total_bytes_out;
|
||||
public get totalKiloBytesOut(): number {
|
||||
return this.totalBytesOut / 1000;
|
||||
}
|
||||
|
||||
return new NetStats(startTime, totalPacketsIn, totalBytesIn, totalBytesOut);
|
||||
}
|
||||
public get totalMegaBytesIn(): number {
|
||||
return this.totalKiloBytesIn / 1000;
|
||||
}
|
||||
|
||||
public get totalMegaBytesOut(): number {
|
||||
return this.totalKiloBytesOut / 1000;
|
||||
}
|
||||
|
||||
public get totalGigaBytesIn(): number {
|
||||
return this.totalMegaBytesIn / 1000;
|
||||
}
|
||||
|
||||
public get totalGigaBytesOut(): number {
|
||||
return this.totalMegaBytesOut / 1000;
|
||||
}
|
||||
|
||||
constructor(startTime: number, totalPacketsIn: number, totalBytesIn: number, totalBytesOut: number) {
|
||||
this.startTime = startTime;
|
||||
this.totalPacketsIn = totalPacketsIn;
|
||||
this.totalBytesIn = totalBytesIn;
|
||||
this.totalBytesOut = totalBytesOut;
|
||||
}
|
||||
|
||||
public static parse(netStats: any): NetStats {
|
||||
const startTime: number = netStats.start_time;
|
||||
const totalPacketsIn: number = netStats.total_packets_in;
|
||||
const totalBytesIn: number = netStats.total_bytes_in;
|
||||
const totalBytesOut: number = netStats.total_bytes_out;
|
||||
|
||||
return new NetStats(startTime, totalPacketsIn, totalBytesIn, totalBytesOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* start_time - unsigned int; Unix start time.
|
||||
total_packets_in - unsigned int;
|
||||
total_bytes_in - unsigned int;
|
||||
total_packets_out - unsigned int;
|
||||
total_bytes_out - unsigned int;
|
||||
status - string; General RPC error code. "OK" means everything looks good.
|
||||
untrusted - boolean; States if the result is obtained using the bootstrap mode, and is therefore not trusted (true), or when the daemon is fully synced and thus handles the RPC locally (false).
|
||||
*/
|
Loading…
Reference in a new issue