Replace ESP_LOGLEVEL and ESP_LOGFILTERby ESP_LOG (#2291)
* Replace `ESP_LOGLEVEL` and `ESP_LOGFILTER`by `ESP_LOG` * CHANGELOG.md * Clippy * Fail build if using the now unsupported env variables
This commit is contained in:
parent
038d07f5b6
commit
ca5e8560bf
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Replace environment variables `ESP_LOGLEVEL` and `ESP_LOGFILTER` with just one environment variable: `ESP_LOG` (#2291)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ portable-atomic = { version = "1.7.0", optional = true, default-features = fal
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
esp-build = { version = "0.1.0", path = "../esp-build" }
|
esp-build = { version = "0.1.0", path = "../esp-build" }
|
||||||
|
log = "0.4.20"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["critical-section", "colors", "auto"]
|
default = ["critical-section", "colors", "auto"]
|
||||||
|
|||||||
@ -76,8 +76,7 @@ init_logger_from_env();
|
|||||||
|
|
||||||
In this case the following environment variables are used:
|
In this case the following environment variables are used:
|
||||||
|
|
||||||
- `ESP_LOGLEVEL` sets the log level, use values like `trace`, `info` etc.
|
- `ESP_LOG` log messages you want to show, similar to `RUST_LOG`. RegEx is not supported. e.g. `warn,test::foo=info,test::foo::bar=debug`
|
||||||
- `ESP_LOGTARGETS` if set you should provide the crate names of crates (optionally with a path e.g. `esp_wifi::compat::common`) which should get logged, separated by `,` and no additional whitespace between
|
|
||||||
|
|
||||||
If this simple logger implementation isn't sufficient for your needs, you can implement your own logger on top of `esp-println`. See [Implementing a Logger section log documentaion]
|
If this simple logger implementation isn't sufficient for your needs, you can implement your own logger on top of `esp-println`. See [Implementing a Logger section log documentaion]
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::{env, path::Path};
|
||||||
|
|
||||||
use esp_build::assert_unique_used_features;
|
use esp_build::assert_unique_used_features;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -29,4 +31,157 @@ fn main() {
|
|||||||
"cargo:warning=The `colors` feature is only effective when using the `log` feature"
|
"cargo:warning=The `colors` feature is only effective when using the `log` feature"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if std::env::var("ESP_LOGLEVEL").is_ok() || std::env::var("ESP_LOGFILTER").is_ok() {
|
||||||
|
panic!("`ESP_LOGLEVEL` and `ESP_LOGFILTER` is not supported anymore. Please use `ESP_LOG` instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_filter_snippet();
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
println!("cargo:rustc-cfg=host_is_windows");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-env-changed=ESP_LOG");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(host_is_windows)");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_filter_snippet() {
|
||||||
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
let dest_path = Path::new(&out_dir).join("log_filter.rs");
|
||||||
|
|
||||||
|
let filter = env::var("ESP_LOG");
|
||||||
|
let snippet = if let Ok(filter) = filter {
|
||||||
|
let res = parse_spec(&filter);
|
||||||
|
|
||||||
|
if !res.errors.is_empty() {
|
||||||
|
panic!("Error parsing `ESP_LOG`: {:?}", res.errors);
|
||||||
|
} else {
|
||||||
|
let max = res
|
||||||
|
.directives
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.level)
|
||||||
|
.max()
|
||||||
|
.unwrap_or(log::LevelFilter::Off);
|
||||||
|
let max = match max {
|
||||||
|
log::LevelFilter::Off => "Off",
|
||||||
|
log::LevelFilter::Error => "Error",
|
||||||
|
log::LevelFilter::Warn => "Warn",
|
||||||
|
log::LevelFilter::Info => "Info",
|
||||||
|
log::LevelFilter::Debug => "Debug",
|
||||||
|
log::LevelFilter::Trace => "Trace",
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut snippet = String::new();
|
||||||
|
|
||||||
|
snippet.push_str(&format!(
|
||||||
|
"pub(crate) const FILTER_MAX: log::LevelFilter = log::LevelFilter::{};",
|
||||||
|
max
|
||||||
|
));
|
||||||
|
|
||||||
|
snippet
|
||||||
|
.push_str("pub(crate) fn is_enabled(level: log::Level, _target: &str) -> bool {");
|
||||||
|
|
||||||
|
for directive in res.directives {
|
||||||
|
let level = match directive.level {
|
||||||
|
log::LevelFilter::Off => "Off",
|
||||||
|
log::LevelFilter::Error => "Error",
|
||||||
|
log::LevelFilter::Warn => "Warn",
|
||||||
|
log::LevelFilter::Info => "Info",
|
||||||
|
log::LevelFilter::Debug => "Debug",
|
||||||
|
log::LevelFilter::Trace => "Trace",
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(name) = directive.name {
|
||||||
|
snippet.push_str(&format!(
|
||||||
|
"if _target.starts_with(\"{}\") && level <= log::LevelFilter::{} {{ return true; }}",
|
||||||
|
&name, level
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
snippet.push_str(&format!(
|
||||||
|
"if level <= log::LevelFilter::{} {{ return true; }}",
|
||||||
|
level
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snippet.push_str(" false");
|
||||||
|
snippet.push('}');
|
||||||
|
snippet
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"pub(crate) const FILTER_MAX: log::LevelFilter = log::LevelFilter::Off; pub(crate) fn is_enabled(_level: log::Level, _target: &str) -> bool { true }".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
std::fs::write(&dest_path, &snippet).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct ParseResult {
|
||||||
|
pub(crate) directives: Vec<Directive>,
|
||||||
|
pub(crate) errors: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParseResult {
|
||||||
|
fn add_directive(&mut self, directive: Directive) {
|
||||||
|
self.directives.push(directive);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_error(&mut self, message: String) {
|
||||||
|
self.errors.push(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Directive {
|
||||||
|
pub(crate) name: Option<String>,
|
||||||
|
pub(crate) level: log::LevelFilter,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a logging specification string (e.g:
|
||||||
|
/// `crate1,crate2::mod3,crate3::x=error/foo`) and return a vector with log
|
||||||
|
/// directives.
|
||||||
|
fn parse_spec(spec: &str) -> ParseResult {
|
||||||
|
let mut result = ParseResult::default();
|
||||||
|
|
||||||
|
let mut parts = spec.split('/');
|
||||||
|
let mods = parts.next();
|
||||||
|
|
||||||
|
if let Some(m) = mods {
|
||||||
|
for s in m.split(',').map(|ss| ss.trim()) {
|
||||||
|
if s.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut parts = s.split('=');
|
||||||
|
let (log_level, name) =
|
||||||
|
match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
|
||||||
|
(Some(part0), None, None) => {
|
||||||
|
// if the single argument is a log-level string or number,
|
||||||
|
// treat that as a global fallback
|
||||||
|
match part0.parse() {
|
||||||
|
Ok(num) => (num, None),
|
||||||
|
Err(_) => (log::LevelFilter::max(), Some(part0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(part0), Some(""), None) => (log::LevelFilter::max(), Some(part0)),
|
||||||
|
(Some(part0), Some(part1), None) => {
|
||||||
|
if let Ok(num) = part1.parse() {
|
||||||
|
(num, Some(part0))
|
||||||
|
} else {
|
||||||
|
result.add_error(format!("invalid logging spec '{part1}'"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
result.add_error(format!("invalid logging spec '{s}'"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
result.add_directive(Directive {
|
||||||
|
name: name.map(|s| s.to_owned()),
|
||||||
|
level: log_level,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
use core::str::FromStr;
|
|
||||||
|
|
||||||
use log::LevelFilter;
|
|
||||||
|
|
||||||
use super::println;
|
use super::println;
|
||||||
|
|
||||||
const LOG_TARGETS: Option<&'static str> = option_env!("ESP_LOGTARGETS");
|
#[cfg(not(host_is_windows))]
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/log_filter.rs"));
|
||||||
|
|
||||||
|
#[cfg(host_is_windows)]
|
||||||
|
include!(concat!(env!("OUT_DIR"), "\\log_filter.rs"));
|
||||||
|
|
||||||
|
/// Initialize the logger with the given maximum log level.
|
||||||
|
///
|
||||||
|
/// `ESP_LOG` environment variable will still be honored if set.
|
||||||
pub fn init_logger(level: log::LevelFilter) {
|
pub fn init_logger(level: log::LevelFilter) {
|
||||||
unsafe {
|
unsafe {
|
||||||
log::set_logger_racy(&EspLogger).unwrap();
|
log::set_logger_racy(&EspLogger).unwrap();
|
||||||
@ -13,37 +16,27 @@ pub fn init_logger(level: log::LevelFilter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialize the logger from the `ESP_LOG` environment variable.
|
||||||
pub fn init_logger_from_env() {
|
pub fn init_logger_from_env() {
|
||||||
unsafe {
|
unsafe {
|
||||||
log::set_logger_racy(&EspLogger).unwrap();
|
log::set_logger_racy(&EspLogger).unwrap();
|
||||||
}
|
log::set_max_level_racy(FILTER_MAX);
|
||||||
|
|
||||||
const LEVEL: Option<&'static str> = option_env!("ESP_LOGLEVEL");
|
|
||||||
|
|
||||||
if let Some(lvl) = LEVEL {
|
|
||||||
let level = LevelFilter::from_str(lvl).unwrap_or_else(|_| LevelFilter::Off);
|
|
||||||
unsafe { log::set_max_level_racy(level) };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EspLogger;
|
struct EspLogger;
|
||||||
|
|
||||||
impl log::Log for EspLogger {
|
impl log::Log for EspLogger {
|
||||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
fn enabled(&self, metadata: &log::Metadata) -> bool {
|
||||||
true
|
let level = metadata.level();
|
||||||
|
let target = metadata.target();
|
||||||
|
is_enabled(level, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn log(&self, record: &log::Record) {
|
fn log(&self, record: &log::Record) {
|
||||||
// check enabled log targets if any
|
if !self.enabled(&record.metadata()) {
|
||||||
if let Some(targets) = LOG_TARGETS {
|
return;
|
||||||
if targets
|
|
||||||
.split(",")
|
|
||||||
.find(|v| record.target().starts_with(v))
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESET: &str = "\u{001B}[0m";
|
const RESET: &str = "\u{001B}[0m";
|
||||||
|
|||||||
@ -27,7 +27,7 @@ rustflags = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
ESP_LOGLEVEL = "info"
|
ESP_LOG = "info"
|
||||||
SSID = "SSID"
|
SSID = "SSID"
|
||||||
PASSWORD = "PASSWORD"
|
PASSWORD = "PASSWORD"
|
||||||
STATIC_IP = "1.1.1.1 "
|
STATIC_IP = "1.1.1.1 "
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user