fn register_components(&mut self, command: &Self::Cmd) -> Result<(), FrameworkError> {
        use crate::components::{
            metrics::MetricsEndpoint, tokio::TokioComponent, tracing::TracingEndpoint,
        };

        let mut components = self.framework_components(command)?;

        // Load config *after* framework components so that we can
        // report an error to the terminal if it occurs.
        let config = command
            .config_path()
            .map(|path| self.load_config(&path))
            .transpose()?
            .unwrap_or_default();

        let config = command.process_config(config)?;

        let theme = if Self::outputs_are_ttys() && config.tracing.use_color {
            color_eyre::config::Theme::dark()
        } else {
            color_eyre::config::Theme::new()
        };

        // collect the common metadata for the issue URL and panic report
        let network = config.network.network.to_string();
        let panic_metadata = vec![
            ("version", env!("CARGO_PKG_VERSION").to_string()),
            ("git commit", Self::git_commit().to_string()),
            ("Zcash network", network),
        ];

        let mut builder = color_eyre::config::HookBuilder::default();
        let mut metadata_section = "Metadata:".to_string();
        for (k, v) in panic_metadata {
            builder = builder.add_issue_metadata(k, v.clone());
            metadata_section.push_str(&format!("\n{}: {}", k, v));
        }

        builder = builder
            .theme(theme)
            .panic_section(metadata_section)
            .issue_url(concat!(env!("CARGO_PKG_REPOSITORY"), "/issues/new"))
            .issue_filter(|kind| match kind {
                color_eyre::ErrorKind::NonRecoverable(error) => {
                    let error_str = match error.downcast_ref::<String>() {
                        Some(as_string) => as_string,
                        None => return true,
                    };
                    // listener port conflicts
                    if PORT_IN_USE_ERROR.is_match(error_str) {
                        return false;
                    }
                    // RocksDB lock file conflicts
                    if LOCK_FILE_ERROR.is_match(error_str) {
                        return false;
                    }
                    true
                }
                color_eyre::ErrorKind::Recoverable(error) => {
                    // type checks should be faster than string conversions
                    if error.is::<tower::timeout::error::Elapsed>()
                        || error.is::<tokio::time::error::Elapsed>()
                    {
                        return false;
                    }

                    let error_str = error.to_string();
                    !error_str.contains("timed out") && !error_str.contains("duplicate hash")
                }
            });

        // This MUST happen after `Terminal::new` to ensure our preferred panic
        // handler is the last one installed
        let (panic_hook, eyre_hook) = builder.into_hooks();
        eyre_hook.install().unwrap();

        // The Sentry default config pulls in the DSN from the `SENTRY_DSN`
        // environment variable.
        #[cfg(feature = "enable-sentry")]
        let guard = sentry::init(
            sentry::ClientOptions {
                debug: true,
                release: Some(Self::git_commit().into()),
                ..Default::default()
            }
            .add_integration(sentry_tracing::TracingIntegration::default()),
        );

        std::panic::set_hook(Box::new(move |panic_info| {
            let panic_report = panic_hook.panic_report(panic_info);
            eprintln!("{}", panic_report);

            #[cfg(feature = "enable-sentry")]
            {
                let event = crate::sentry::panic_event_from(panic_report);
                sentry::capture_event(event);

                if !guard.close(None) {
                    warn!("unable to flush sentry events during panic");
                }
            }
        }));

        self.config = Some(config);

        let cfg_ref = self
            .config
            .as_ref()
            .expect("config is loaded before register_components");

        let default_filter = if command.verbose { "debug" } else { "info" };
        let is_server = command
            .command
            .as_ref()
            .map(ZebradCmd::is_server)
            .unwrap_or(false);

        // Ignore the tracing filter for short-lived commands
        if is_server {
            // Override the default tracing filter based on the command-line verbosity.
            let mut tracing_config = cfg_ref.tracing.clone();
            tracing_config.filter = tracing_config
                .filter
                .or_else(|| Some(default_filter.to_owned()));

            components.push(Box::new(Tracing::new(tracing_config)?));
        } else {
            // Don't apply the configured filter for short-lived commands.
            let mut tracing_config = cfg_ref.tracing.clone();
            tracing_config.filter = Some(default_filter.to_owned());
            tracing_config.flamegraph = None;
            components.push(Box::new(Tracing::new(tracing_config)?));
        }

        // Activate the global span, so it's visible when we load the other
        // components. Space is at a premium here, so we use an empty message,
        // short commit hash, and the unique part of the network name.
        let global_span = error_span!(
            "",
            zebrad = ZebradApp::git_commit(),
            net = &self.config.clone().unwrap().network.network.to_string()[..4],
        );
        let global_guard = global_span.enter();
        // leak the global span, to make sure it stays active
        std::mem::forget(global_guard);

        // Launch network and async endpoints only for long-running commands.
        if is_server {
            components.push(Box::new(TokioComponent::new()?));
            components.push(Box::new(TracingEndpoint::new(cfg_ref)?));
            components.push(Box::new(MetricsEndpoint::new(cfg_ref)?));
        }

        self.state.components.register(components)
    }
