diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 12547a77..36098e9b 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -1806,6 +1806,7 @@ dependencies = [ "futures", "http", "log", + "serde", "serde_json", "soketto", "thiserror", diff --git a/backend/telemetry_core/build.rs b/backend/telemetry_core/build.rs new file mode 100644 index 00000000..e0a5b845 --- /dev/null +++ b/backend/telemetry_core/build.rs @@ -0,0 +1,12 @@ +use std::process::Command; + +fn main() { + // Fetch the git hash if possible, if not. + let git_hash = Command::new("git") + .args(&["rev-parse", "HEAD"]) + .output() + .map(|output| String::from_utf8(output.stdout).unwrap_or_default()) + .unwrap_or_default(); + + println!("cargo:rustc-env=GIT_HASH={}", git_hash); +} diff --git a/backend/telemetry_core/src/aggregator/inner_loop.rs b/backend/telemetry_core/src/aggregator/inner_loop.rs index 52eee8bb..dbc6468f 100644 --- a/backend/telemetry_core/src/aggregator/inner_loop.rs +++ b/backend/telemetry_core/src/aggregator/inner_loop.rs @@ -451,7 +451,10 @@ impl InnerLoop { // Tell the new feed subscription some basic things to get it going: let mut feed_serializer = FeedMessageSerializer::new(); - feed_serializer.push(feed_message::Version(32)); + feed_serializer.push(feed_message::Version(crate::feed_message::FEED_VERSION)); + feed_serializer.push(feed_message::TelemetryInfo { + git_hash: crate::GIT_HASH, + }); for chain in self.node_state.iter_chains() { feed_serializer.push(feed_message::AddedChain( chain.label(), diff --git a/backend/telemetry_core/src/feed_message.rs b/backend/telemetry_core/src/feed_message.rs index 00f94a2e..0f6ca37c 100644 --- a/backend/telemetry_core/src/feed_message.rs +++ b/backend/telemetry_core/src/feed_message.rs @@ -25,6 +25,10 @@ use common::node_types::{ }; use serde_json::to_writer; +/// The version of the feed messages. This should be incremented +/// on the backend and frontend when the feed API changes. +pub const FEED_VERSION: usize = 33; + type FeedNodeId = usize; pub trait FeedMessage { @@ -123,6 +127,7 @@ actions! { 20: StaleNode, 21: NodeIOUpdate<'_>, 22: ChainStatsUpdate<'_>, + 23: TelemetryInfo, } #[derive(Serialize)] @@ -252,3 +257,8 @@ pub struct ChainStats { pub disk_random_write_score: Ranking<(u32, Option)>, pub cpu_vendor: Ranking, } + +#[derive(Serialize)] +pub struct TelemetryInfo { + pub git_hash: &'static str, +} diff --git a/backend/telemetry_core/src/main.rs b/backend/telemetry_core/src/main.rs index 32b6d79c..6ca10e29 100644 --- a/backend/telemetry_core/src/main.rs +++ b/backend/telemetry_core/src/main.rs @@ -41,6 +41,7 @@ use jemallocator::Jemalloc; #[global_allocator] static GLOBAL: Jemalloc = Jemalloc; +const GIT_HASH: &str = env!("GIT_HASH"); const VERSION: &str = env!("CARGO_PKG_VERSION"); const AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); const NAME: &str = "Substrate Telemetry Backend Core"; diff --git a/backend/telemetry_core/tests/e2e_tests.rs b/backend/telemetry_core/tests/e2e_tests.rs index 76e6989b..f6487456 100644 --- a/backend/telemetry_core/tests/e2e_tests.rs +++ b/backend/telemetry_core/tests/e2e_tests.rs @@ -46,6 +46,8 @@ use test_utils::{ workspace::{start_server, start_server_debug, CoreOpts, ServerOpts, ShardOpts}, }; +const GIT_HASH: &str = env!("GIT_HASH"); + fn polkadot_genesis_hash() -> BlockHash { BlockHash::from_str("0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3") .expect("valid polkadot genesis hash") @@ -69,7 +71,12 @@ async fn e2e_feed_sent_version_on_connect() { let feed_messages = feed_rx.recv_feed_messages().await.unwrap(); assert_eq!( feed_messages, - vec![FeedMessage::Version(32)], + vec![ + FeedMessage::Version(33), + FeedMessage::TelemetryInfo { + git_hash: GIT_HASH.to_string() + } + ], "expecting version" ); @@ -127,7 +134,12 @@ async fn e2e_multiple_feeds_sent_version_on_connect() { for feed_messages in responses { assert_eq!( feed_messages.expect("should have messages"), - vec![FeedMessage::Version(32)], + vec![ + FeedMessage::Version(33), + FeedMessage::TelemetryInfo { + git_hash: GIT_HASH.to_string() + } + ], "expecting version" ); } diff --git a/backend/test_utils/Cargo.toml b/backend/test_utils/Cargo.toml index d56131f5..d603b726 100644 --- a/backend/test_utils/Cargo.toml +++ b/backend/test_utils/Cargo.toml @@ -11,6 +11,7 @@ anyhow = "1.0.41" futures = "0.3.15" http = "0.2.4" log = "0.4.14" +serde = "1" serde_json = "1.0.64" soketto = "0.7.1" thiserror = "1.0.25" diff --git a/backend/test_utils/src/feed_message_de.rs b/backend/test_utils/src/feed_message_de.rs index 6161125e..10703e30 100644 --- a/backend/test_utils/src/feed_message_de.rs +++ b/backend/test_utils/src/feed_message_de.rs @@ -122,6 +122,9 @@ pub enum FeedMessage { node_id: usize, // details: NodeIO, // can't losslessly deserialize }, + TelemetryInfo { + git_hash: String, + }, /// A "special" case when we don't know how to decode an action: UnknownValue { action: u8, @@ -367,6 +370,18 @@ impl FeedMessage { let (node_id, _node_io): (_, &RawValue) = serde_json::from_str(raw_val.get())?; FeedMessage::NodeIOUpdate { node_id } } + // Note: 22: ChainStatsUpdate is not here. Add when we want to test it. + // TelemetryInfo + 23 => { + #[derive(serde::Deserialize)] + struct TelemetryInfo { + git_hash: String, + } + let val: TelemetryInfo = serde_json::from_str(raw_val.get())?; + FeedMessage::TelemetryInfo { + git_hash: val.git_hash, + } + } // A catchall for messages we don't know/care about yet: _ => { let value = raw_val.to_string(); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 94b537a6..306a922f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -113,6 +113,7 @@ export default class App extends React.Component { this.appUpdate = bindState(this, { status: 'offline', + gitHash: '', best: 0 as Types.BlockNumber, finalized: 0 as Types.BlockNumber, blockTimestamp: 0 as Types.Timestamp, @@ -145,6 +146,7 @@ export default class App extends React.Component { public render() { const { timeDiff, subscribed, status, tab } = this.appState; const chains = this.chains(); + const gitHash = this.appState.gitHash; const subscribedData = subscribed ? this.appState.chains.get(subscribed) : null; @@ -173,6 +175,7 @@ export default class App extends React.Component {
. color: #000; min-width: 1350px; position: relative; - background: linear-gradient(0deg, rgba(0,0,0,0.2) 0%, rgb(255, 255, 255) 17%), white; + background: linear-gradient( + 0deg, + rgba(0, 0, 0, 0.2) 0%, + rgb(255, 255, 255) 17% + ), + white; } .Header-tabs { diff --git a/frontend/src/components/Chains.tsx b/frontend/src/components/Chains.tsx index e30e8e93..02c78d53 100644 --- a/frontend/src/components/Chains.tsx +++ b/frontend/src/components/Chains.tsx @@ -26,6 +26,7 @@ import listIcon from '../icons/kebab-horizontal.svg'; import './Chains.css'; interface ChainsProps { + gitHash: string; chains: ChainData[]; subscribedHash: Maybe; subscribedData: Maybe; @@ -75,6 +76,10 @@ export class Chains extends React.Component {
) : null; + const githubLink = this.props.gitHash + ? `https://github.com/paritytech/substrate-telemetry/tree/${this.props.gitHash}` + : 'https://github.com/paritytech/substrate-telemetry'; + return (
{subscribedChain} @@ -88,9 +93,9 @@ export class Chains extends React.Component { diff --git a/frontend/src/index.css b/frontend/src/index.css index ea62fa7b..2921acf9 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -21,7 +21,8 @@ along with this program. If not, see . box-sizing: border-box; } -html, body { +html, +body { background-color: #2c2b2b; } diff --git a/frontend/src/state.ts b/frontend/src/state.ts index 840cec11..2ae4981d 100644 --- a/frontend/src/state.ts +++ b/frontend/src/state.ts @@ -318,6 +318,7 @@ export interface StateSettings { } export interface State { + gitHash: string; status: 'online' | 'offline' | 'upgrade-requested'; best: Types.BlockNumber; finalized: Types.BlockNumber;