Merge pull request #414 from sigp/cli-logging-2
Add CLI Flag for logging to JSON file
This commit is contained in:
commit
e66ef32a9d
@ -14,13 +14,20 @@ fn main() {
|
|||||||
let decorator = slog_term::TermDecorator::new().build();
|
let decorator = slog_term::TermDecorator::new().build();
|
||||||
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
|
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
|
||||||
let drain = slog_async::Async::new(drain).build().fuse();
|
let drain = slog_async::Async::new(drain).build().fuse();
|
||||||
let log = slog::Logger::root(drain, o!());
|
let mut log = slog::Logger::root(drain, o!());
|
||||||
|
|
||||||
// CLI
|
// CLI
|
||||||
let matches = App::new("Lighthouse Accounts Manager")
|
let matches = App::new("Lighthouse Accounts Manager")
|
||||||
.version("0.0.1")
|
.version("0.0.1")
|
||||||
.author("Sigma Prime <contact@sigmaprime.io>")
|
.author("Sigma Prime <contact@sigmaprime.io>")
|
||||||
.about("Eth 2.0 Accounts Manager")
|
.about("Eth 2.0 Accounts Manager")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("logfile")
|
||||||
|
.long("logfile")
|
||||||
|
.value_name("logfile")
|
||||||
|
.help("File path where output will be written.")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("datadir")
|
Arg::with_name("datadir")
|
||||||
.long("datadir")
|
.long("datadir")
|
||||||
@ -91,21 +98,12 @@ fn main() {
|
|||||||
|
|
||||||
let mut client_config = ValidatorClientConfig::default();
|
let mut client_config = ValidatorClientConfig::default();
|
||||||
|
|
||||||
if let Err(e) = client_config.apply_cli_args(&matches) {
|
|
||||||
crit!(log, "Failed to apply CLI args"; "error" => format!("{:?}", e));
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure the `data_dir` in the config matches that supplied to the CLI.
|
// Ensure the `data_dir` in the config matches that supplied to the CLI.
|
||||||
client_config.data_dir = data_dir.clone();
|
client_config.data_dir = data_dir.clone();
|
||||||
|
|
||||||
// Update the client config with any CLI args.
|
if let Err(e) = client_config.apply_cli_args(&matches, &mut log) {
|
||||||
match client_config.apply_cli_args(&matches) {
|
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => format!("{:?}", e));
|
||||||
Ok(()) => (),
|
|
||||||
Err(s) => {
|
|
||||||
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Log configuration
|
// Log configuration
|
||||||
|
@ -21,8 +21,9 @@ serde_derive = "1.0"
|
|||||||
error-chain = "0.12.0"
|
error-chain = "0.12.0"
|
||||||
eth2_ssz = { path = "../../eth2/utils/ssz" }
|
eth2_ssz = { path = "../../eth2/utils/ssz" }
|
||||||
slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] }
|
slog = { version = "^2.2.3" , features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
slog-term = "^2.4.0"
|
|
||||||
slog-async = "^2.3.0"
|
slog-async = "^2.3.0"
|
||||||
|
slog-json = "^2.3"
|
||||||
|
slog-term = "^2.4.0"
|
||||||
tokio = "0.1.15"
|
tokio = "0.1.15"
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
dirs = "1.0.3"
|
dirs = "1.0.3"
|
||||||
|
@ -2,8 +2,10 @@ use clap::ArgMatches;
|
|||||||
use http_server::HttpServerConfig;
|
use http_server::HttpServerConfig;
|
||||||
use network::NetworkConfig;
|
use network::NetworkConfig;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use slog::{info, o, Drain};
|
||||||
|
use std::fs::{self, OpenOptions};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
/// The core configuration of a Lighthouse beacon node.
|
/// The core configuration of a Lighthouse beacon node.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -11,6 +13,7 @@ pub struct Config {
|
|||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
pub db_type: String,
|
pub db_type: String,
|
||||||
db_name: String,
|
db_name: String,
|
||||||
|
pub log_file: PathBuf,
|
||||||
pub network: network::NetworkConfig,
|
pub network: network::NetworkConfig,
|
||||||
pub rpc: rpc::RPCConfig,
|
pub rpc: rpc::RPCConfig,
|
||||||
pub http: HttpServerConfig,
|
pub http: HttpServerConfig,
|
||||||
@ -20,6 +23,7 @@ impl Default for Config {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data_dir: PathBuf::from(".lighthouse"),
|
data_dir: PathBuf::from(".lighthouse"),
|
||||||
|
log_file: PathBuf::from(""),
|
||||||
db_type: "disk".to_string(),
|
db_type: "disk".to_string(),
|
||||||
db_name: "chain_db".to_string(),
|
db_name: "chain_db".to_string(),
|
||||||
// Note: there are no default bootnodes specified.
|
// Note: there are no default bootnodes specified.
|
||||||
@ -45,23 +49,64 @@ impl Config {
|
|||||||
Some(path)
|
Some(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the logger to output in JSON to specified file
|
||||||
|
fn update_logger(&mut self, log: &mut slog::Logger) -> Result<(), &'static str> {
|
||||||
|
let file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&self.log_file);
|
||||||
|
|
||||||
|
if file.is_err() {
|
||||||
|
return Err("Cannot open log file");
|
||||||
|
}
|
||||||
|
let file = file.unwrap();
|
||||||
|
|
||||||
|
if let Some(file) = self.log_file.to_str() {
|
||||||
|
info!(
|
||||||
|
*log,
|
||||||
|
"Log file specified, output will now be written to {} in json.", file
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
*log,
|
||||||
|
"Log file specified output will now be written in json"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drain = Mutex::new(slog_json::Json::default(file)).fuse();
|
||||||
|
let drain = slog_async::Async::new(drain).build().fuse();
|
||||||
|
*log = slog::Logger::root(drain, o!());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply the following arguments to `self`, replacing values if they are specified in `args`.
|
/// Apply the following arguments to `self`, replacing values if they are specified in `args`.
|
||||||
///
|
///
|
||||||
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
||||||
/// invalid.
|
/// invalid.
|
||||||
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), String> {
|
pub fn apply_cli_args(
|
||||||
|
&mut self,
|
||||||
|
args: &ArgMatches,
|
||||||
|
log: &mut slog::Logger,
|
||||||
|
) -> Result<(), String> {
|
||||||
if let Some(dir) = args.value_of("datadir") {
|
if let Some(dir) = args.value_of("datadir") {
|
||||||
self.data_dir = PathBuf::from(dir);
|
self.data_dir = PathBuf::from(dir);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(dir) = args.value_of("db") {
|
if let Some(dir) = args.value_of("db") {
|
||||||
self.db_type = dir.to_string();
|
self.db_type = dir.to_string();
|
||||||
}
|
};
|
||||||
|
|
||||||
self.network.apply_cli_args(args)?;
|
self.network.apply_cli_args(args)?;
|
||||||
self.rpc.apply_cli_args(args)?;
|
self.rpc.apply_cli_args(args)?;
|
||||||
self.http.apply_cli_args(args)?;
|
self.http.apply_cli_args(args)?;
|
||||||
|
|
||||||
|
if let Some(log_file) = args.value_of("logfile") {
|
||||||
|
self.log_file = PathBuf::from(log_file);
|
||||||
|
self.update_logger(log)?;
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,13 @@ fn main() {
|
|||||||
.help("Data directory for keys and databases.")
|
.help("Data directory for keys and databases.")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("logfile")
|
||||||
|
.long("logfile")
|
||||||
|
.value_name("logfile")
|
||||||
|
.help("File path where output will be written.")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
// network related arguments
|
// network related arguments
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("listen-address")
|
Arg::with_name("listen-address")
|
||||||
@ -159,7 +166,7 @@ fn main() {
|
|||||||
_ => drain.filter_level(Level::Info),
|
_ => drain.filter_level(Level::Info),
|
||||||
};
|
};
|
||||||
|
|
||||||
let log = slog::Logger::root(drain.fuse(), o!());
|
let mut log = slog::Logger::root(drain.fuse(), o!());
|
||||||
|
|
||||||
let data_dir = match matches
|
let data_dir = match matches
|
||||||
.value_of("datadir")
|
.value_of("datadir")
|
||||||
@ -214,7 +221,7 @@ fn main() {
|
|||||||
client_config.data_dir = data_dir.clone();
|
client_config.data_dir = data_dir.clone();
|
||||||
|
|
||||||
// Update the client config with any CLI args.
|
// Update the client config with any CLI args.
|
||||||
match client_config.apply_cli_args(&matches) {
|
match client_config.apply_cli_args(&matches, &mut log) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
|
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
|
||||||
|
@ -26,8 +26,9 @@ types = { path = "../eth2/types" }
|
|||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
slog = "^2.2.3"
|
slog = "^2.2.3"
|
||||||
slog-term = "^2.4.0"
|
|
||||||
slog-async = "^2.3.0"
|
slog-async = "^2.3.0"
|
||||||
|
slog-json = "^2.3"
|
||||||
|
slog-term = "^2.4.0"
|
||||||
tokio = "0.1.18"
|
tokio = "0.1.18"
|
||||||
tokio-timer = "0.2.10"
|
tokio-timer = "0.2.10"
|
||||||
toml = "^0.5"
|
toml = "^0.5"
|
||||||
|
@ -2,11 +2,11 @@ use bincode;
|
|||||||
use bls::Keypair;
|
use bls::Keypair;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use slog::{debug, error, info};
|
use slog::{debug, error, info, o, Drain};
|
||||||
use std::fs;
|
use std::fs::{self, File, OpenOptions};
|
||||||
use std::fs::File;
|
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Mutex;
|
||||||
use types::{EthSpec, MainnetEthSpec};
|
use types::{EthSpec, MainnetEthSpec};
|
||||||
|
|
||||||
/// Stores the core configuration for this validator instance.
|
/// Stores the core configuration for this validator instance.
|
||||||
@ -14,6 +14,8 @@ use types::{EthSpec, MainnetEthSpec};
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// The data directory, which stores all validator databases
|
/// The data directory, which stores all validator databases
|
||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
|
/// The path where the logs will be outputted
|
||||||
|
pub log_file: PathBuf,
|
||||||
/// The server at which the Beacon Node can be contacted
|
/// The server at which the Beacon Node can be contacted
|
||||||
pub server: String,
|
pub server: String,
|
||||||
/// The number of slots per epoch.
|
/// The number of slots per epoch.
|
||||||
@ -27,6 +29,7 @@ impl Default for Config {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data_dir: PathBuf::from(".lighthouse-validator"),
|
data_dir: PathBuf::from(".lighthouse-validator"),
|
||||||
|
log_file: PathBuf::from(""),
|
||||||
server: "localhost:5051".to_string(),
|
server: "localhost:5051".to_string(),
|
||||||
slots_per_epoch: MainnetEthSpec::slots_per_epoch(),
|
slots_per_epoch: MainnetEthSpec::slots_per_epoch(),
|
||||||
}
|
}
|
||||||
@ -38,11 +41,20 @@ impl Config {
|
|||||||
///
|
///
|
||||||
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
||||||
/// invalid.
|
/// invalid.
|
||||||
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
pub fn apply_cli_args(
|
||||||
|
&mut self,
|
||||||
|
args: &ArgMatches,
|
||||||
|
log: &mut slog::Logger,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
if let Some(datadir) = args.value_of("datadir") {
|
if let Some(datadir) = args.value_of("datadir") {
|
||||||
self.data_dir = PathBuf::from(datadir);
|
self.data_dir = PathBuf::from(datadir);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(log_file) = args.value_of("logfile") {
|
||||||
|
self.log_file = PathBuf::from(log_file);
|
||||||
|
self.update_logger(log)?;
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(srv) = args.value_of("server") {
|
if let Some(srv) = args.value_of("server") {
|
||||||
self.server = srv.to_string();
|
self.server = srv.to_string();
|
||||||
};
|
};
|
||||||
@ -50,6 +62,38 @@ impl Config {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the logger to output in JSON to specified file
|
||||||
|
fn update_logger(&mut self, log: &mut slog::Logger) -> Result<(), &'static str> {
|
||||||
|
let file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&self.log_file);
|
||||||
|
|
||||||
|
if file.is_err() {
|
||||||
|
return Err("Cannot open log file");
|
||||||
|
}
|
||||||
|
let file = file.unwrap();
|
||||||
|
|
||||||
|
if let Some(file) = self.log_file.to_str() {
|
||||||
|
info!(
|
||||||
|
*log,
|
||||||
|
"Log file specified, output will now be written to {} in json.", file
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
*log,
|
||||||
|
"Log file specified output will now be written in json"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drain = Mutex::new(slog_json::Json::default(file)).fuse();
|
||||||
|
let drain = slog_async::Async::new(drain).build().fuse();
|
||||||
|
*log = slog::Logger::root(drain, o!());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to load keys from validator_dir, returning None if none are found or an error.
|
/// Try to load keys from validator_dir, returning None if none are found or an error.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn fetch_keys(&self, log: &slog::Logger) -> Option<Vec<Keypair>> {
|
pub fn fetch_keys(&self, log: &slog::Logger) -> Option<Vec<Keypair>> {
|
||||||
|
@ -26,7 +26,7 @@ fn main() {
|
|||||||
let decorator = slog_term::TermDecorator::new().build();
|
let decorator = slog_term::TermDecorator::new().build();
|
||||||
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
|
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
|
||||||
let drain = slog_async::Async::new(drain).build().fuse();
|
let drain = slog_async::Async::new(drain).build().fuse();
|
||||||
let log = slog::Logger::root(drain, o!());
|
let mut log = slog::Logger::root(drain, o!());
|
||||||
|
|
||||||
// CLI
|
// CLI
|
||||||
let matches = App::new("Lighthouse Validator Client")
|
let matches = App::new("Lighthouse Validator Client")
|
||||||
@ -41,6 +41,13 @@ fn main() {
|
|||||||
.help("Data directory for keys and databases.")
|
.help("Data directory for keys and databases.")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("logfile")
|
||||||
|
.long("logfile")
|
||||||
|
.value_name("logfile")
|
||||||
|
.help("File path where output will be written.")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("eth2-spec")
|
Arg::with_name("eth2-spec")
|
||||||
.long("eth2-spec")
|
.long("eth2-spec")
|
||||||
@ -123,7 +130,7 @@ fn main() {
|
|||||||
client_config.data_dir = data_dir.clone();
|
client_config.data_dir = data_dir.clone();
|
||||||
|
|
||||||
// Update the client config with any CLI args.
|
// Update the client config with any CLI args.
|
||||||
match client_config.apply_cli_args(&matches) {
|
match client_config.apply_cli_args(&matches, &mut log) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
|
crit!(log, "Failed to parse ClientConfig CLI arguments"; "error" => s);
|
||||||
|
Loading…
Reference in New Issue
Block a user