/// Register all components used by this application.
///
/// If you would like to add additional components to your application
/// beyond the default ones provided by the framework, this is the place
/// to do so.
Register all components used by this application.
If you would like to add additional components to your application
beyond the default ones provided by the framework, this is the place
to do so.
Register all components used by this application . If you would like to add additional components to your application beyond the default ones provided by the framework this is the place to do so .
fn register_components(&mut self, command: &Self::Cmd) -> Result<(), FrameworkError> {
        use crate::components::{
            metrics::MetricsEndpoint, tokio::TokioComponent, tracing::TracingEndpoint,
        };
        let mut components = self.framework_components(command)?;
        // Load config *after* framework components so that we can
        // report an error to the terminal if it occurs.
        let config = command
            .config_path()
            .map(|path| self.load_config(&path))
            .transpose()?
            .unwrap_or_default();
        let config = command.process_config(config)?;
        let theme = if Self::outputs_are_ttys() && config.tracing.use_color {
            color_eyre::config::Theme::dark()
        } else {
            color_eyre::config::Theme::new()
        };
        // collect the common metadata for the issue URL and panic report
        let network = config.network.network.to_string();
        let panic_metadata = vec![
            ("version", env!("CARGO_PKG_VERSION").to_string()),
            ("git commit", Self::git_commit().to_string()),
            ("Zcash network", network),
        ];
        let mut builder = color_eyre::config::HookBuilder::default();
        let mut metadata_section = "Metadata:".to_string();
        for (k, v) in panic_metadata {
            builder = builder.add_issue_metadata(k, v.clone());
            metadata_section.push_str(&format!("\n{}: {}", k, v));
        }
        builder = builder
            .theme(theme)
            .panic_section(metadata_section)
            .issue_url(concat!(env!("CARGO_PKG_REPOSITORY"), "/issues/new"))
            .issue_filter(|kind| match kind {
                color_eyre::ErrorKind::NonRecoverable(error) => {
                    let error_str = match error.downcast_ref::<String>() {
                        Some(as_string) => as_string,
                        None => return true,
                    };
                    // listener port conflicts
                    if PORT_IN_USE_ERROR.is_match(error_str) {
                        return false;
                    }
                    // RocksDB lock file conflicts
                    if LOCK_FILE_ERROR.is_match(error_str) {
                        return false;
                    }
                    true
                }
                color_eyre::ErrorKind::Recoverable(error) => {
                    // type checks should be faster than string conversions
                    if error.is::<tower::timeout::error::Elapsed>()
                        || error.is::<tokio::time::error::Elapsed>()
                    {
                        return false;
                    }
                    let error_str = error.to_string();
                    !error_str.contains("timed out") && !error_str.contains("duplicate hash")
                }
            });
        // This MUST happen after `Terminal::new` to ensure our preferred panic
        // handler is the last one installed
        let (panic_hook, eyre_hook) = builder.into_hooks();
        eyre_hook.install().unwrap();
        // The Sentry default config pulls in the DSN from the `SENTRY_DSN`
        // environment variable.
        #[cfg(feature = "enable-sentry")]
        let guard = sentry::init(
            sentry::ClientOptions {
                debug: true,
                release: Some(Self::git_commit().into()),
                ..Default::default()
            }
            .add_integration(sentry_tracing::TracingIntegration::default()),
        );
        std::panic::set_hook(Box::new(move |panic_info| {
            let panic_report = panic_hook.panic_report(panic_info);
            eprintln!("{}", panic_report);
            #[cfg(feature = "enable-sentry")]
            {
                let event = crate::sentry::panic_event_from(panic_report);
                sentry::capture_event(event);
                if !guard.close(None) {
                    warn!("unable to flush sentry events during panic");
                }
            }
        }));
        self.config = Some(config);
        let cfg_ref = self
            .config
            .as_ref()
            .expect("config is loaded before register_components");
        let default_filter = if command.verbose { "debug" } else { "info" };
        let is_server = command
            .command
            .as_ref()
            .map(ZebradCmd::is_server)
            .unwrap_or(false);
        // Ignore the tracing filter for short-lived commands
        if is_server {
            // Override the default tracing filter based on the command-line verbosity.
            let mut tracing_config = cfg_ref.tracing.clone();
            tracing_config.filter = tracing_config
                .filter
                .or_else(|| Some(default_filter.to_owned()));
            components.push(Box::new(Tracing::new(tracing_config)?));
        } else {
            // Don't apply the configured filter for short-lived commands.
            let mut tracing_config = cfg_ref.tracing.clone();
            tracing_config.filter = Some(default_filter.to_owned());
            tracing_config.flamegraph = None;
            components.push(Box::new(Tracing::new(tracing_config)?));
        }
        // Activate the global span, so it's visible when we load the other
        // components. Space is at a premium here, so we use an empty message,
        // short commit hash, and the unique part of the network name.
        let global_span = error_span!(
            "",
            zebrad = ZebradApp::git_commit(),
            net = &self.config.clone().unwrap().network.network.to_string()[..4],
        );
        let global_guard = global_span.enter();
        // leak the global span, to make sure it stays active
        std::mem::forget(global_guard);
        // Launch network and async endpoints only for long-running commands.
        if is_server {
            components.push(Box::new(TokioComponent::new()?));
            components.push(Box::new(TracingEndpoint::new(cfg_ref)?));
            components.push(Box::new(MetricsEndpoint::new(cfg_ref)?));
        }
        self.state.components.register(components)
    }
