diff --git a/substrate/bin/node/cli/src/cli.rs b/substrate/bin/node/cli/src/cli.rs
index 6e8afc613336ae3d48faed3a99e3255f0b022995..8cd8cb9f33d8c3d4c3d0abe0e9d960b00cd8d77a 100644
--- a/substrate/bin/node/cli/src/cli.rs
+++ b/substrate/bin/node/cli/src/cli.rs
@@ -21,7 +21,7 @@ use sc_cli::{IntoExit, NoCustom, SharedParams, ImportParams, error};
 use sc_service::{AbstractService, Roles as ServiceRoles, Configuration};
 use log::info;
 use structopt::{StructOpt, clap::App};
-use sc_cli::{display_role, parse_and_prepare, AugmentClap, GetLogFilter, ParseAndPrepare};
+use sc_cli::{display_role, parse_and_prepare, AugmentClap, GetSharedParams, ParseAndPrepare};
 use crate::{service, ChainSpec, load_spec};
 use crate::factory_impl::FactoryState;
 use node_transaction_factory::RuntimeAdapter;
@@ -38,9 +38,11 @@ pub enum CustomSubcommands {
 	Factory(FactoryCmd),
 }
 
-impl GetLogFilter for CustomSubcommands {
-	fn get_log_filter(&self) -> Option<String> {
-		None
+impl GetSharedParams for CustomSubcommands {
+	fn shared_params(&self) -> Option<&SharedParams> {
+		match self {
+			CustomSubcommands::Factory(cmd) => Some(&cmd.shared_params),
+		}
 	}
 }
 
diff --git a/substrate/client/cli/src/lib.rs b/substrate/client/cli/src/lib.rs
index 41456fc8c4aee798ba934f5e7271479d26fb257c..d1b3388432d100c7819777f43b5624cf40b3aa7f 100644
--- a/substrate/client/cli/src/lib.rs
+++ b/substrate/client/cli/src/lib.rs
@@ -57,7 +57,7 @@ use params::{
 	NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd,
 };
 pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy};
-pub use traits::{GetLogFilter, AugmentClap};
+pub use traits::{GetSharedParams, AugmentClap};
 use app_dirs::{AppInfo, AppDataType};
 use log::info;
 use lazy_static::lazy_static;
@@ -195,7 +195,7 @@ pub fn parse_and_prepare<'a, CC, RP, I>(
 	args: I,
 ) -> ParseAndPrepare<'a, CC, RP>
 where
-	CC: StructOpt + Clone + GetLogFilter,
+	CC: StructOpt + Clone + GetSharedParams,
 	RP: StructOpt + Clone + AugmentClap,
 	I: IntoIterator,
 	<I as IntoIterator>::Item: Into<std::ffi::OsString> + Clone,
@@ -216,10 +216,9 @@ where
 		.setting(AppSettings::SubcommandsNegateReqs)
 		.get_matches_from(args);
 	let cli_args = CoreParams::<CC, RP>::from_clap(&matches);
-	init_logger(cli_args.get_log_filter().as_ref().map(|v| v.as_ref()).unwrap_or(""));
 	fdlimit::raise_fd_limit();
 
-	match cli_args {
+	let args = match cli_args {
 		params::CoreParams::Run(params) => ParseAndPrepare::Run(
 			ParseAndPrepareRun { params, impl_name, version }
 		),
@@ -242,7 +241,9 @@ where
 			ParseAndPrepareRevert { params, version }
 		),
 		params::CoreParams::Custom(params) => ParseAndPrepare::CustomCommand(params),
-	}
+	};
+	init_logger(args.shared_params().and_then(|p| p.log.as_ref()).map(|v| v.as_ref()).unwrap_or(""));
+	args
 }
 
 /// Returns a string displaying the node role, special casing the sentry mode
@@ -277,6 +278,22 @@ pub enum ParseAndPrepare<'a, CC, RP> {
 	CustomCommand(CC),
 }
 
+impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> where CC: GetSharedParams {
+	/// Return common set of parameters shared by all commands.
+	pub fn shared_params(&self) -> Option<&SharedParams> {
+		match self {
+			ParseAndPrepare::Run(c) => Some(&c.params.left.shared_params),
+			ParseAndPrepare::BuildSpec(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::ExportBlocks(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::ImportBlocks(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::CheckBlock(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::PurgeChain(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::RevertChain(c) => Some(&c.params.shared_params),
+			ParseAndPrepare::CustomCommand(c) => c.shared_params(),
+		}
+	}
+}
+
 /// Command ready to run the main client.
 pub struct ParseAndPrepareRun<'a, RP> {
 	params: MergeParameters<RunCmd, RP>,
diff --git a/substrate/client/cli/src/params.rs b/substrate/client/cli/src/params.rs
index 6cb425bd74232ff8f2443dc1bbcb11f1f96f41bd..e8d00978a8d79bb8d8f2c43c75ceefce39593bc8 100644
--- a/substrate/client/cli/src/params.rs
+++ b/substrate/client/cli/src/params.rs
@@ -14,24 +14,13 @@
 // You should have received a copy of the GNU General Public License
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
-use crate::traits::{AugmentClap, GetLogFilter};
+use crate::traits::{AugmentClap, GetSharedParams};
 
 use std::{str::FromStr, path::PathBuf};
 use structopt::{StructOpt, clap::{arg_enum, App, AppSettings, SubCommand, Arg}};
 
 pub use crate::execution_strategy::ExecutionStrategy;
 
-/// Auxiliary macro to implement `GetLogFilter` for all types that have the `shared_params` field.
-macro_rules! impl_get_log_filter {
-	( $type:ident ) => {
-		impl $crate::GetLogFilter for $type {
-			fn get_log_filter(&self) -> Option<String> {
-				self.shared_params.get_log_filter()
-			}
-		}
-	}
-}
-
 impl Into<sc_client_api::ExecutionStrategy> for ExecutionStrategy {
 	fn into(self) -> sc_client_api::ExecutionStrategy {
 		match self {
@@ -153,12 +142,6 @@ pub struct ImportParams {
 	pub state_cache_size: usize,
 }
 
-impl GetLogFilter for SharedParams {
-	fn get_log_filter(&self) -> Option<String> {
-		self.log.clone()
-	}
-}
-
 /// Parameters used to create the network configuration.
 #[derive(Debug, StructOpt, Clone)]
 pub struct NetworkConfigurationParams {
@@ -723,7 +706,6 @@ fn parse_cors(s: &str) -> Result<Cors, Box<dyn std::error::Error>> {
 }
 
 impl_augment_clap!(RunCmd);
-impl_get_log_filter!(RunCmd);
 
 /// The `build-spec` command used to build a specification.
 #[derive(Debug, StructOpt, Clone)]
@@ -748,8 +730,6 @@ pub struct BuildSpecCmd {
 	pub node_key_params: NodeKeyParams,
 }
 
-impl_get_log_filter!(BuildSpecCmd);
-
 /// Wrapper type of `String` which holds an arbitary sized unsigned integer formatted as decimal.
 #[derive(Debug, Clone)]
 pub struct BlockNumber(String);
@@ -813,8 +793,6 @@ pub struct ExportBlocksCmd {
 	pub shared_params: SharedParams,
 }
 
-impl_get_log_filter!(ExportBlocksCmd);
-
 /// The `import-blocks` command used to import blocks.
 #[derive(Debug, StructOpt, Clone)]
 pub struct ImportBlocksCmd {
@@ -837,8 +815,6 @@ pub struct ImportBlocksCmd {
 	pub import_params: ImportParams,
 }
 
-impl_get_log_filter!(ImportBlocksCmd);
-
 /// The `check-block` command used to validate blocks.
 #[derive(Debug, StructOpt, Clone)]
 pub struct CheckBlockCmd {
@@ -861,8 +837,6 @@ pub struct CheckBlockCmd {
 	pub import_params: ImportParams,
 }
 
-impl_get_log_filter!(CheckBlockCmd);
-
 /// The `revert` command used revert the chain to a previous state.
 #[derive(Debug, StructOpt, Clone)]
 pub struct RevertCmd {
@@ -875,8 +849,6 @@ pub struct RevertCmd {
 	pub shared_params: SharedParams,
 }
 
-impl_get_log_filter!(RevertCmd);
-
 /// The `purge-chain` command used to remove the whole chain.
 #[derive(Debug, StructOpt, Clone)]
 pub struct PurgeChainCmd {
@@ -889,8 +861,6 @@ pub struct PurgeChainCmd {
 	pub shared_params: SharedParams,
 }
 
-impl_get_log_filter!(PurgeChainCmd);
-
 /// All core commands that are provided by default.
 ///
 /// The core commands are split into multiple subcommands and `Run` is the default subcommand. From
@@ -924,7 +894,7 @@ pub enum CoreParams<CC, RP> {
 }
 
 impl<CC, RP> StructOpt for CoreParams<CC, RP> where
-	CC: StructOpt + GetLogFilter,
+	CC: StructOpt + GetSharedParams,
 	RP: StructOpt + AugmentClap
 {
 	fn clap<'a, 'b>() -> App<'a, 'b> {
@@ -979,21 +949,6 @@ impl<CC, RP> StructOpt for CoreParams<CC, RP> where
 	}
 }
 
-impl<CC, RP> GetLogFilter for CoreParams<CC, RP> where CC: GetLogFilter {
-	fn get_log_filter(&self) -> Option<String> {
-		match self {
-			CoreParams::Run(c) => c.left.get_log_filter(),
-			CoreParams::BuildSpec(c) => c.get_log_filter(),
-			CoreParams::ExportBlocks(c) => c.get_log_filter(),
-			CoreParams::ImportBlocks(c) => c.get_log_filter(),
-			CoreParams::CheckBlock(c) => c.get_log_filter(),
-			CoreParams::PurgeChain(c) => c.get_log_filter(),
-			CoreParams::Revert(c) => c.get_log_filter(),
-			CoreParams::Custom(c) => c.get_log_filter(),
-		}
-	}
-}
-
 /// A special commandline parameter that expands to nothing.
 /// Should be used as custom subcommand/run arguments if no custom values are required.
 #[derive(Clone, Debug, Default)]
@@ -1015,8 +970,8 @@ impl AugmentClap for NoCustom {
 	}
 }
 
-impl GetLogFilter for NoCustom {
-	fn get_log_filter(&self) -> Option<String> {
+impl GetSharedParams for NoCustom {
+	fn shared_params(&self) -> Option<&SharedParams> {
 		None
 	}
 }
diff --git a/substrate/client/cli/src/traits.rs b/substrate/client/cli/src/traits.rs
index 0f8d247e49ab144f0f916c54fd1f5998e3701734..dddba0b25ab2c14d58757b8b441fb00cc4bc157c 100644
--- a/substrate/client/cli/src/traits.rs
+++ b/substrate/client/cli/src/traits.rs
@@ -15,6 +15,7 @@
 // along with Substrate.  If not, see <http://www.gnu.org/licenses/>.
 
 use structopt::{StructOpt, clap::App};
+use crate::params::SharedParams;
 
 /// Something that can augment a clap app with further parameters.
 /// `derive(StructOpt)` is implementing this function by default, so a macro `impl_augment_clap!`
@@ -37,8 +38,8 @@ macro_rules! impl_augment_clap {
 	}
 }
 
-/// Returns the log filter given by the user as commandline argument.
-pub trait GetLogFilter {
-	/// Returns the set log filter.
-	fn get_log_filter(&self) -> Option<String>;
+/// Supports getting common params.
+pub trait GetSharedParams {
+	/// Returns shared params if any.
+	fn shared_params(&self) -> Option<&SharedParams>;
 }
diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs
index 713b873ff94e34eb17152aee4507b7921ee8c068..9b5afe957a1158d29edec4b3e3ffa9e2aca13443 100644
--- a/substrate/client/service/src/builder.rs
+++ b/substrate/client/service/src/builder.rs
@@ -95,7 +95,7 @@ pub struct ServiceBuilder<TBl, TRtApi, TCfg, TGen, TCSExt, TCl, TFchr, TSc, TImp
 }
 
 /// Full client type.
-type TFullClient<TBl, TRtApi, TExecDisp> = Client<
+pub type TFullClient<TBl, TRtApi, TExecDisp> = Client<
 	TFullBackend<TBl>,
 	TFullCallExecutor<TBl, TExecDisp>,
 	TBl,
@@ -103,16 +103,16 @@ type TFullClient<TBl, TRtApi, TExecDisp> = Client<
 >;
 
 /// Full client backend type.
-type TFullBackend<TBl> = sc_client_db::Backend<TBl>;
+pub type TFullBackend<TBl> = sc_client_db::Backend<TBl>;
 
 /// Full client call executor type.
-type TFullCallExecutor<TBl, TExecDisp> = sc_client::LocalCallExecutor<
+pub type TFullCallExecutor<TBl, TExecDisp> = sc_client::LocalCallExecutor<
 	sc_client_db::Backend<TBl>,
 	NativeExecutor<TExecDisp>,
 >;
 
 /// Light client type.
-type TLightClient<TBl, TRtApi, TExecDisp> = Client<
+pub type TLightClient<TBl, TRtApi, TExecDisp> = Client<
 	TLightBackend<TBl>,
 	TLightCallExecutor<TBl, TExecDisp>,
 	TBl,
@@ -120,13 +120,13 @@ type TLightClient<TBl, TRtApi, TExecDisp> = Client<
 >;
 
 /// Light client backend type.
-type TLightBackend<TBl> = sc_client::light::backend::Backend<
+pub type TLightBackend<TBl> = sc_client::light::backend::Backend<
 	sc_client_db::light::LightStorage<TBl>,
 	Blake2Hasher,
 >;
 
 /// Light call executor type.
-type TLightCallExecutor<TBl, TExecDisp> = sc_client::light::call_executor::GenesisCallExecutor<
+pub type TLightCallExecutor<TBl, TExecDisp> = sc_client::light::call_executor::GenesisCallExecutor<
 	sc_client::light::backend::Backend<
 		sc_client_db::light::LightStorage<TBl>,
 		Blake2Hasher
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index 757d3b0bf6465b9ae8516151fe9b62287d9db00c..d9dc9bd004d52adea35edcc629e5f50616ffbe5f 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -53,7 +53,10 @@ use sp_runtime::generic::BlockId;
 use sp_runtime::traits::{NumberFor, Block as BlockT};
 
 pub use self::error::Error;
-pub use self::builder::{ServiceBuilder, ServiceBuilderCommand};
+pub use self::builder::{
+	ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
+	TFullCallExecutor, TLightCallExecutor,
+};
 pub use config::{Configuration, Roles, PruningMode};
 pub use sc_chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension};
 pub use sp_transaction_pool::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, error::IntoPoolError};