diff --git a/src/python/pants/init/logging.py b/src/python/pants/init/logging.py index 42b3b0caf717..aa63a7baf133 100644 --- a/src/python/pants/init/logging.py +++ b/src/python/pants/init/logging.py @@ -48,7 +48,7 @@ def setup_logging_from_options(bootstrap_options): return setup_logging(level, console_stream=sys.stderr, log_dir=bootstrap_options.logdir) -def setup_logging(level, console_stream=None, log_dir=None, scope=None, log_name=None): +def setup_logging(level, console_stream=None, log_dir=None, scope=None, log_name=None, native=None): """Configures logging for a given scope, by default the global scope. :param str level: The logging level to enable, must be one of the level names listed here: @@ -95,10 +95,15 @@ def trace(self, message, *args, **kwargs): logger.addHandler(console_handler) if log_dir: + safe_mkdir(log_dir) log_filename = os.path.join(log_dir, log_name or 'pants.log') file_handler = FileHandler(log_filename) + if native: + print("BL: setup_logging with native, filename {}".format(log_filename)) + native.lib.setup_pantsd_logging(log_filename, level) + class GlogFormatter(Formatter): LEVEL_MAP = { logging.FATAL: 'F', diff --git a/src/python/pants/pantsd/pants_daemon.py b/src/python/pants/pantsd/pants_daemon.py index 5a55782dff3c..4815b0b54d24 100644 --- a/src/python/pants/pantsd/pants_daemon.py +++ b/src/python/pants/pantsd/pants_daemon.py @@ -287,7 +287,7 @@ def _pantsd_logging(self): # for further forks. with stdio_as(stdin_fd=-1, stdout_fd=-1, stderr_fd=-1): # Reinitialize logging for the daemon context. - result = setup_logging(self._log_level, log_dir=self._log_dir, log_name=self.LOG_NAME) + result = setup_logging(self._log_level, log_dir=self._log_dir, log_name=self.LOG_NAME, native=self._native) # Do a python-level redirect of stdout/stderr, which will not disturb `0,1,2`. # TODO: Consider giving these pipes/actual fds, in order to make them "deep" replacements diff --git a/src/rust/engine/logging/src/logger.rs b/src/rust/engine/logging/src/logger.rs index 251adb987ee9..e4538a630f0f 100644 --- a/src/rust/engine/logging/src/logger.rs +++ b/src/rust/engine/logging/src/logger.rs @@ -6,15 +6,17 @@ use simplelog::Config; use simplelog::WriteLogger; use std::fs::File; use std::io::{stderr, Stderr, Write}; +use std::path::PathBuf; +use std::io::Error; lazy_static! { - static ref LOGGER: Logger = Logger::new(LevelFilter::Off); + pub static ref LOGGER: Logger = Logger::new(LevelFilter::Off); } // This is a hard-coding of constants in the standard logging python package. // TODO: Switch from CustomTryInto to TryFromPrimitive when try_from is stable. #[derive(Debug, Eq, PartialEq, CustomTryInto)] -#[repr(u8)] +#[repr(u64)] enum PythonLogLevel { NotSet = 0, // Trace doesn't exist in a Python world, so set it to "a bit lower than Debug". @@ -76,7 +78,7 @@ impl Logger { } pub fn init(max_level: u8) { - let max_python_level = max_level.try_into_PythonLogLevel(); + let max_python_level = (max_level as u64).try_into_PythonLogLevel(); match max_python_level { Ok(python_level) => { let level: log::LevelFilter = python_level.into(); @@ -97,6 +99,18 @@ impl Logger { pub fn set_stderr_log_level(&self, level: LevelFilter) { self.stderr_log.lock().set_level(level); } + + pub fn set_pantsd_logger(&self, log_file_path: PathBuf, python_level: u64) -> Result<(), String> { + let res = python_level.try_into_PythonLogLevel().and_then( |level| { +// File::create(log_file_path).map(|file| { + File::create(log_file_path.clone()).map(|file| { + *self.pantsd_log.lock() = MaybeWriteLogger::new(file, level.into()); + }).map_err(|err| format!("{}", err)) + }); + + info!("BL: Set pantsd logger at {:?}", log_file_path); + res + } } impl Log for Logger { diff --git a/src/rust/engine/src/lib.rs b/src/rust/engine/src/lib.rs index 92d1406c34c7..3a3913b0cbc3 100644 --- a/src/rust/engine/src/lib.rs +++ b/src/rust/engine/src/lib.rs @@ -98,6 +98,8 @@ use scheduler::{ExecutionRequest, RootResult, Scheduler, Session}; use tasks::Tasks; use types::Types; +use logging::logger::LOGGER; + // TODO: Consider renaming and making generic for collections of PyResults. #[repr(C)] pub struct RawNodes { @@ -783,6 +785,15 @@ pub extern "C" fn materialize_directories( .into() } +#[no_mangle] +pub extern "C" fn setup_pantsd_logging(log_file_ptr: *const raw::c_char, level: u64) -> PyResult { + let path_str = unsafe { CStr::from_ptr(log_file_ptr).to_string_lossy().into_owned() }; + let path = PathBuf::from(path_str); + eprintln!("BL: Setup pantsd logger"); + LOGGER.set_pantsd_logger(path, level) + .into() +} + fn graph_full(scheduler: &Scheduler, subject_types: Vec) -> RuleGraph { let graph_maker = GraphMaker::new(&scheduler.core.tasks, subject_types); graph_maker.full_graph()