api and log refactor

This commit is contained in:
John Smith
2022-07-01 12:13:52 -04:00
parent f409c84778
commit c106d324c8
25 changed files with 662 additions and 501 deletions

View File

@@ -10,14 +10,10 @@ cfg_if! {
use send_wrapper::*;
struct ApiLoggerInner {
max_level: Option<VeilidLogLevel>,
filter_ignore: Cow<'static, [Cow<'static, str>]>,
update_callback: SendWrapper<UpdateCallback>,
}
} else {
struct ApiLoggerInner {
max_level: Option<VeilidLogLevel>,
filter_ignore: Cow<'static, [Cow<'static, str>]>,
update_callback: UpdateCallback,
}
}
@@ -31,21 +27,14 @@ pub struct ApiTracingLayer {
static API_LOGGER: OnceCell<ApiTracingLayer> = OnceCell::new();
impl ApiTracingLayer {
fn new_inner(
max_level: Option<VeilidLogLevel>,
update_callback: UpdateCallback,
) -> ApiLoggerInner {
fn new_inner(update_callback: UpdateCallback) -> ApiLoggerInner {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
ApiLoggerInner {
max_level,
filter_ignore: Default::default(),
update_callback: SendWrapper::new(update_callback),
}
} else {
ApiLoggerInner {
max_level,
filter_ignore: Default::default(),
update_callback,
}
}
@@ -53,11 +42,11 @@ impl ApiTracingLayer {
}
#[instrument(level = "debug", skip(update_callback))]
pub async fn init(max_level: Option<VeilidLogLevel>, update_callback: UpdateCallback) {
pub async fn init(update_callback: UpdateCallback) {
let api_logger = API_LOGGER.get_or_init(|| ApiTracingLayer {
inner: Arc::new(Mutex::new(None)),
});
let apilogger_inner = Some(Self::new_inner(max_level, update_callback));
let apilogger_inner = Some(Self::new_inner(update_callback));
*api_logger.inner.lock() = apilogger_inner;
}
@@ -76,52 +65,9 @@ impl ApiTracingLayer {
})
.clone()
}
#[instrument(level = "trace")]
pub fn change_api_log_level(max_level: Option<VeilidLogLevel>) {
if let Some(api_logger) = API_LOGGER.get() {
if let Some(inner) = &mut *api_logger.inner.lock() {
inner.max_level = max_level;
}
}
}
pub fn add_filter_ignore_str(filter_ignore: &'static str) {
if let Some(api_logger) = API_LOGGER.get() {
if let Some(inner) = &mut *api_logger.inner.lock() {
let mut list = Vec::from(&*inner.filter_ignore);
list.push(Cow::Borrowed(filter_ignore));
inner.filter_ignore = Cow::Owned(list);
}
}
}
}
impl<S: Subscriber + for<'a> registry::LookupSpan<'a>> Layer<S> for ApiTracingLayer {
fn enabled(&self, metadata: &tracing::Metadata<'_>, _: layer::Context<'_, S>) -> bool {
if let Some(inner) = &mut *self.inner.lock() {
// Skip things that are out of our level
if let Some(max_level) = inner.max_level {
if VeilidLogLevel::from_tracing_level(*metadata.level()) > max_level {
return false;
}
} else {
return false;
}
// Skip filtered targets
let skip = match (metadata.target(), &*inner.filter_ignore) {
(path, ignore) if !ignore.is_empty() => {
// Check that the module path does not match any ignore filters
ignore.iter().any(|v| path.starts_with(&**v))
}
_ => false,
};
!skip
} else {
false
}
}
fn on_new_span(
&self,
attrs: &tracing::span::Attributes<'_>,
@@ -161,23 +107,16 @@ impl<S: Subscriber + for<'a> registry::LookupSpan<'a>> Layer<S> for ApiTracingLa
event.record(&mut recorder);
let meta = event.metadata();
let level = meta.level();
if let Some(max_level) = inner.max_level {
if VeilidLogLevel::from_tracing_level(*level) <= max_level {
let log_level = VeilidLogLevel::from_tracing_level(*level);
let log_level = VeilidLogLevel::from_tracing_level(*level);
let origin = meta
.file()
.and_then(|file| meta.line().map(|ln| format!("{}:{}", file, ln)))
.unwrap_or_default();
let origin = meta
.file()
.and_then(|file| meta.line().map(|ln| format!("{}:{}", file, ln)))
.unwrap_or_default();
let message = format!("{} {}", origin, recorder);
let message = format!("{} {}", origin, recorder);
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
log_level,
message,
}))
}
}
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog { log_level, message }))
}
}
}
@@ -232,64 +171,3 @@ impl core::default::Default for StringRecorder {
StringRecorder::new()
}
}
impl log::Log for ApiTracingLayer {
fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
if let Some(inner) = &mut *self.inner.lock() {
if let Some(max_level) = inner.max_level {
return VeilidLogLevel::from_log_level(metadata.level()) <= max_level;
}
}
false
}
fn log(&self, record: &log::Record<'_>) {
if let Some(inner) = &mut *self.inner.lock() {
// Skip filtered targets
let skip = match (record.target(), &*inner.filter_ignore) {
(path, ignore) if !ignore.is_empty() => {
// Check that the module path does not match any ignore filters
ignore.iter().any(|v| path.starts_with(&**v))
}
_ => false,
};
if skip {
return;
}
let metadata = record.metadata();
let level = metadata.level();
let log_level = VeilidLogLevel::from_log_level(level);
if let Some(max_level) = inner.max_level {
if log_level <= max_level {
let file = record.file().unwrap_or("<unknown>");
let loc = if level >= log::Level::Debug {
if let Some(line) = record.line() {
format!("[{}:{}] ", file, line)
} else {
format!("[{}:<unknown>] ", file)
}
} else {
"".to_owned()
};
let tgt = if record.target().is_empty() {
"".to_owned()
} else {
format!("{}: ", record.target())
};
let message = format!("{}{}{}", tgt, loc, record.args());
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
log_level,
message,
}))
}
}
}
}
fn flush(&self) {
// always flushes
}
}

