mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-18 00:21:01 +00:00
I/O metrics (#224)
* feat: Proxy Node IO stats to the FE * chore: Sync up FE * feat: Charts for cache sizes * feat: All graphs are in * chore: Remove browserlist
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
NodeCount,
|
||||
NodeDetails,
|
||||
NodeStats,
|
||||
NodeIO,
|
||||
NodeHardware,
|
||||
NodeLocation,
|
||||
BlockNumber,
|
||||
@@ -43,6 +44,7 @@ export const Actions = {
|
||||
AfgReceivedPrecommit : 0x12 as 0x12,
|
||||
AfgAuthoritySet : 0x13 as 0x13,
|
||||
StaleNode : 0x14 as 0x14,
|
||||
NodeIO : 0x15 as 0x15,
|
||||
};
|
||||
|
||||
export type Action = typeof Actions[keyof typeof Actions];
|
||||
@@ -70,7 +72,7 @@ export namespace Variants {
|
||||
|
||||
export interface AddedNodeMessage extends MessageBase {
|
||||
action: typeof Actions.AddedNode;
|
||||
payload: [NodeId, NodeDetails, NodeStats, NodeHardware, BlockDetails, Maybe<NodeLocation>, Timestamp];
|
||||
payload: [NodeId, NodeDetails, NodeStats, NodeIO, NodeHardware, BlockDetails, Maybe<NodeLocation>, Timestamp];
|
||||
}
|
||||
|
||||
export interface RemovedNodeMessage extends MessageBase {
|
||||
@@ -103,6 +105,11 @@ export namespace Variants {
|
||||
payload: [NodeId, NodeHardware];
|
||||
}
|
||||
|
||||
export interface NodeIOMessage extends MessageBase {
|
||||
action: typeof Actions.NodeIO;
|
||||
payload: [NodeId, NodeIO];
|
||||
}
|
||||
|
||||
export interface TimeSyncMessage extends MessageBase {
|
||||
action: typeof Actions.TimeSync;
|
||||
payload: Timestamp;
|
||||
|
||||
@@ -9,4 +9,4 @@ import * as FeedMessage from './feed';
|
||||
export { Types, FeedMessage };
|
||||
|
||||
// Increment this if breaking changes were made to types in `feed.ts`
|
||||
export const VERSION: Types.FeedVersion = 28 as Types.FeedVersion;
|
||||
export const VERSION: Types.FeedVersion = 29 as Types.FeedVersion;
|
||||
|
||||
@@ -22,6 +22,7 @@ export type Longitude = Opaque<number, 'Longitude'>;
|
||||
export type City = Opaque<string, 'City'>;
|
||||
export type MemoryUse = Opaque<number, 'MemoryUse'>;
|
||||
export type CPUUse = Opaque<number, 'CPUUse'>;
|
||||
export type Bytes = Opaque<number, 'Bytes'>;
|
||||
export type BytesPerSecond = Opaque<number, 'BytesPerSecond'>;
|
||||
export type NetworkId = Opaque<string, 'NetworkId'>;
|
||||
export type NetworkState = Opaque<string | object, 'NetworkState'>;
|
||||
@@ -29,6 +30,7 @@ export type NetworkState = Opaque<string | object, 'NetworkState'>;
|
||||
export type BlockDetails = [BlockNumber, BlockHash, Milliseconds, Timestamp, Maybe<PropagationTime>];
|
||||
export type NodeDetails = [NodeName, NodeImplementation, NodeVersion, Maybe<Address>, Maybe<NetworkId>];
|
||||
export type NodeStats = [PeerCount, TransactionCount];
|
||||
export type NodeIO = [Array<Bytes>, Array<Bytes>, Array<BytesPerSecond>, Array<BytesPerSecond>];
|
||||
export type NodeHardware = [Array<MemoryUse>, Array<CPUUse>, Array<BytesPerSecond>, Array<BytesPerSecond>, Array<Timestamp>];
|
||||
export type NodeLocation = [Latitude, Longitude, City];
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ export default class App extends React.Component<{}, State> {
|
||||
mem: true,
|
||||
upload: false,
|
||||
download: false,
|
||||
stateCacheSize: false,
|
||||
dbCacheSize: false,
|
||||
diskRead: false,
|
||||
diskWrite: false,
|
||||
blocknumber: true,
|
||||
blockhash: true,
|
||||
blocktime: true,
|
||||
|
||||
@@ -166,9 +166,9 @@ export class Connection {
|
||||
}
|
||||
|
||||
case Actions.AddedNode: {
|
||||
const [id, nodeDetails, nodeStats, nodeHardware, blockDetails, location, connectedAt] = message.payload;
|
||||
const [id, nodeDetails, nodeStats, nodeIO, nodeHardware, blockDetails, location, connectedAt] = message.payload;
|
||||
const pinned = this.pins.has(nodeDetails[0]);
|
||||
const node = new Node(pinned, id, nodeDetails, nodeStats, nodeHardware, blockDetails, location, connectedAt);
|
||||
const node = new Node(pinned, id, nodeDetails, nodeStats, nodeIO, nodeHardware, blockDetails, location, connectedAt);
|
||||
|
||||
nodes.add(node);
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ import cpuIcon from '../../icons/microchip-solid.svg';
|
||||
import memoryIcon from '../../icons/memory-solid.svg';
|
||||
import uploadIcon from '../../icons/cloud-upload.svg';
|
||||
import downloadIcon from '../../icons/cloud-download.svg';
|
||||
import readIcon from '../../icons/arrow-up.svg';
|
||||
import writeIcon from '../../icons/arrow-down.svg';
|
||||
import databaseIcon from '../../icons/database.svg';
|
||||
import stateIcon from '../../icons/git-branch.svg';
|
||||
import networkIcon from '../../icons/network.svg';
|
||||
import uptimeIcon from '../../icons/pulse.svg';
|
||||
import externalLinkIcon from '../../icons/link-external.svg';
|
||||
@@ -210,6 +214,74 @@ export namespace Column {
|
||||
}
|
||||
};
|
||||
|
||||
export const STATE_CACHE: Column = {
|
||||
label: 'State Cache Size',
|
||||
icon: stateIcon,
|
||||
width: 40,
|
||||
setting: 'stateCacheSize',
|
||||
sortBy: ({ stateCacheSize }) => stateCacheSize.length < 3 ? 0 : stateCacheSize[stateCacheSize.length - 1],
|
||||
render: ({ stateCacheSize, chartstamps }) => {
|
||||
if (stateCacheSize.length < 3) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return (
|
||||
<Sparkline width={44} height={16} stroke={1} format={formatBytes} values={stateCacheSize} stamps={chartstamps} minScale={MEMORY_SCALE} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const DB_CACHE: Column = {
|
||||
label: 'Database Cache Size',
|
||||
icon: databaseIcon,
|
||||
width: 40,
|
||||
setting: 'dbCacheSize',
|
||||
sortBy: ({ dbCacheSize }) => dbCacheSize.length < 3 ? 0 : dbCacheSize[dbCacheSize.length - 1],
|
||||
render: ({ dbCacheSize, chartstamps }) => {
|
||||
if (dbCacheSize.length < 3) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return (
|
||||
<Sparkline width={44} height={16} stroke={1} format={formatBytes} values={dbCacheSize} stamps={chartstamps} minScale={MEMORY_SCALE} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const DISK_READ: Column = {
|
||||
label: 'Disk Read',
|
||||
icon: readIcon,
|
||||
width: 40,
|
||||
setting: 'diskRead',
|
||||
sortBy: ({ diskRead }) => diskRead.length < 3 ? 0 : diskRead[diskRead.length - 1],
|
||||
render: ({ diskRead, chartstamps }) => {
|
||||
if (diskRead.length < 3) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return (
|
||||
<Sparkline width={44} height={16} stroke={1} format={formatBandwidth} values={diskRead} stamps={chartstamps} minScale={MEMORY_SCALE} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const DISK_WRITE: Column = {
|
||||
label: 'Disk Write',
|
||||
icon: writeIcon,
|
||||
width: 40,
|
||||
setting: 'diskWrite',
|
||||
sortBy: ({ diskWrite }) => diskWrite.length < 3 ? 0 : diskWrite[diskWrite.length - 1],
|
||||
render: ({ diskWrite, chartstamps }) => {
|
||||
if (diskWrite.length < 3) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return (
|
||||
<Sparkline width={44} height={16} stroke={1} format={formatBandwidth} values={diskWrite} stamps={chartstamps} minScale={MEMORY_SCALE} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const BLOCK_NUMBER: Column = {
|
||||
label: 'Block',
|
||||
icon: blockIcon,
|
||||
@@ -330,6 +402,18 @@ function formatMemory(kbs: number, stamp: Maybe<Types.Timestamp>): string {
|
||||
}
|
||||
}
|
||||
|
||||
function formatBytes(bytes: number, stamp: Maybe<Types.Timestamp>): string {
|
||||
const ago = stamp ? ` (${formatStamp(stamp)})` : '';
|
||||
|
||||
if (bytes >= 1024 * 1024) {
|
||||
return `${(bytes / (1024 * 1024)).toFixed(1)} MB${ago}`;
|
||||
} else if (bytes >= 1000) {
|
||||
return `${(bytes / 1024).toFixed(1)} kB${ago}`;
|
||||
} else {
|
||||
return `${bytes} B${ago}`;
|
||||
}
|
||||
}
|
||||
|
||||
function formatBandwidth(bps: number, stamp: Maybe<Types.Timestamp>): string {
|
||||
const ago = stamp ? ` (${formatStamp(stamp)})` : '';
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ export class Row extends React.Component<Row.Props, Row.State> {
|
||||
Column.MEM,
|
||||
Column.UPLOAD,
|
||||
Column.DOWNLOAD,
|
||||
Column.STATE_CACHE,
|
||||
Column.DB_CACHE,
|
||||
Column.DISK_READ,
|
||||
Column.DISK_WRITE,
|
||||
Column.BLOCK_NUMBER,
|
||||
Column.BLOCK_HASH,
|
||||
Column.FINALIZED,
|
||||
|
||||
@@ -43,6 +43,10 @@ export class Node {
|
||||
public cpu: Types.CPUUse[];
|
||||
public upload: Types.BytesPerSecond[];
|
||||
public download: Types.BytesPerSecond[];
|
||||
public stateCacheSize: Types.Bytes[];
|
||||
public dbCacheSize: Types.Bytes[];
|
||||
public diskRead: Types.BytesPerSecond[];
|
||||
public diskWrite: Types.BytesPerSecond[];
|
||||
public chartstamps: Types.Timestamp[];
|
||||
|
||||
public height: Types.BlockNumber;
|
||||
@@ -66,6 +70,7 @@ export class Node {
|
||||
id: Types.NodeId,
|
||||
nodeDetails: Types.NodeDetails,
|
||||
nodeStats: Types.NodeStats,
|
||||
nodeIO: Types.NodeIO,
|
||||
nodeHardware: Types.NodeHardware,
|
||||
blockDetails: Types.BlockDetails,
|
||||
location: Maybe<Types.NodeLocation>,
|
||||
@@ -89,6 +94,7 @@ export class Node {
|
||||
this.sortableVersion = (major * 1000 + minor * 100 + patch) | 0;
|
||||
|
||||
this.updateStats(nodeStats);
|
||||
this.updateIO(nodeIO);
|
||||
this.updateHardware(nodeHardware);
|
||||
this.updateBlock(blockDetails);
|
||||
|
||||
@@ -106,6 +112,17 @@ export class Node {
|
||||
this.trigger();
|
||||
}
|
||||
|
||||
public updateIO(io: Types.NodeIO) {
|
||||
const [stateCacheSize, dbCacheSize, diskRead, diskWrite] = io;
|
||||
|
||||
this.stateCacheSize = stateCacheSize;
|
||||
this.dbCacheSize = dbCacheSize;
|
||||
this.diskRead = diskRead;
|
||||
this.diskWrite = diskWrite;
|
||||
|
||||
this.trigger();
|
||||
}
|
||||
|
||||
public updateHardware(hardware: Types.NodeHardware) {
|
||||
const [mem, cpu, upload, download, chartstamps] = hardware;
|
||||
|
||||
@@ -202,6 +219,10 @@ export namespace State {
|
||||
mem: boolean;
|
||||
upload: boolean;
|
||||
download: boolean;
|
||||
stateCacheSize: boolean;
|
||||
dbCacheSize: boolean;
|
||||
diskRead: boolean;
|
||||
diskWrite: boolean;
|
||||
blocknumber: boolean;
|
||||
blockhash: boolean;
|
||||
finalized: boolean;
|
||||
|
||||
Reference in New Issue
Block a user