fn register_components ( & mut self , command : & Self :: Cmd ) -> Result < ( ) , FrameworkError > { use crate :: components :: { metrics :: MetricsEndpoint , tokio :: TokioComponent , tracing :: TracingEndpoint , } ; let mut components = self . framework_components ( command ) ? ; // Load config *after* framework components so that we can // report an error to the terminal if it occurs. let config = command . config_path ( ) . map ( | path | self . load_config ( & path ) ) . transpose ( ) ? . unwrap_or_default ( ) ; let config = command . process_config ( config ) ? ; let theme = if Self :: outputs_are_ttys ( ) && config . tracing . use_color { color_eyre :: config :: Theme :: dark ( ) } else { color_eyre :: config :: Theme :: new ( ) } ; // collect the common metadata for the issue URL and panic report let network = config . network . network . to_string ( ) ; let panic_metadata = vec ! [ ( " " env ( " " ) to_string ( ) ) ( " " Self git_commit ( ) to_string ( ) ) ( " " network ) ] ; let mut builder = color_eyre :: config :: HookBuilder :: default ( ) ; let mut metadata_section = " " . to_string ( ) ; for ( k , v ) in panic_metadata { builder = builder . add_issue_metadata ( k , v . clone ( ) ) ; metadata_section . push_str ( & format ! ( " \n " k v ) ) ; } builder = builder . theme ( theme ) . panic_section ( metadata_section ) . issue_url ( concat ! ( env ( " " ) " " ) ) . issue_filter ( | kind | match kind { color_eyre :: ErrorKind :: NonRecoverable ( error ) => { let error_str = match error . downcast_ref :: < String > ( ) { Some ( as_string ) => as_string , None => return true , } ; // listener port conflicts if PORT_IN_USE_ERROR . is_match ( error_str ) { return false ; } // RocksDB lock file conflicts if LOCK_FILE_ERROR . is_match ( error_str ) { return false ; } true } color_eyre :: ErrorKind :: Recoverable ( error ) => { // type checks should be faster than string conversions if error . is :: < tower :: timeout :: error :: Elapsed > ( ) || error . is :: < tokio :: time :: error :: Elapsed > ( ) { return false ; } let error_str = error . to_string ( ) ; ! error_str . contains ( " " ) && ! error_str . contains ( " " ) } } ) ; // This MUST happen after `Terminal::new` to ensure our preferred panic // handler is the last one installed let ( panic_hook , eyre_hook ) = builder . into_hooks ( ) ; eyre_hook . install ( ) . unwrap ( ) ; // The Sentry default config pulls in the DSN from the `SENTRY_DSN` // environment variable. # [ cfg ( feature " " ) ] let guard = sentry :: init ( sentry :: ClientOptions { debug : true , release : Some ( Self :: git_commit ( ) . into ( ) ) , .. Default :: default ( ) } . add_integration ( sentry_tracing :: TracingIntegration :: default ( ) ) , ) ; std :: panic :: set_hook ( Box :: new ( move | panic_info | { let panic_report = panic_hook . panic_report ( panic_info ) ; eprintln ! ( " " panic_report ) ; # [ cfg ( feature " " ) ] { let event = crate :: sentry :: panic_event_from ( panic_report ) ; sentry :: capture_event ( event ) ; if ! guard . close ( None ) { warn ! ( " " ) ; } } } ) ) ; self . config = Some ( config ) ; let cfg_ref = self . config . as_ref ( ) . expect ( " " ) ; let default_filter = if command . verbose { " " } else { " " } ; let is_server = command . command . as_ref ( ) . map ( ZebradCmd :: is_server ) . unwrap_or ( false ) ; // Ignore the tracing filter for short-lived commands if is_server { // Override the default tracing filter based on the command-line verbosity. let mut tracing_config = cfg_ref . tracing . clone ( ) ; tracing_config . filter = tracing_config . filter . or_else ( | | Some ( default_filter . to_owned ( ) ) ) ; components . push ( Box :: new ( Tracing :: new ( tracing_config ) ? ) ) ; } else { // Don't apply the configured filter for short-lived commands. let mut tracing_config = cfg_ref . tracing . clone ( ) ; tracing_config . filter = Some ( default_filter . to_owned ( ) ) ; tracing_config . flamegraph = None ; components . push ( Box :: new ( Tracing :: new ( tracing_config ) ? ) ) ; } // Activate the global span, so it's visible when we load the other // components. Space is at a premium here, so we use an empty message, // short commit hash, and the unique part of the network name. let global_span = error_span ! ( " " zebrad ZebradApp git_commit ( ) net self config clone ( ) unwrap ( ) network network to_string ( ) [ 4 ] ) ; let global_guard = global_span . enter ( ) ; // leak the global span, to make sure it stays active std :: mem :: forget ( global_guard ) ; // Launch network and async endpoints only for long-running commands. if is_server { components . push ( Box :: new ( TokioComponent :: new ( ) ? ) ) ; components . push ( Box :: new ( TracingEndpoint :: new ( cfg_ref ) ? ) ) ; components . push ( Box :: new ( MetricsEndpoint :: new ( cfg_ref ) ? ) ) ; } self . state . components . register ( components ) }
Register all components used by this application.
Register all components used by this application .
&mut self
command
&Self::Cmd