View File

@@ -59,21 +59,11 @@ impl ServicesContext {
#[instrument(err, skip_all)]
pub async fn startup(&mut self) -> Result<(), VeilidAPIError> {
let api_log_level: VeilidConfigLogLevel = self.config.get().api_log_level;
if api_log_level != VeilidConfigLogLevel::Off {
ApiTracingLayer::init(
api_log_level.to_veilid_log_level(),
self.update_callback.clone(),
)
.await;
for ig in crate::DEFAULT_LOG_IGNORE_LIST {
ApiTracingLayer::add_filter_ignore_str(ig);
}
info!("Veilid API logging initialized");
}
info!("Veilid API starting up");
info!("init api tracing");
ApiTracingLayer::init(self.update_callback.clone()).await;
// Set up protected store
trace!("init protected store");
let protected_store = ProtectedStore::new(self.config.clone());

View File

@@ -30,6 +30,7 @@ mod routing_table;
mod rpc_processor;
mod veilid_api;
mod veilid_config;
mod veilid_layer_filter;
mod veilid_rng;
#[macro_use]
@@ -40,6 +41,7 @@ pub use self::attachment_manager::AttachmentState;
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
pub use self::veilid_api::*;
pub use self::veilid_config::*;
pub use self::veilid_layer_filter::*;
pub mod veilid_capnp {
include!(concat!(env!("OUT_DIR"), "/proto/veilid_capnp.rs"));

View File

@@ -169,7 +169,6 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
match key.as_str() {
"program_name" => Ok(Box::new(String::from("Veilid"))),
"namespace" => Ok(Box::new(String::from(""))),
"api_log_level" => Ok(Box::new(VeilidConfigLogLevel::Off)),
"capabilities.protocol_udp" => Ok(Box::new(true)),
"capabilities.protocol_connect_tcp" => Ok(Box::new(true)),
"capabilities.protocol_accept_tcp" => Ok(Box::new(true)),

View File

@@ -1861,12 +1861,6 @@ impl VeilidAPI {
.map_err(|e| VeilidAPIError::Internal { message: e })
}
// Change api logging level if it is enabled
#[instrument(skip(self))]
pub async fn change_api_log_level(&self, log_level: VeilidConfigLogLevel) {
ApiTracingLayer::change_api_log_level(log_level.to_veilid_log_level());
}
////////////////////////////////////////////////////////////////
// Direct Node Access (pretty much for testing only)

View File

@@ -223,6 +223,16 @@ impl VeilidConfigLogLevel {
Some(VeilidLogLevel::Trace) => Self::Trace,
}
}
pub fn from_tracing_level_filter(level: level_filters::LevelFilter) -> Self {
match level {
level_filters::LevelFilter::OFF => Self::Off,
level_filters::LevelFilter::ERROR => Self::Error,
level_filters::LevelFilter::WARN => Self::Warn,
level_filters::LevelFilter::INFO => Self::Info,
level_filters::LevelFilter::DEBUG => Self::Debug,
level_filters::LevelFilter::TRACE => Self::Trace,
}
}
}
impl Default for VeilidConfigLogLevel {
fn default() -> Self {

View File

@@ -0,0 +1,91 @@
use super::*;
use crate::xx::*;
use tracing::level_filters::LevelFilter;
use tracing::subscriber;
use tracing_subscriber::layer;
struct VeilidLayerFilterInner {
max_level: LevelFilter,
ignore_list: Vec<String>,
}
#[derive(Clone)]
pub struct VeilidLayerFilter {
inner: Arc<RwLock<VeilidLayerFilterInner>>,
}
impl VeilidLayerFilter {
pub fn new(
max_level: VeilidConfigLogLevel,
ignore_list: Option<Vec<String>>,
) -> VeilidLayerFilter {
Self {
inner: Arc::new(RwLock::new(VeilidLayerFilterInner {
max_level: max_level.to_tracing_level_filter(),
ignore_list: ignore_list
.unwrap_or_else(|| DEFAULT_LOG_IGNORE_LIST.map(|x| x.to_owned()).to_vec()),
})),
}
}
pub fn max_level(&self) -> VeilidConfigLogLevel {
let inner = self.inner.read();
VeilidConfigLogLevel::from_tracing_level_filter(inner.max_level)
}
pub fn ignore_list(&self) -> Vec<String> {
let inner = self.inner.read();
inner.ignore_list.clone()
}
pub fn set_max_level(&self, level: VeilidConfigLogLevel) {
{
let mut inner = self.inner.write();
inner.max_level = level.to_tracing_level_filter();
}
callsite::rebuild_interest_cache();
}
pub fn set_ignore_list(&self, ignore_list: Option<Vec<String>>) {
{
let mut inner = self.inner.write();
inner.ignore_list = ignore_list
.unwrap_or_else(|| DEFAULT_LOG_IGNORE_LIST.map(|x| x.to_owned()).to_vec());
}
callsite::rebuild_interest_cache();
}
}
impl<S: tracing::Subscriber> layer::Filter<S> for VeilidLayerFilter {
fn enabled(&self, metadata: &tracing::Metadata<'_>, _: &layer::Context<'_, S>) -> bool {
let inner = self.inner.read();
if *metadata.level() > inner.max_level {
false
} else {
true
}
}
fn callsite_enabled(
&self,
metadata: &'static tracing::Metadata<'static>,
) -> subscriber::Interest {
let inner = self.inner.read();
let skip = inner
.ignore_list
.iter()
.any(|v| metadata.target().starts_with(&**v));
if skip {
subscriber::Interest::never()
} else if *metadata.level() > inner.max_level {
subscriber::Interest::never()
} else {
subscriber::Interest::always()
}
}
fn max_level_hint(&self) -> Option<LevelFilter> {
let inner = self.inner.read();
Some(inner.max_level)
}
}