2020
2121extern crate app_dirs;
2222extern crate env_logger;
23+ extern crate atty;
24+ extern crate ansi_term;
25+ extern crate regex;
26+ extern crate time;
2327extern crate futures;
2428extern crate tokio_core;
2529extern crate ctrlc;
@@ -37,6 +41,8 @@ extern crate polkadot_executor;
3741extern crate polkadot_runtime;
3842extern crate polkadot_service as service;
3943
44+ #[ macro_use]
45+ extern crate lazy_static;
4046#[ macro_use]
4147extern crate clap;
4248#[ macro_use]
@@ -183,7 +189,7 @@ fn start_server<T, F>(mut address: SocketAddr, start: F) -> Result<T, io::Error>
183189}
184190
185191fn parse_address ( default : & str , port_param : & str , matches : & clap:: ArgMatches ) -> Result < SocketAddr , String > {
186- let mut address: SocketAddr = default. parse ( ) . unwrap ( ) ;
192+ let mut address: SocketAddr = default. parse ( ) . ok ( ) . ok_or ( format ! ( "Invalid address specified for --{}." , port_param ) ) ? ;
187193 if let Some ( port) = matches. value_of ( port_param) {
188194 let port: u16 = port. parse ( ) . ok ( ) . ok_or ( format ! ( "Invalid port for --{} specified." , port_param) ) ?;
189195 address. set_port ( port) ;
@@ -219,6 +225,8 @@ fn default_base_path() -> PathBuf {
219225}
220226
221227fn init_logger ( pattern : & str ) {
228+ use ansi_term:: Colour ;
229+
222230 let mut builder = env_logger:: LogBuilder :: new ( ) ;
223231 // Disable info logging by default for some modules:
224232 builder. filter ( Some ( "ws" ) , log:: LogLevelFilter :: Warn ) ;
@@ -231,7 +239,37 @@ fn init_logger(pattern: &str) {
231239 }
232240
233241 builder. parse ( pattern) ;
242+ let isatty = atty:: is ( atty:: Stream :: Stderr ) ;
243+ let enable_color = isatty;
244+
245+ let format = move |record : & log:: LogRecord | {
246+ let timestamp = time:: strftime ( "%Y-%m-%d %H:%M:%S" , & time:: now ( ) ) . expect ( "Error formatting log timestamp" ) ;
247+
248+ let mut output = if log:: max_log_level ( ) <= log:: LogLevelFilter :: Info {
249+ format ! ( "{} {}" , Colour :: Black . bold( ) . paint( timestamp) , record. args( ) )
250+ } else {
251+ let name = :: std:: thread:: current ( ) . name ( ) . map_or_else ( Default :: default, |x| format ! ( "{}" , Colour :: Blue . bold( ) . paint( x) ) ) ;
252+ format ! ( "{} {} {} {} {}" , Colour :: Black . bold( ) . paint( timestamp) , name, record. level( ) , record. target( ) , record. args( ) )
253+ } ;
254+
255+ if !enable_color {
256+ output = kill_color ( output. as_ref ( ) ) ;
257+ }
234258
259+ if !isatty && record. level ( ) <= log:: LogLevel :: Info && atty:: is ( atty:: Stream :: Stdout ) {
260+ // duplicate INFO/WARN output to console
261+ println ! ( "{}" , output) ;
262+ }
263+ output
264+ } ;
265+ builder. format ( format) ;
235266
236267 builder. init ( ) . expect ( "Logger initialized only once." ) ;
237268}
269+
270+ fn kill_color ( s : & str ) -> String {
271+ lazy_static ! {
272+ static ref RE : regex:: Regex = regex:: Regex :: new( "\x1b \\ [[^m]+m" ) . expect( "Error initializing color regex" ) ;
273+ }
274+ RE . replace_all ( s, "" ) . to_string ( )
275+ }
0 commit comments