mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-20 21:01:07 +00:00
Pass through node details
This commit is contained in:
@@ -20,13 +20,14 @@ export default class Aggregator extends EventEmitter {
|
|||||||
this.broadcast(Feed.addedNode(node));
|
this.broadcast(Feed.addedNode(node));
|
||||||
|
|
||||||
node.once('disconnect', () => {
|
node.once('disconnect', () => {
|
||||||
node.removeAllListeners('block');
|
node.removeAllListeners();
|
||||||
|
|
||||||
this.nodes.remove(node);
|
this.nodes.remove(node);
|
||||||
this.broadcast(Feed.removedNode(node));
|
this.broadcast(Feed.removedNode(node));
|
||||||
});
|
});
|
||||||
|
|
||||||
node.on('block', () => this.updateBlock(node));
|
node.on('block', () => this.updateBlock(node));
|
||||||
|
node.on('stats', () => this.broadcast(Feed.stats(node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFeed(feed: Feed) {
|
public addFeed(feed: Feed) {
|
||||||
@@ -40,7 +41,7 @@ export default class Aggregator extends EventEmitter {
|
|||||||
|
|
||||||
feed.once('disconnect', () => {
|
feed.once('disconnect', () => {
|
||||||
this.feeds.remove(feed);
|
this.feeds.remove(feed);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public nodeList(): IterableIterator<Node> {
|
public nodeList(): IterableIterator<Node> {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default class Feed extends EventEmitter {
|
|||||||
public static addedNode(node: Node): FeedData {
|
public static addedNode(node: Node): FeedData {
|
||||||
return serialize({
|
return serialize({
|
||||||
action: 'added',
|
action: 'added',
|
||||||
payload: [node.id, node.nodeDetails(), node.blockDetails()]
|
payload: [node.id, node.nodeDetails(), node.nodeStats(), node.blockDetails()]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +59,13 @@ export default class Feed extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static stats(node: Node): FeedData {
|
||||||
|
return serialize({
|
||||||
|
action: 'stats',
|
||||||
|
payload: [node.id, node.nodeStats()]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public send(data: FeedData) {
|
public send(data: FeedData) {
|
||||||
this.socket.send(data);
|
this.socket.send(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ interface MessageBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface BestBlock {
|
export interface BestBlock {
|
||||||
best: string,
|
best: Types.BlockHash,
|
||||||
height: Types.BlockNumber,
|
height: Types.BlockNumber,
|
||||||
ts: Date,
|
ts: Date,
|
||||||
}
|
}
|
||||||
@@ -44,14 +44,14 @@ interface SystemConnected {
|
|||||||
name: Types.NodeName,
|
name: Types.NodeName,
|
||||||
chain: string,
|
chain: string,
|
||||||
config: string,
|
config: string,
|
||||||
implementation: string,
|
implementation: Types.NodeImplementation,
|
||||||
version: string,
|
version: Types.NodeVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SystemInterval extends BestBlock {
|
export interface SystemInterval extends BestBlock {
|
||||||
msg: 'system.interval',
|
msg: 'system.interval',
|
||||||
txcount: number,
|
txcount: Types.TransactionCount,
|
||||||
peers: number,
|
peers: Types.PeerCount,
|
||||||
status: 'Idle' | string, // TODO: 'Idle' | ...?
|
status: 'Idle' | string, // TODO: 'Idle' | ...?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import * as EventEmitter from 'events';
|
import * as EventEmitter from 'events';
|
||||||
import { Maybe, Types, idGenerator } from '@dotstats/common';
|
import { Maybe, Types, idGenerator } from '@dotstats/common';
|
||||||
import { parseMessage, getBestBlock, Message, BestBlock } from './message';
|
import { parseMessage, getBestBlock, Message, BestBlock, SystemInterval } from './message';
|
||||||
|
|
||||||
const BLOCK_TIME_HISTORY = 10;
|
const BLOCK_TIME_HISTORY = 10;
|
||||||
const TIMEOUT = 1000 * 60 * 5; // 5 seconds
|
const TIMEOUT = 1000 * 60 * 1; // 1 minute
|
||||||
|
|
||||||
const nextId = idGenerator<Types.NodeId>();
|
const nextId = idGenerator<Types.NodeId>();
|
||||||
|
|
||||||
@@ -12,18 +12,27 @@ export default class Node extends EventEmitter {
|
|||||||
public lastMessage: number;
|
public lastMessage: number;
|
||||||
public id: Types.NodeId;
|
public id: Types.NodeId;
|
||||||
public name: Types.NodeName;
|
public name: Types.NodeName;
|
||||||
public implementation: string;
|
public implementation: Types.NodeImplementation;
|
||||||
public version: string;
|
public version: Types.NodeVersion;
|
||||||
public config: string;
|
public config: string;
|
||||||
public height = 0 as Types.BlockNumber;
|
public height = 0 as Types.BlockNumber;
|
||||||
public latency = 0 as Types.Milliseconds;
|
public latency = 0 as Types.Milliseconds;
|
||||||
public blockTime = 0 as Types.Milliseconds;
|
public blockTime = 0 as Types.Milliseconds;
|
||||||
|
|
||||||
|
private peers = 0 as Types.PeerCount;
|
||||||
|
private txcount = 0 as Types.TransactionCount;
|
||||||
|
|
||||||
private socket: WebSocket;
|
private socket: WebSocket;
|
||||||
private blockTimes: Array<number> = new Array(BLOCK_TIME_HISTORY);
|
private blockTimes: Array<number> = new Array(BLOCK_TIME_HISTORY);
|
||||||
private lastBlockAt: Maybe<Date> = null;
|
private lastBlockAt: Maybe<Date> = null;
|
||||||
|
|
||||||
constructor(socket: WebSocket, name: Types.NodeName, config: string, implentation: string, version: string) {
|
constructor(
|
||||||
|
socket: WebSocket,
|
||||||
|
name: Types.NodeName,
|
||||||
|
config: string,
|
||||||
|
implentation: Types.NodeImplementation,
|
||||||
|
version: Types.NodeVersion,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.lastMessage = Date.now();
|
this.lastMessage = Date.now();
|
||||||
@@ -37,11 +46,11 @@ export default class Node extends EventEmitter {
|
|||||||
console.log(`Listening to a new node: ${name}`);
|
console.log(`Listening to a new node: ${name}`);
|
||||||
|
|
||||||
socket.on('message', (data) => {
|
socket.on('message', (data) => {
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
const message = parseMessage(data);
|
const message = parseMessage(data);
|
||||||
|
|
||||||
if (!message) return;
|
if (!message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.lastMessage = Date.now();
|
this.lastMessage = Date.now();
|
||||||
this.updateLatency(message.ts);
|
this.updateLatency(message.ts);
|
||||||
@@ -51,6 +60,10 @@ export default class Node extends EventEmitter {
|
|||||||
if (update) {
|
if (update) {
|
||||||
this.updateBestBlock(update);
|
this.updateBestBlock(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.msg === 'system.interval') {
|
||||||
|
this.onSystemInterval(message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('close', () => {
|
socket.on('close', () => {
|
||||||
@@ -74,8 +87,6 @@ export default class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handler(data: WebSocket.Data) {
|
function handler(data: WebSocket.Data) {
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
const message = parseMessage(data);
|
const message = parseMessage(data);
|
||||||
|
|
||||||
if (message && message.msg === "system.connected") {
|
if (message && message.msg === "system.connected") {
|
||||||
@@ -106,16 +117,15 @@ export default class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public nodeDetails(): Types.NodeDetails {
|
public nodeDetails(): Types.NodeDetails {
|
||||||
return {
|
return [this.name, this.implementation, this.version];
|
||||||
name: this.name,
|
}
|
||||||
};
|
|
||||||
|
public nodeStats(): Types.NodeStats {
|
||||||
|
return [this.peers, this.txcount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public blockDetails(): Types.BlockDetails {
|
public blockDetails(): Types.BlockDetails {
|
||||||
return {
|
return [this.height, this.blockTime];
|
||||||
height: this.height,
|
|
||||||
blockTime: this.blockTime,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get average(): number {
|
public get average(): number {
|
||||||
@@ -143,6 +153,17 @@ export default class Node extends EventEmitter {
|
|||||||
this.emit('disconnect');
|
this.emit('disconnect');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onSystemInterval(message: SystemInterval) {
|
||||||
|
const { peers, txcount } = message;
|
||||||
|
|
||||||
|
if (this.peers !== peers || this.txcount !== txcount) {
|
||||||
|
this.peers = peers;
|
||||||
|
this.txcount = txcount;
|
||||||
|
|
||||||
|
this.emit('stats');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private updateLatency(time: Date) {
|
private updateLatency(time: Date) {
|
||||||
this.latency = (this.lastMessage - +time) as Types.Milliseconds;
|
this.latency = (this.lastMessage - +time) as Types.Milliseconds;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
"outDir": "build"
|
"outDir": "build"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts"
|
"./src/**/*.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ import { Id } from './id';
|
|||||||
export type FeedId = Id<'Feed'>;
|
export type FeedId = Id<'Feed'>;
|
||||||
export type NodeId = Id<'Node'>;
|
export type NodeId = Id<'Node'>;
|
||||||
export type NodeName = Opaque<string, 'NodeName'>;
|
export type NodeName = Opaque<string, 'NodeName'>;
|
||||||
|
export type NodeImplementation = Opaque<string, 'NodeImplementation'>;
|
||||||
|
export type NodeVersion = Opaque<string, 'NodeVersion'>;
|
||||||
export type BlockNumber = Opaque<number, 'BlockNumber'>;
|
export type BlockNumber = Opaque<number, 'BlockNumber'>;
|
||||||
|
export type BlockHash = Opaque<string, 'BlockHash'>;
|
||||||
export type Milliseconds = Opaque<number, 'Milliseconds'>;
|
export type Milliseconds = Opaque<number, 'Milliseconds'>;
|
||||||
|
export type PeerCount = Opaque<number, 'PeerCount'>;
|
||||||
|
export type TransactionCount = Opaque<number, 'TransactionCount'>;
|
||||||
|
|
||||||
export interface BlockDetails {
|
export type BlockDetails = [BlockNumber, Milliseconds];
|
||||||
height: BlockNumber;
|
export type NodeDetails = [NodeName, NodeImplementation, NodeVersion];
|
||||||
blockTime: Milliseconds;
|
export type NodeStats = [PeerCount, TransactionCount];
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeDetails {
|
|
||||||
name: NodeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BestBlock {
|
interface BestBlock {
|
||||||
action: 'best';
|
action: 'best';
|
||||||
@@ -23,7 +23,7 @@ interface BestBlock {
|
|||||||
|
|
||||||
interface AddedNode {
|
interface AddedNode {
|
||||||
action: 'added';
|
action: 'added';
|
||||||
payload: [NodeId, NodeDetails, BlockDetails];
|
payload: [NodeId, NodeDetails, NodeStats, BlockDetails];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RemovedNode {
|
interface RemovedNode {
|
||||||
@@ -36,4 +36,9 @@ interface Imported {
|
|||||||
payload: [NodeId, BlockDetails];
|
payload: [NodeId, BlockDetails];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FeedMessage = BestBlock | AddedNode | RemovedNode | Imported;
|
interface Stats {
|
||||||
|
action: 'stats';
|
||||||
|
payload: [NodeId, NodeStats];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FeedMessage = BestBlock | AddedNode | RemovedNode | Imported | Stats;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Types } from '@dotstats/common';
|
|||||||
|
|
||||||
interface Node {
|
interface Node {
|
||||||
nodeDetails: Types.NodeDetails,
|
nodeDetails: Types.NodeDetails,
|
||||||
|
nodeStats: Types.NodeStats,
|
||||||
blockDetails: Types.BlockDetails,
|
blockDetails: Types.BlockDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,18 +36,27 @@ export default class App extends React.Component<{}, State> {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th><th>Block</th><th>Block time</th>
|
<th>Node Name</th><th>Node Type</th><th>Peers</th><th>Transactions</th><th>Block</th><th>Block time</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
this.nodes().map(([ id, node ]) => (
|
this.nodes().map(([ id, node ]) => {
|
||||||
<tr key={id}>
|
const [name, implementation, version] = node.nodeDetails;
|
||||||
<td>{node.nodeDetails.name}</td>
|
const [height, blockTime] = node.blockDetails;
|
||||||
<td>{node.blockDetails.height}</td>
|
const [peers, txcount] = node.nodeStats;
|
||||||
<td>{node.blockDetails.blockTime / 1000}s</td>
|
|
||||||
</tr>
|
return (
|
||||||
))
|
<tr key={id}>
|
||||||
|
<td>{name}</td>
|
||||||
|
<td>{implementation} v{version}</td>
|
||||||
|
<td>{peers}</td>
|
||||||
|
<td>{txcount}</td>
|
||||||
|
<td>{height}</td>
|
||||||
|
<td>{blockTime / 1000}s</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -67,8 +77,8 @@ export default class App extends React.Component<{}, State> {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 'added': {
|
case 'added': {
|
||||||
const [id, nodeDetails, blockDetails] = message.payload;
|
const [id, nodeDetails, nodeStats, blockDetails] = message.payload;
|
||||||
const node = { nodeDetails, blockDetails };
|
const node = { nodeDetails, nodeStats, blockDetails };
|
||||||
|
|
||||||
nodes.set(id, node);
|
nodes.set(id, node);
|
||||||
}
|
}
|
||||||
@@ -89,6 +99,18 @@ export default class App extends React.Component<{}, State> {
|
|||||||
node.blockDetails = blockDetails;
|
node.blockDetails = blockDetails;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'stats': {
|
||||||
|
const [id, nodeStats] = message.payload;
|
||||||
|
|
||||||
|
const node = nodes.get(id);
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.nodeStats = nodeStats;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
scripts/build-common.sh
|
scripts/build-common.sh
|
||||||
scripts/build-backend.sh
|
scripts/build-backend.sh
|
||||||
node packages/backend/build/index.js
|
node packages/backend/build/backend/src/index.js
|
||||||
|
|||||||
@@ -22,9 +22,6 @@
|
|||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"./node_modules/@types"
|
"./node_modules/@types"
|
||||||
],
|
],
|
||||||
"include": [
|
|
||||||
"src/**/*.ts"
|
|
||||||
],
|
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user