mirror of https://github.com/rwf2/Rocket.git
Dynamically increase/decrease log level at launch.
This commit modifies the internal logger so that launch messages are emitted with the proper "info" level. The approach is to temporarily weaken the log level to "normal" during launch and reset it to the user's setting after launching. This commit also upgrades to 'log' 0.4. Fixes #553.
This commit is contained in:
parent
f2331a831a
commit
3a8d0e8a9a
|
@ -17,7 +17,7 @@ plugin = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
||||||
ordermap = "0.3"
|
ordermap = "0.3"
|
||||||
log = "0.3"
|
log = "0.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
compiletest_rs = "0.3.5"
|
compiletest_rs = "0.3.5"
|
||||||
|
|
|
@ -22,7 +22,7 @@ templates = ["serde", "serde_json", "glob"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
rocket = { version = "0.4.0-dev", path = "../lib/" }
|
||||||
log = "^0.3"
|
log = "0.4"
|
||||||
|
|
||||||
# UUID dependencies.
|
# UUID dependencies.
|
||||||
uuid = { version = "^0.5", optional = true }
|
uuid = { version = "^0.5", optional = true }
|
||||||
|
|
|
@ -19,7 +19,7 @@ tls = ["rustls", "hyper-sync-rustls"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
yansi = { version = "0.3.3", features = ["nightly"] }
|
yansi = { version = "0.3.3", features = ["nightly"] }
|
||||||
log = "0.3"
|
log = "0.4"
|
||||||
percent-encoding = "1"
|
percent-encoding = "1"
|
||||||
toml = "0.4.2"
|
toml = "0.4.2"
|
||||||
num_cpus = "1.0"
|
num_cpus = "1.0"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use log::{self, Log, LogLevel, LogRecord, LogMetadata};
|
use log;
|
||||||
use yansi::Paint;
|
use yansi::Paint;
|
||||||
|
|
||||||
struct RocketLogger(LoggingLevel);
|
struct RocketLogger(LoggingLevel);
|
||||||
|
@ -21,11 +21,11 @@ pub enum LoggingLevel {
|
||||||
|
|
||||||
impl LoggingLevel {
|
impl LoggingLevel {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn max_log_level(&self) -> LogLevel {
|
fn max_log_level(&self) -> log::Level {
|
||||||
match *self {
|
match *self {
|
||||||
LoggingLevel::Critical => LogLevel::Warn,
|
LoggingLevel::Critical => log::Level::Warn,
|
||||||
LoggingLevel::Normal => LogLevel::Info,
|
LoggingLevel::Normal => log::Level::Info,
|
||||||
LoggingLevel::Debug => LogLevel::Trace,
|
LoggingLevel::Debug => log::Level::Trace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,9 @@ impl fmt::Display for LoggingLevel {
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
macro_rules! log_ { ($name:ident: $($args:tt)*) => { $name!(target: "_", $($args)*) }; }
|
macro_rules! log_ { ($name:ident: $($args:tt)*) => { $name!(target: "_", $($args)*) }; }
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
macro_rules! launch_info { ($($args:tt)*) => { error!(target: "launch", $($args)*) } }
|
macro_rules! launch_info { ($($args:tt)*) => { info!(target: "launch", $($args)*) } }
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
macro_rules! launch_info_ { ($($args:tt)*) => { error!(target: "launch_", $($args)*) } }
|
macro_rules! launch_info_ { ($($args:tt)*) => { info!(target: "launch_", $($args)*) } }
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
macro_rules! error_ { ($($args:expr),+) => { log_!(error: $($args),+); }; }
|
macro_rules! error_ { ($($args:expr),+) => { log_!(error: $($args),+); }; }
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
|
@ -74,82 +74,102 @@ macro_rules! debug_ { ($($args:expr),+) => { log_!(debug: $($args),+); }; }
|
||||||
#[doc(hidden)] #[macro_export]
|
#[doc(hidden)] #[macro_export]
|
||||||
macro_rules! warn_ { ($($args:expr),+) => { log_!(warn: $($args),+); }; }
|
macro_rules! warn_ { ($($args:expr),+) => { log_!(warn: $($args),+); }; }
|
||||||
|
|
||||||
impl Log for RocketLogger {
|
impl log::Log for RocketLogger {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn enabled(&self, md: &LogMetadata) -> bool {
|
fn enabled(&self, record: &log::Metadata) -> bool {
|
||||||
md.level() <= self.0.max_log_level()
|
record.target().starts_with("launch") || record.level() <= self.0.max_log_level()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&self, record: &LogRecord) {
|
fn log(&self, record: &log::Record) {
|
||||||
// Print nothing if this level isn't enabled.
|
// Print nothing if this level isn't enabled and this isn't launch info.
|
||||||
if !self.enabled(record.metadata()) {
|
if !self.enabled(record.metadata()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use the `launch_info` macro to "fake" a high priority info
|
|
||||||
// message. We want to print the message unless the user uses a custom
|
|
||||||
// drain, so we set it's status to critical, but reset it here to info.
|
|
||||||
let (configged_level, level) = match record.target() {
|
|
||||||
"launch" | "launch_" => (LoggingLevel::Normal, LogLevel::Info),
|
|
||||||
_ => (self.0, record.level())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Don't print Hyper or Rustls messages unless debug is enabled.
|
// Don't print Hyper or Rustls messages unless debug is enabled.
|
||||||
let from_hyper = record.location().module_path().starts_with("hyper::");
|
let configged_level = self.0;
|
||||||
let from_rustls = record.location().module_path().starts_with("rustls::");
|
let from_hyper = record.module_path().map_or(false, |m| m.starts_with("hyper::"));
|
||||||
|
let from_rustls = record.module_path().map_or(false, |m| m.starts_with("rustls::"));
|
||||||
if configged_level != LoggingLevel::Debug && (from_hyper || from_rustls) {
|
if configged_level != LoggingLevel::Debug && (from_hyper || from_rustls) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Rocket, we abuse targets with value "_" to indicate indentation.
|
// In Rocket, we abuse targets with suffix "_" to indicate indentation.
|
||||||
if record.target().ends_with('_') && configged_level != LoggingLevel::Critical {
|
if record.target().ends_with('_') {
|
||||||
print!(" {} ", Paint::white("=>"));
|
if configged_level != LoggingLevel::Critical || record.target().starts_with("launch") {
|
||||||
|
print!(" {} ", Paint::white("=>"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use log::LogLevel::*;
|
match record.level() {
|
||||||
match level {
|
log::Level::Info => println!("{}", Paint::blue(record.args())),
|
||||||
Info => println!("{}", Paint::blue(record.args())),
|
log::Level::Trace => println!("{}", Paint::purple(record.args())),
|
||||||
Trace => println!("{}", Paint::purple(record.args())),
|
log::Level::Error => {
|
||||||
Error => {
|
|
||||||
println!("{} {}",
|
println!("{} {}",
|
||||||
Paint::red("Error:").bold(),
|
Paint::red("Error:").bold(),
|
||||||
Paint::red(record.args()))
|
Paint::red(record.args()))
|
||||||
}
|
}
|
||||||
Warn => {
|
log::Level::Warn => {
|
||||||
println!("{} {}",
|
println!("{} {}",
|
||||||
Paint::yellow("Warning:").bold(),
|
Paint::yellow("Warning:").bold(),
|
||||||
Paint::yellow(record.args()))
|
Paint::yellow(record.args()))
|
||||||
}
|
}
|
||||||
Debug => {
|
log::Level::Debug => {
|
||||||
let loc = record.location();
|
|
||||||
print!("\n{} ", Paint::blue("-->").bold());
|
print!("\n{} ", Paint::blue("-->").bold());
|
||||||
println!("{}:{}", Paint::blue(loc.file()), Paint::blue(loc.line()));
|
if let Some(file) = record.file() {
|
||||||
|
print!("{}", Paint::blue(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line) = record.line() {
|
||||||
|
println!(":{}", Paint::blue(line));
|
||||||
|
}
|
||||||
|
|
||||||
println!("{}", record.args());
|
println!("{}", record.args());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush(&self) {
|
||||||
|
// NOOP: We don't buffer any records.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
pub(crate) fn try_init(level: LoggingLevel, verbose: bool) {
|
||||||
pub fn try_init(level: LoggingLevel, verbose: bool) {
|
|
||||||
if !::isatty::stdout_isatty() {
|
if !::isatty::stdout_isatty() {
|
||||||
Paint::disable();
|
Paint::disable();
|
||||||
} else if cfg!(windows) {
|
} else if cfg!(windows) {
|
||||||
Paint::enable_windows_ascii();
|
Paint::enable_windows_ascii();
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = log::set_logger(|max_log_level| {
|
push_max_level(level);
|
||||||
max_log_level.set(level.max_log_level().to_log_level_filter());
|
if let Err(e) = log::set_boxed_logger(Box::new(RocketLogger(level))) {
|
||||||
Box::new(RocketLogger(level))
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Err(err) = result {
|
|
||||||
if verbose {
|
if verbose {
|
||||||
println!("Logger failed to initialize: {}", err);
|
eprintln!("Logger failed to initialize: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
static LAST_LOG_FILTER: AtomicUsize = AtomicUsize::new(filter_to_usize(log::LevelFilter::Off));
|
||||||
|
|
||||||
|
const fn filter_to_usize(filter: log::LevelFilter) -> usize {
|
||||||
|
filter as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usize_to_filter(num: usize) -> log::LevelFilter {
|
||||||
|
unsafe { ::std::mem::transmute(num) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn push_max_level(level: LoggingLevel) {
|
||||||
|
LAST_LOG_FILTER.store(filter_to_usize(log::max_level()), Ordering::Release);
|
||||||
|
log::set_max_level(level.max_log_level().to_level_filter());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn pop_max_level() {
|
||||||
|
log::set_max_level(usize_to_filter(LAST_LOG_FILTER.load(Ordering::Acquire)));
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn init(level: LoggingLevel) {
|
pub fn init(level: LoggingLevel) {
|
||||||
try_init(level, true)
|
try_init(level, true)
|
||||||
|
|
|
@ -372,7 +372,9 @@ impl Rocket {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn configured(config: Config, log: bool) -> Rocket {
|
fn configured(config: Config, log: bool) -> Rocket {
|
||||||
if log {
|
if log {
|
||||||
|
// Initialize logger. Temporary weaken log level for launch info.
|
||||||
logger::try_init(config.log_level, false);
|
logger::try_init(config.log_level, false);
|
||||||
|
logger::push_max_level(logger::LoggingLevel::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_info!("{}Configured for {}.", Paint::masked("🔧 "), config.environment);
|
launch_info!("{}Configured for {}.", Paint::masked("🔧 "), config.environment);
|
||||||
|
@ -679,6 +681,9 @@ impl Rocket {
|
||||||
Paint::white(proto).bold(),
|
Paint::white(proto).bold(),
|
||||||
Paint::white(&full_addr).bold());
|
Paint::white(&full_addr).bold());
|
||||||
|
|
||||||
|
// Restore the log level back to what it originally was.
|
||||||
|
logger::pop_max_level();
|
||||||
|
|
||||||
let threads = self.config.workers as usize;
|
let threads = self.config.workers as usize;
|
||||||
if let Err(e) = server.handle_threads(self, threads) {
|
if let Err(e) = server.handle_threads(self, threads) {
|
||||||
return LaunchError::from(e);
|
return LaunchError::from(e);
|
||||||
|
|
Loading…
Reference in New Issue