diff --git a/pow/src/cuckoo.rs b/pow/src/cuckoo.rs index 1d340d3c5b..f8c26a6ffc 100644 --- a/pow/src/cuckoo.rs +++ b/pow/src/cuckoo.rs @@ -5,6 +5,7 @@ use hash::blake2b_256; use serde::{de, Deserialize as SerdeDeserialize}; use serde_derive::Deserialize; use std::collections::HashMap; +use std::fmt; // Cuckatoo proofs take the form of a length 42 off-by-1-cycle in a bipartite graph with // 2^N+2^N nodes and 2^N edges, with N ranging from 10 up to 64. @@ -19,6 +20,12 @@ pub struct CuckooParams { cycle_length: u32, } +impl fmt::Display for CuckooParams { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.edge_bits, self.cycle_length) + } +} + fn validate_cycle_length<'de, D>(d: D) -> Result where D: de::Deserializer<'de>, diff --git a/pow/src/lib.rs b/pow/src/lib.rs index 136bf72b72..0992e931ad 100644 --- a/pow/src/lib.rs +++ b/pow/src/lib.rs @@ -4,6 +4,7 @@ use ckb_core::header::{BlockNumber, Header, RawHeader, Seal}; use hash::blake2b_256; use numext_fixed_hash::H256; use serde_derive::Deserialize; +use std::fmt; use std::sync::Arc; mod cuckoo; @@ -19,6 +20,15 @@ pub enum Pow { Cuckoo(CuckooParams), } +impl fmt::Display for Pow { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Pow::Dummy => write!(f, "Dummy"), + Pow::Cuckoo(params) => write!(f, "Cuckoo{}", params), + } + } +} + impl Pow { pub fn engine(&self) -> Arc { match *self { diff --git a/src/setup/mod.rs b/src/setup/mod.rs index 088936ea0d..5afc9a0c60 100644 --- a/src/setup/mod.rs +++ b/src/setup/mod.rs @@ -12,6 +12,7 @@ use ckb_chain_spec::{consensus::Consensus, ChainSpec}; use ckb_instrument::Format; use ckb_resource::ResourceLocator; use clap::{value_t, ArgMatches}; +use log::info; use logger::LoggerInitGuard; use std::path::PathBuf; @@ -19,6 +20,7 @@ pub struct Setup { subcommand_name: String, resource_locator: ResourceLocator, config: AppConfig, + is_sentry_enabled: bool, } pub struct SetupGuard { @@ -45,18 +47,36 @@ impl Setup { return Err(ExitCode::Config); } + let is_sentry_enabled = is_daemon(&subcommand_name) && config.sentry().is_enabled(); + Ok(Setup { subcommand_name: subcommand_name.to_string(), resource_locator, config, + is_sentry_enabled, }) } pub fn setup_app(&self) -> Result { let logger_guard = logger::init(self.config.logger().clone())?; - let sentry_guard = if is_daemon(&self.subcommand_name) { - Some(self.config.sentry().init()) + + let sentry_guard = if self.is_sentry_enabled { + let sentry_config = self.config.sentry(); + + info!(target: "sentry", "**Notice**: \ + The ckb process will send stack trace to sentry on Rust panics. \ + This is enabled by default before mainnet, which can be opted out by setting \ + the option `dsn` to empty in the config file. The DSN is now {}", sentry_config.dsn); + + let guard = sentry_config.init(); + + sentry::configure_scope(|scope| { + scope.set_tag("subcommand", &self.subcommand_name); + }); + + Some(guard) } else { + info!(target: "sentry", "sentry is disabled"); None }; @@ -141,11 +161,32 @@ impl Setup { } fn chain_spec(&self) -> Result { - self.config.chain_spec(&self.resource_locator) + let result = self.config.chain_spec(&self.resource_locator); + + if let Ok(spec) = &result { + if self.is_sentry_enabled { + sentry::configure_scope(|scope| { + scope.set_tag("spec.name", &spec.name); + scope.set_tag("spec.pow", &spec.pow); + }); + } + } + + result } fn consensus(&self) -> Result { - consensus_from_spec(&self.chain_spec()?) + let result = consensus_from_spec(&self.chain_spec()?); + + if let Ok(consensus) = &result { + if self.is_sentry_enabled { + sentry::configure_scope(|scope| { + scope.set_tag("genesis", consensus.genesis_block.header().hash()); + }); + } + } + + result } } diff --git a/src/setup/sentry_config.rs b/src/setup/sentry_config.rs index 4a59856670..7519696990 100644 --- a/src/setup/sentry_config.rs +++ b/src/setup/sentry_config.rs @@ -1,5 +1,4 @@ use build_info::{get_version, Version}; -use log::info; use serde_derive::Deserialize; #[derive(Clone, Debug, PartialEq, Deserialize)] @@ -9,25 +8,25 @@ pub struct SentryConfig { impl SentryConfig { pub fn init(&self) -> sentry::internals::ClientInitGuard { - let guard = sentry::init(self); + let version = get_version!(); + let guard = sentry::init(self.build_sentry_client_options(&version)); if guard.is_enabled() { + sentry::configure_scope(|scope| { + scope.set_tag("release.pre", version.is_pre()); + scope.set_tag("release.dirty", version.is_dirty()); + }); + sentry::integrations::panic::register_panic_handler(); - info!(target: "sentry", "**Notice**: \ - The ckb process will send stack trace to sentry on Rust panics. \ - This is enabled by default before mainnet, which can be opted out by setting \ - the option `dsn` to empty in the config file. The DSN is now {}", self.dsn); - } else { - info!(target: "sentry", "sentry is disabled"); } guard } -} -impl<'a> Into for &'a SentryConfig { - fn into(self) -> sentry::ClientOptions { - let version = get_version!(); + pub fn is_enabled(&self) -> bool { + self.dsn.parse::().is_ok() + } + fn build_sentry_client_options(&self, version: &Version) -> sentry::ClientOptions { sentry::ClientOptions { dsn: self.dsn.parse().ok(), release: Some(version.long().into()), diff --git a/util/build-info/src/lib.rs b/util/build-info/src/lib.rs index eacce8feca..def611e6b3 100644 --- a/util/build-info/src/lib.rs +++ b/util/build-info/src/lib.rs @@ -59,6 +59,18 @@ impl Version { pub fn long(&self) -> String { format!("{}", self) } + + pub fn is_pre(&self) -> bool { + self.dash_pre != "" + } + + pub fn is_dirty(&self) -> bool { + if let Some(describe) = &self.commit_describe { + describe.ends_with("-dirty") + } else { + false + } + } } impl std::fmt::Display for Version { @@ -93,7 +105,7 @@ pub fn get_channel() -> Option { pub fn get_commit_describe() -> Option { std::process::Command::new("git") - .args(&["describe", "--dirty=dev"]) + .args(&["describe", "--dirty"]) .output() .ok() .and_then(|r| String::from_utf8(r.stdout).ok())