diff --git a/.gitignore b/.gitignore index e7e1f36fe..1d03a2083 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # See https://help.github.com/ignore-files/ for more about ignoring files. htdocs - +.idea backend/target # dependencies diff --git a/backend/.dockerignore b/backend/.dockerignore index af65baafb..0fb67fbfe 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -1,3 +1,4 @@ target *.Dockerfile .git +.idea \ No newline at end of file diff --git a/backend/telemetry_core/src/aggregator/inner_loop.rs b/backend/telemetry_core/src/aggregator/inner_loop.rs index 1c8559d21..52eee8bbc 100644 --- a/backend/telemetry_core/src/aggregator/inner_loop.rs +++ b/backend/telemetry_core/src/aggregator/inner_loop.rs @@ -69,7 +69,7 @@ pub enum FromShardWebsocket { Disconnected, } -/// The aggregator can these messages back to a shard connection. +/// The aggregator can send these messages back to a shard connection. #[derive(Debug)] pub enum ToShardWebsocket { /// Mute messages to the core by passing the shard-local ID of them. @@ -84,7 +84,7 @@ pub enum ToShardWebsocket { pub enum FromFeedWebsocket { /// When the socket is opened, it'll send this first /// so that we have a way to communicate back to it. - /// Unbounded so that slow feeds don't block aggregato + /// Unbounded so that slow feeds don't block aggregator /// progress. Initialize { channel: flume::Sender, diff --git a/backend/telemetry_core/src/feed_message.rs b/backend/telemetry_core/src/feed_message.rs index c1d033ec0..2ba2a9180 100644 --- a/backend/telemetry_core/src/feed_message.rs +++ b/backend/telemetry_core/src/feed_message.rs @@ -183,12 +183,18 @@ impl FeedMessageWrite for AddedNode<'_> { let AddedNode(nid, node, expose_node_details) = self; let details = node.details(); - // Hide the ip, sysinfo and hwbench if the `expose_node_details` flag was not specified. + // Always include sysinfo, conditionally include ip and hwbench based on expose_node_details. let node_hwbench = node.hwbench(); - let (ip, sys_info, hwbench) = if *expose_node_details { - (&details.ip, &details.sysinfo, &node_hwbench) + let ip = if *expose_node_details { + &details.ip } else { - (&None, &None, &None) + &None + }; + let sys_info = &details.sysinfo; + let hwbench = if *expose_node_details { + &node_hwbench + } else { + &None }; let details = ( @@ -197,6 +203,9 @@ impl FeedMessageWrite for AddedNode<'_> { &details.version, &details.validator, &details.network_id, + &details.target_os, + &details.target_arch, + &details.target_env, &ip, &sys_info, &hwbench, diff --git a/backend/telemetry_core/src/state/chain_stats.rs b/backend/telemetry_core/src/state/chain_stats.rs index 3f79e574d..be5c94676 100644 --- a/backend/telemetry_core/src/state/chain_stats.rs +++ b/backend/telemetry_core/src/state/chain_stats.rs @@ -16,7 +16,6 @@ use super::counter::{Counter, CounterValue}; use crate::feed_message::ChainStats; - // These are the benchmark scores generated on our reference hardware. const REFERENCE_CPU_SCORE: u64 = 1028; const REFERENCE_MEMORY_SCORE: u64 = 14899; diff --git a/backend/telemetry_core/src/state/counter.rs b/backend/telemetry_core/src/state/counter.rs index 49ea45752..cc1f474c4 100644 --- a/backend/telemetry_core/src/state/counter.rs +++ b/backend/telemetry_core/src/state/counter.rs @@ -39,7 +39,7 @@ impl Counter where K: Sized + std::hash::Hash + Eq, { - /// Either adds or removes a single occurrence of a given `key`. + /// Either adds or removes a single occurence of a given `key`. pub fn modify<'a, Q>(&mut self, key: Option<&'a Q>, op: CounterValue) where Q: ?Sized + std::hash::Hash + Eq, diff --git a/backend/telemetry_shard/src/json_message/mod.rs b/backend/telemetry_shard/src/json_message/mod.rs index 37892574c..2b54cf88e 100644 --- a/backend/telemetry_shard/src/json_message/mod.rs +++ b/backend/telemetry_shard/src/json_message/mod.rs @@ -19,5 +19,4 @@ mod hash; mod node_message; -pub use hash::Hash; pub use node_message::*; diff --git a/backend/test_utils/src/feed_message_de.rs b/backend/test_utils/src/feed_message_de.rs index aa0d72431..6161125ec 100644 --- a/backend/test_utils/src/feed_message_de.rs +++ b/backend/test_utils/src/feed_message_de.rs @@ -136,6 +136,9 @@ pub struct NodeDetails { pub version: String, pub validator: Option, pub network_id: Option, + pub os: String, + pub arch: String, + pub target_env: String, pub ip: Option, pub sysinfo: Option, } @@ -144,7 +147,6 @@ impl FeedMessage { /// Decode a slice of bytes into a vector of feed messages pub fn from_bytes(bytes: &[u8]) -> Result, anyhow::Error> { let v: Vec<&RawValue> = serde_json::from_slice(bytes)?; - let mut feed_messages = vec![]; for raw_keyval in v.chunks(2) { let raw_key = raw_keyval[0]; @@ -161,6 +163,8 @@ impl FeedMessage { // Deserialize the feed message to a value based on the "action" key fn decode(action: u8, raw_val: &RawValue) -> Result { + println!("\n\n"); + println!("{raw_val:#?}"); let feed_message = match action { // Version: 0 => { @@ -189,7 +193,19 @@ impl FeedMessage { 3 => { let ( node_id, - (name, implementation, version, validator, network_id, ip, sysinfo, hwbench), + ( + name, + implementation, + version, + validator, + network_id, + os, + arch, + target_env, + ip, + sysinfo, + hwbench, + ), stats, io, hardware, @@ -209,6 +225,9 @@ impl FeedMessage { version, validator, network_id, + os, + arch, + target_env, ip, sysinfo, }, diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 80b1f7e64..4bd145464 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -30,7 +30,7 @@ "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": [ "warn", - { + { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" diff --git a/frontend/Dockerfile.README.md b/frontend/Dockerfile.README.md index 017a63c81..c8d2305de 100644 --- a/frontend/Dockerfile.README.md +++ b/frontend/Dockerfile.README.md @@ -1,3 +1,3 @@ # substrate-telemetry-frontend -### [Documentation](https://github.com/paritytech/substrate-telemetry/blob/master/README.md) \ No newline at end of file +### [Documentation](https://github.com/paritytech/substrate-telemetry/blob/master/README.md) diff --git a/frontend/assets/index.html b/frontend/assets/index.html index 6eff0f347..be1c24ae3 100644 --- a/frontend/assets/index.html +++ b/frontend/assets/index.html @@ -1,23 +1,25 @@ - - - + + + Polkadot Telemetry - + - +
diff --git a/frontend/assets/mock.image.js b/frontend/assets/mock.image.js index 1b627634a..2c2042e78 100644 --- a/frontend/assets/mock.image.js +++ b/frontend/assets/mock.image.js @@ -1,3 +1,3 @@ // loading images gives back a path. This is what we replace // that with for tests: -module.exports = 'test-image-stub'; \ No newline at end of file +module.exports = 'test-image-stub'; diff --git a/frontend/assets/mock.style.js b/frontend/assets/mock.style.js index 44feea96e..110f10ba1 100644 --- a/frontend/assets/mock.style.js +++ b/frontend/assets/mock.style.js @@ -1,2 +1,2 @@ // For loading styles, give back an empty object in tests: -module.exports = {}; \ No newline at end of file +module.exports = {}; diff --git a/frontend/images.d.ts b/frontend/images.d.ts index fd9ba477f..aa6feaf0d 100644 --- a/frontend/images.d.ts +++ b/frontend/images.d.ts @@ -14,6 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -declare module '*.svg' -declare module '*.png' -declare module '*.jpg' +declare module '*.svg'; +declare module '*.png'; +declare module '*.jpg'; diff --git a/frontend/jest.config.js b/frontend/jest.config.js index e35734749..e69f909b3 100644 --- a/frontend/jest.config.js +++ b/frontend/jest.config.js @@ -20,7 +20,8 @@ module.exports = { testEnvironment: 'jsdom', setupFiles: ['/setupJest.js'], moduleNameMapper: { - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/assets/mock.image.js", - "\\.(css|less|scss|sass)$": "/assets/mock.style.js" + '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': + '/assets/mock.image.js', + '\\.(css|less|scss|sass)$': '/assets/mock.style.js', }, -}; \ No newline at end of file +}; diff --git a/frontend/setupJest.js b/frontend/setupJest.js index a78eb3b42..ddacb44d8 100644 --- a/frontend/setupJest.js +++ b/frontend/setupJest.js @@ -22,4 +22,4 @@ global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; // polyfill fetch since it's not in jsdom: -require('whatwg-fetch'); \ No newline at end of file +require('whatwg-fetch'); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4af9b1d10..94b537a6f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -46,6 +46,7 @@ export default class App extends React.Component { constructor(props: Record) { super(props); + //todo! Check what's important to set to true, false this.settings = new PersistentObject( 'settings', { @@ -55,8 +56,6 @@ export default class App extends React.Component { networkId: false, peers: true, txs: true, - cpu: true, - mem: true, upload: false, download: false, stateCacheSize: false, @@ -65,12 +64,27 @@ export default class App extends React.Component { diskWrite: false, blocknumber: true, blockhash: true, - blocktime: true, finalized: false, finalizedhash: false, + blocktime: true, blockpropagation: true, blocklasttime: false, uptime: false, + version: false, + target_os: false, + target_arch: false, + cpu: false, + cpu_hashrate_score: true, + cpu_vendor: true, + core_count: false, + mem: true, + memory: false, + linux_distro: false, + linux_kernel: false, + memory_memcpy_score: true, + disk_sequential_write_score: true, + disk_random_write_score: true, + is_virtual_machine: false, }, (settings) => { const selectedColumns = this.selectedColumns(settings); diff --git a/frontend/src/Connection.ts b/frontend/src/Connection.ts index 8fcaf953b..327756a16 100644 --- a/frontend/src/Connection.ts +++ b/frontend/src/Connection.ts @@ -269,7 +269,6 @@ export class Connection { case ACTIONS.NodeStats: { const [id, nodeStats] = message.payload; - nodes.mutAndMaybeSort( id, (node) => node.updateStats(nodeStats), diff --git a/frontend/src/common/types.ts b/frontend/src/common/types.ts index 0c64e253a..211480a85 100644 --- a/frontend/src/common/types.ts +++ b/frontend/src/common/types.ts @@ -25,6 +25,15 @@ export type NodeId = Id<'Node'>; export type NodeName = Opaque; export type NodeImplementation = Opaque; export type NodeVersion = Opaque; +export type OperatingSystem = Opaque; +export type CpuArchitecture = Opaque; +export type Cpu = string; +export type CpuCores = number; +export type TargetEnv = string; +export type Memory = number; +export type VirtualMachine = boolean; +export type LinuxKernel = string; +export type LinuxDistro = string; export type BlockNumber = Opaque; export type BlockHash = Opaque; export type Address = Opaque; @@ -43,6 +52,15 @@ export type Bytes = Opaque; export type BytesPerSecond = Opaque; export type NetworkId = Opaque; +export type NodeSysInfo = { + cpu: string; + memory: number; + core_count: number; + linux_kernel: string; + linux_distro: string; + is_virtual_machine: boolean; +}; + export type BlockDetails = [ BlockNumber, BlockHash, @@ -56,8 +74,13 @@ export type NodeDetails = [ NodeVersion, Maybe
, Maybe, - Maybe + OperatingSystem, + CpuArchitecture, + TargetEnv, + undefined, + NodeSysInfo ]; + export type NodeStats = [PeerCount, TransactionCount]; export type NodeIO = [Array]; export type NodeHardware = [ diff --git a/frontend/src/components/List/Column/Column.tsx b/frontend/src/components/List/Column/Column.tsx index da0ad2e28..f1aab9df9 100644 --- a/frontend/src/components/List/Column/Column.tsx +++ b/frontend/src/components/List/Column/Column.tsx @@ -38,6 +38,15 @@ import { BlockPropagationColumn, LastBlockColumn, UptimeColumn, + CpuArchitectureColumn, //extra columns added + CpuColumn, + CpuCoresColumn, + LinuxKernelColumn, + IsVirtualMachineColumn, + MemoryColumn, + OperatingSystemColumn, + VersionColumn, + LinuxDistroColumn, } from './'; export type Column = @@ -58,7 +67,16 @@ export type Column = | typeof BlockTimeColumn | typeof BlockPropagationColumn | typeof LastBlockColumn - | typeof UptimeColumn; + | typeof UptimeColumn + | typeof CpuArchitectureColumn + | typeof CpuColumn + | typeof CpuCoresColumn + | typeof LinuxDistroColumn + | typeof LinuxKernelColumn + | typeof IsVirtualMachineColumn + | typeof MemoryColumn + | typeof OperatingSystemColumn + | typeof VersionColumn; export interface ColumnProps { node: Node; diff --git a/frontend/src/components/List/Column/CpuArchitectureColumn.tsx b/frontend/src/components/List/Column/CpuArchitectureColumn.tsx new file mode 100644 index 000000000..fe77c5c12 --- /dev/null +++ b/frontend/src/components/List/Column/CpuArchitectureColumn.tsx @@ -0,0 +1,43 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying which CPU Architecture the node is running on +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class CpuArchitectureColumn extends React.Component { + public static readonly label = 'CPU Architecture'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'target_arch'; + public static readonly sortBy = ({ target_arch }: Node) => target_arch || ''; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.hash; + } + + render() { + const { target_arch } = this.props.node; + + this.data = target_arch; + + return {target_arch || '-'}; + } +} diff --git a/frontend/src/components/List/Column/CpuColumn.tsx b/frontend/src/components/List/Column/CpuColumn.tsx new file mode 100644 index 000000000..12376dfb2 --- /dev/null +++ b/frontend/src/components/List/Column/CpuColumn.tsx @@ -0,0 +1,44 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying which CPU type the node is running on + +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class CpuColumn extends React.Component { + public static readonly label = 'CPU Column'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'cpu'; + public static readonly sortBy = ({ cpu }: Node) => cpu || 0; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.cpu; + } + + render() { + const { cpu } = this.props.node; + + this.data = cpu; + + return {cpu || '-'}; + } +} diff --git a/frontend/src/components/List/Column/CpuCoresColumn.tsx b/frontend/src/components/List/Column/CpuCoresColumn.tsx new file mode 100644 index 000000000..4091c62e2 --- /dev/null +++ b/frontend/src/components/List/Column/CpuCoresColumn.tsx @@ -0,0 +1,41 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class CpuCoresColumn extends React.Component { + public static readonly label = 'CPU Cores'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'core_count'; + public static readonly sortBy = ({ core_count }: Node) => core_count || 0; + + private data: number; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.core_count; + } + + render() { + const { core_count } = this.props.node; + + this.data = core_count; + + return {core_count || '-'}; + } +} diff --git a/frontend/src/components/List/Column/IsVirtualMachineColumn.tsx b/frontend/src/components/List/Column/IsVirtualMachineColumn.tsx new file mode 100644 index 000000000..7f1280c28 --- /dev/null +++ b/frontend/src/components/List/Column/IsVirtualMachineColumn.tsx @@ -0,0 +1,44 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying whether each node runs a VM or not +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class IsVirtualMachineColumn extends React.Component { + public static readonly label = 'Virtual Machine'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'is_virtual_machine'; + public static readonly sortBy = ({ is_virtual_machine }: Node) => + is_virtual_machine || false; + + private data: boolean; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.is_virtual_machine; + } + + render() { + const { is_virtual_machine } = this.props.node; + + this.data = is_virtual_machine; + + return {is_virtual_machine ? 'Yes' : 'No'}; + } +} diff --git a/frontend/src/components/List/Column/LinuxDistroColumn.tsx b/frontend/src/components/List/Column/LinuxDistroColumn.tsx new file mode 100644 index 000000000..bce8da093 --- /dev/null +++ b/frontend/src/components/List/Column/LinuxDistroColumn.tsx @@ -0,0 +1,45 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying type of distro each node is running (Linux Distribution) + +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class LinuxDistroColumn extends React.Component { + public static readonly label = 'Linux Distro'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'linux_distro'; + public static readonly sortBy = ({ linux_distro }: Node) => + linux_distro || ''; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.linux_distro; + } + + render() { + const { linux_distro } = this.props.node; + + this.data = linux_distro; + + return {linux_distro || '-'}; + } +} diff --git a/frontend/src/components/List/Column/LinuxKernelColumn.tsx b/frontend/src/components/List/Column/LinuxKernelColumn.tsx new file mode 100644 index 000000000..bc00fa9f3 --- /dev/null +++ b/frontend/src/components/List/Column/LinuxKernelColumn.tsx @@ -0,0 +1,43 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying which kernel each node is running on +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class LinuxKernelColumn extends React.Component { + public static readonly label = 'Linux Kernel'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'linux_kernel'; + public static readonly sortBy = ({ linux_kernel }: Node) => linux_kernel || 0; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.linux_kernel; + } + + render() { + const { linux_kernel } = this.props.node; + + this.data = linux_kernel; + + return {linux_kernel || '-'}; + } +} diff --git a/frontend/src/components/List/Column/MemoryColumn.tsx b/frontend/src/components/List/Column/MemoryColumn.tsx new file mode 100644 index 000000000..151eba136 --- /dev/null +++ b/frontend/src/components/List/Column/MemoryColumn.tsx @@ -0,0 +1,43 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column specifying type of memory each node has +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class MemoryColumn extends React.Component { + public static readonly label = 'memory'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'memory'; + public static readonly sortBy = ({ memory }: Node) => memory || ''; + + private data: number; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.memory; + } + + render() { + const { memory } = this.props.node; + + this.data = memory; + + return {memory || '-'}; + } +} diff --git a/frontend/src/components/List/Column/OperatingSystemColumn.tsx b/frontend/src/components/List/Column/OperatingSystemColumn.tsx new file mode 100644 index 000000000..d1ba70799 --- /dev/null +++ b/frontend/src/components/List/Column/OperatingSystemColumn.tsx @@ -0,0 +1,44 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying which OS the node is running on + +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class OperatingSystemColumn extends React.Component { + public static readonly label = 'OS'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'target_os'; + public static readonly sortBy = ({ target_os }: Node) => target_os || ''; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.hash; + } + + render() { + const { target_os } = this.props.node; + + this.data = target_os; + + return {target_os || '-'}; + } +} diff --git a/frontend/src/components/List/Column/VersionColumn.tsx b/frontend/src/components/List/Column/VersionColumn.tsx new file mode 100644 index 000000000..602baf144 --- /dev/null +++ b/frontend/src/components/List/Column/VersionColumn.tsx @@ -0,0 +1,44 @@ +// Source code for the Substrate Telemetry Server. +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//Column for specifying which polkadot version node is running on + +import * as React from 'react'; +import { ColumnProps } from './'; +import { Node } from '../../../state'; +import icon from '../../../icons/file-binary.svg'; + +export class VersionColumn extends React.Component { + public static readonly label = 'version'; + public static readonly icon = icon; + public static readonly width = 154; + public static readonly setting = 'version'; + public static readonly sortBy = ({ version }: Node) => version || ''; + + private data: string; + + public shouldComponentUpdate(nextProps: ColumnProps) { + return this.data !== nextProps.node.version; + } + + render() { + const { version } = this.props.node; + + this.data = version; + + return {version || '-'}; + } +} diff --git a/frontend/src/components/List/Column/index.ts b/frontend/src/components/List/Column/index.ts index b65ac2766..e8f2c61f3 100644 --- a/frontend/src/components/List/Column/index.ts +++ b/frontend/src/components/List/Column/index.ts @@ -33,3 +33,12 @@ export * from './BlockTimeColumn'; export * from './BlockPropagationColumn'; export * from './LastBlockColumn'; export * from './UptimeColumn'; +export * from './CpuArchitectureColumn'; //extra columns added +export * from './CpuCoresColumn'; +export * from './LinuxDistroColumn'; +export * from './IsVirtualMachineColumn'; +export * from './MemoryColumn'; +export * from './CpuColumn'; +export * from './OperatingSystemColumn'; +export * from './VersionColumn'; +export * from './LinuxKernelColumn'; diff --git a/frontend/src/components/List/Row.tsx b/frontend/src/components/List/Row.tsx index 36a86cab1..684a2b64d 100644 --- a/frontend/src/components/List/Row.tsx +++ b/frontend/src/components/List/Row.tsx @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// Each Row in the List Page import * as React from 'react'; import { Types } from '../../common'; import { Node } from '../../state'; @@ -38,6 +39,15 @@ import { BlockPropagationColumn, LastBlockColumn, UptimeColumn, + CpuArchitectureColumn, + CpuColumn, + CpuCoresColumn, + MemoryColumn, + OperatingSystemColumn, + VersionColumn, + IsVirtualMachineColumn, + LinuxDistroColumn, + LinuxKernelColumn, } from './'; import './Row.css'; @@ -72,8 +82,16 @@ export class Row extends React.Component { BlockPropagationColumn, LastBlockColumn, UptimeColumn, + VersionColumn, + OperatingSystemColumn, + CpuArchitectureColumn, + CpuColumn, + CpuCoresColumn, + MemoryColumn, + LinuxDistroColumn, + LinuxKernelColumn, + IsVirtualMachineColumn, ]; - private renderedChangeRef = 0; public shouldComponentUpdate(nextProps: RowProps): boolean { diff --git a/frontend/src/state.ts b/frontend/src/state.ts index 023e5c527..840cec11c 100644 --- a/frontend/src/state.ts +++ b/frontend/src/state.ts @@ -26,8 +26,8 @@ export const PINNED_CHAINS = { }; export function comparePinnedChains(a: string, b: string) { - const aWeight = PINNED_CHAINS[a] || 1024; - const bWeight = PINNED_CHAINS[b] || 1024; + const aWeight: number = (PINNED_CHAINS as any)[a] || 1024; + const bWeight: number = (PINNED_CHAINS as any)[b] || 1024; return aWeight - bWeight; } @@ -62,6 +62,17 @@ export class Node { public readonly validator: Maybe; public readonly networkId: Maybe; public readonly startupTime: Maybe; + public readonly target_os: Types.OperatingSystem; + public readonly target_arch: Types.CpuArchitecture; + public readonly target_env: Types.TargetEnv; + public readonly sysInfo: Types.NodeSysInfo; + + public readonly cpu: Types.Cpu; + public readonly memory: Types.Memory; + public readonly core_count: Types.CpuCores; + public readonly linux_kernel: Types.LinuxKernel; + public readonly linux_distro: Types.LinuxDistro; + public readonly is_virtual_machine: Types.VirtualMachine; public readonly sortableName: string; public readonly sortableVersion: number; @@ -102,7 +113,18 @@ export class Node { location: Maybe, startupTime: Maybe ) { - const [name, implementation, version, validator, networkId] = nodeDetails; + const [ + name, + implementation, + version, + validator, + networkId, + target_os, + target_arch, + target_env, + customNullField, + sysInfo, + ] = nodeDetails; //step 4 this.pinned = pinned; @@ -113,6 +135,30 @@ export class Node { this.validator = validator; this.networkId = networkId; this.startupTime = startupTime; + this.target_os = target_os; + this.target_arch = target_arch; + this.target_env = target_env; + this.sysInfo = { + cpu: sysInfo?.cpu ?? '', // Default value or some global constant + memory: sysInfo?.memory ?? 0, + core_count: sysInfo?.core_count ?? 0, + linux_kernel: sysInfo?.linux_kernel ?? '', + linux_distro: sysInfo?.linux_distro ?? '', + is_virtual_machine: sysInfo?.is_virtual_machine ?? false, + }; + + this.cpu = sysInfo && sysInfo.cpu ? sysInfo.cpu : ''; + this.memory = sysInfo && sysInfo.memory ? Number(sysInfo.memory) : 0; + this.core_count = + sysInfo && sysInfo.core_count ? Number(sysInfo.core_count) : 0; + this.linux_kernel = + sysInfo && sysInfo.linux_kernel ? sysInfo.linux_kernel : ''; + this.linux_distro = + sysInfo && sysInfo.linux_distro ? sysInfo.linux_distro : ''; + this.is_virtual_machine = + sysInfo && sysInfo.is_virtual_machine + ? Boolean(sysInfo.is_virtual_machine) + : false; const [major = 0, minor = 0, patch = 0] = (version || '0.0.0') .split('.') @@ -255,6 +301,20 @@ export interface StateSettings { blockpropagation: boolean; blocklasttime: boolean; uptime: boolean; + version: boolean; + target_os: boolean; + target_arch: boolean; + cpu: boolean; + core_count: boolean; + memory: boolean; + is_virtual_machine: boolean; + linux_distro: boolean; + linux_kernel: boolean; + cpu_hashrate_score: boolean; + memory_memcpy_score: boolean; + disk_sequential_write_score: boolean; + disk_random_write_score: boolean; + cpu_vendor: boolean; } export interface State { diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index a8cfd0782..057f86f50 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -4,11 +4,7 @@ "outDir": "./build/", "module": "es2020", "target": "es2015", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "sourceMap": true, "allowJs": false, "jsx": "react", diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 35d524854..7860c4458 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -16,19 +16,19 @@ module.exports = { // allow 'import "foo.css"' and '@import "foo.css" in css files test: /\.css$/i, use: ['style-loader', 'css-loader'], - generator: { filename: 'styles/[name].[contenthash][ext]' } + generator: { filename: 'styles/[name].[contenthash][ext]' }, }, { // allow 'import Icon from "./icon.png"' test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset/resource', - generator: { filename: 'images/[name].[contenthash][ext]' } + generator: { filename: 'images/[name].[contenthash][ext]' }, }, { // allow CSS @url('./my-font.woff2')" style font loading test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', - generator: { filename: 'fonts/[name].[contenthash][ext]' } + generator: { filename: 'fonts/[name].[contenthash][ext]' }, }, ], }, @@ -36,8 +36,8 @@ module.exports = { // Use our index.html as a starting point (to add script links etc to) // and make sure to use/copy over the favicon too. new HtmlWebpackPlugin({ - favicon: "./assets/favicon.svg", - template: "./assets/index.html" + favicon: './assets/favicon.svg', + template: './assets/index.html', }), ], resolve: { @@ -46,6 +46,6 @@ module.exports = { output: { filename: 'main.[contenthash].js', path: path.resolve(__dirname, 'build'), - clean: true + clean: true, }, -}; \ No newline at end of file +};