mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-11-22 08:56:58 -06:00
api and log refactor
This commit is contained in:
parent
f409c84778
commit
c106d324c8
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5155,7 +5155,6 @@ dependencies = [
|
||||
"ctrlc",
|
||||
"daemonize",
|
||||
"directories",
|
||||
"failure",
|
||||
"flume",
|
||||
"futures-util",
|
||||
"hostname",
|
||||
|
@ -3,6 +3,7 @@ use crate::tools::*;
|
||||
use crate::veilid_client_capnp::*;
|
||||
use capnp::capability::Promise;
|
||||
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, Disconnector, RpcSystem};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::cell::RefCell;
|
||||
use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
@ -28,6 +29,30 @@ macro_rules! pry_result {
|
||||
};
|
||||
}
|
||||
|
||||
fn map_to_internal_error<T: ToString>(e: T) -> VeilidAPIError {
|
||||
VeilidAPIError::Internal {
|
||||
message: e.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_api_result<T: DeserializeOwned + fmt::Debug>(
|
||||
reader: &api_result::Reader,
|
||||
) -> Result<T, VeilidAPIError> {
|
||||
match reader.which().map_err(map_to_internal_error)? {
|
||||
api_result::Which::Ok(v) => {
|
||||
let ok_val = v.map_err(map_to_internal_error)?;
|
||||
let res: T = veilid_core::deserialize_json(ok_val).map_err(map_to_internal_error)?;
|
||||
Ok(res)
|
||||
}
|
||||
api_result::Which::Err(e) => {
|
||||
let err_val = e.map_err(map_to_internal_error)?;
|
||||
let res: VeilidAPIError =
|
||||
veilid_core::deserialize_json(err_val).map_err(map_to_internal_error)?;
|
||||
Err(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct VeilidClientImpl {
|
||||
comproc: CommandProcessor,
|
||||
}
|
||||
@ -254,7 +279,13 @@ impl ClientApiConnection {
|
||||
};
|
||||
let request = server.borrow().attach_request();
|
||||
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||
response.get().map(drop).map_err(map_to_string)
|
||||
let reader = response
|
||||
.get()
|
||||
.map_err(map_to_string)?
|
||||
.get_result()
|
||||
.map_err(map_to_string)?;
|
||||
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
|
||||
res.map_err(map_to_string)
|
||||
}
|
||||
|
||||
pub async fn server_detach(&mut self) -> Result<(), String> {
|
||||
@ -269,7 +300,13 @@ impl ClientApiConnection {
|
||||
};
|
||||
let request = server.borrow().detach_request();
|
||||
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||
response.get().map(drop).map_err(map_to_string)
|
||||
let reader = response
|
||||
.get()
|
||||
.map_err(map_to_string)?
|
||||
.get_result()
|
||||
.map_err(map_to_string)?;
|
||||
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
|
||||
res.map_err(map_to_string)
|
||||
}
|
||||
|
||||
pub async fn server_shutdown(&mut self) -> Result<(), String> {
|
||||
@ -294,18 +331,47 @@ impl ClientApiConnection {
|
||||
inner
|
||||
.server
|
||||
.as_ref()
|
||||
.ok_or_else(|| "Not connected, ignoring attach request".to_owned())?
|
||||
.ok_or_else(|| "Not connected, ignoring debug request".to_owned())?
|
||||
.clone()
|
||||
};
|
||||
let mut request = server.borrow().debug_request();
|
||||
request.get().set_what(&what);
|
||||
request.get().set_command(&what);
|
||||
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||
response
|
||||
let reader = response
|
||||
.get()
|
||||
.map_err(map_to_string)?
|
||||
.get_output()
|
||||
.map(|o| o.to_owned())
|
||||
.map_err(map_to_string)
|
||||
.get_result()
|
||||
.map_err(map_to_string)?;
|
||||
let res: Result<String, VeilidAPIError> = decode_api_result(&reader);
|
||||
res.map_err(map_to_string)
|
||||
}
|
||||
|
||||
pub async fn server_change_log_level(
|
||||
&mut self,
|
||||
layer: String,
|
||||
log_level: VeilidConfigLogLevel,
|
||||
) -> Result<(), String> {
|
||||
trace!("ClientApiConnection::change_log_level");
|
||||
let server = {
|
||||
let inner = self.inner.borrow();
|
||||
inner
|
||||
.server
|
||||
.as_ref()
|
||||
.ok_or_else(|| "Not connected, ignoring change_log_level request".to_owned())?
|
||||
.clone()
|
||||
};
|
||||
let mut request = server.borrow().change_log_level_request();
|
||||
request.get().set_layer(&layer);
|
||||
let log_level_json = veilid_core::serialize_json(&log_level);
|
||||
request.get().set_log_level(&log_level_json);
|
||||
let response = request.send().promise.await.map_err(map_to_string)?;
|
||||
let reader = response
|
||||
.get()
|
||||
.map_err(map_to_string)?
|
||||
.get_result()
|
||||
.map_err(map_to_string)?;
|
||||
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
|
||||
res.map_err(map_to_string)
|
||||
}
|
||||
|
||||
// Start Client API connection
|
||||
|
@ -8,6 +8,19 @@ use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use veilid_core::xx::{Eventual, EventualCommon};
|
||||
use veilid_core::VeilidConfigLogLevel;
|
||||
|
||||
pub fn convert_loglevel(s: &str) -> Result<VeilidConfigLogLevel, String> {
|
||||
match s.to_ascii_lowercase().as_str() {
|
||||
"off" => Ok(VeilidConfigLogLevel::Off),
|
||||
"error" => Ok(VeilidConfigLogLevel::Error),
|
||||
"warn" => Ok(VeilidConfigLogLevel::Warn),
|
||||
"info" => Ok(VeilidConfigLogLevel::Info),
|
||||
"debug" => Ok(VeilidConfigLogLevel::Debug),
|
||||
"trace" => Ok(VeilidConfigLogLevel::Trace),
|
||||
_ => Err(format!("Invalid log level: {}", s)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub enum ConnectionState {
|
||||
@ -97,6 +110,7 @@ shutdown - shut the server down
|
||||
attach - attach the server to the Veilid network
|
||||
detach - detach the server from the Veilid network
|
||||
debug - send a debugging command to the Veilid server
|
||||
change_log_level - change the log level for a tracing layer
|
||||
"#,
|
||||
);
|
||||
let ui = self.ui();
|
||||
@ -131,7 +145,7 @@ debug - send a debugging command to the Veilid server
|
||||
let ui = self.ui();
|
||||
spawn_detached_local(async move {
|
||||
if let Err(e) = capi.server_attach().await {
|
||||
error!("Server command 'attach' failed to execute: {}", e);
|
||||
error!("Server command 'attach' failed: {}", e);
|
||||
}
|
||||
ui.send_callback(callback);
|
||||
});
|
||||
@ -144,7 +158,7 @@ debug - send a debugging command to the Veilid server
|
||||
let ui = self.ui();
|
||||
spawn_detached_local(async move {
|
||||
if let Err(e) = capi.server_detach().await {
|
||||
error!("Server command 'detach' failed to execute: {}", e);
|
||||
error!("Server command 'detach' failed: {}", e);
|
||||
}
|
||||
ui.send_callback(callback);
|
||||
});
|
||||
@ -170,7 +184,40 @@ debug - send a debugging command to the Veilid server
|
||||
match capi.server_debug(rest.unwrap_or_default()).await {
|
||||
Ok(output) => ui.display_string_dialog("Debug Output", output, callback),
|
||||
Err(e) => {
|
||||
error!("Server command 'debug' failed to execute: {}", e);
|
||||
error!("Server command 'debug' failed: {}", e);
|
||||
ui.send_callback(callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn cmd_change_log_level(
|
||||
&self,
|
||||
rest: Option<String>,
|
||||
callback: UICallback,
|
||||
) -> Result<(), String> {
|
||||
trace!("CommandProcessor::cmd_change_log_level");
|
||||
let mut capi = self.capi();
|
||||
let ui = self.ui();
|
||||
spawn_detached_local(async move {
|
||||
let (layer, rest) = Self::word_split(&rest.unwrap_or_default());
|
||||
let log_level = match convert_loglevel(&rest.unwrap_or_default()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("failed to change log level: {}", e);
|
||||
ui.send_callback(callback);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match capi.server_change_log_level(layer, log_level).await {
|
||||
Ok(()) => {
|
||||
info!("Log level changed");
|
||||
ui.send_callback(callback);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Server command 'change_log_level' failed: {}", e);
|
||||
ui.send_callback(callback);
|
||||
}
|
||||
}
|
||||
@ -190,6 +237,7 @@ debug - send a debugging command to the Veilid server
|
||||
"attach" => self.cmd_attach(callback),
|
||||
"detach" => self.cmd_detach(callback),
|
||||
"debug" => self.cmd_debug(rest, callback),
|
||||
"change_log_level" => self.cmd_change_log_level(rest, callback),
|
||||
_ => {
|
||||
let ui = self.ui();
|
||||
ui.send_callback(callback);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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"));
|
||||
|
@ -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)),
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
91
veilid-core/src/veilid_layer_filter.rs
Normal file
91
veilid-core/src/veilid_layer_filter.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ Future<VeilidConfig> getDefaultVeilidConfig() async {
|
||||
return VeilidConfig(
|
||||
programName: "Veilid Plugin Test",
|
||||
namespace: "",
|
||||
apiLogLevel: VeilidConfigLogLevel.info,
|
||||
capabilities: VeilidConfigCapabilities(
|
||||
protocolUDP: !kIsWeb,
|
||||
protocolConnectTCP: !kIsWeb,
|
||||
|
@ -59,7 +59,7 @@ VeilidConfigLogLevel convertToVeilidConfigLogLevel(LogLevel? level) {
|
||||
|
||||
void setRootLogLevel(LogLevel? level) {
|
||||
Loggy('').level = getLogOptions(level);
|
||||
Veilid.instance.changeApiLogLevel(convertToVeilidConfigLogLevel(level));
|
||||
Veilid.instance.changeLogLevel("all", convertToVeilidConfigLogLevel(level));
|
||||
}
|
||||
|
||||
void initLoggy() {
|
||||
@ -81,22 +81,26 @@ void main() {
|
||||
logging: VeilidWASMConfigLogging(
|
||||
performance: VeilidWASMConfigLoggingPerformance(
|
||||
enabled: true,
|
||||
level: VeilidLogLevel.trace,
|
||||
level: VeilidConfigLogLevel.debug,
|
||||
logsInTimings: true,
|
||||
logsInConsole: false)));
|
||||
logsInConsole: true),
|
||||
api: VeilidWASMConfigLoggingApi(
|
||||
enabled: true, level: VeilidConfigLogLevel.info)));
|
||||
Veilid.instance.configureVeilidPlatform(platformConfig.json);
|
||||
} else {
|
||||
var platformConfig = VeilidFFIConfig(
|
||||
logging: VeilidFFIConfigLogging(
|
||||
terminal: VeilidFFIConfigLoggingTerminal(
|
||||
enabled: false,
|
||||
level: VeilidLogLevel.trace,
|
||||
level: VeilidConfigLogLevel.debug,
|
||||
),
|
||||
otlp: VeilidFFIConfigLoggingOtlp(
|
||||
enabled: false,
|
||||
level: VeilidLogLevel.trace,
|
||||
level: VeilidConfigLogLevel.trace,
|
||||
grpcEndpoint: "localhost:4317",
|
||||
serviceName: "VeilidExample")));
|
||||
serviceName: "VeilidExample"),
|
||||
api: VeilidFFIConfigLoggingApi(
|
||||
enabled: true, level: VeilidConfigLogLevel.info)));
|
||||
Veilid.instance.configureVeilidPlatform(platformConfig.json);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import 'veilid_stub.dart'
|
||||
|
||||
class VeilidFFIConfigLoggingTerminal {
|
||||
bool enabled;
|
||||
VeilidLogLevel level;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidFFIConfigLoggingTerminal({
|
||||
required this.enabled,
|
||||
@ -29,12 +29,12 @@ class VeilidFFIConfigLoggingTerminal {
|
||||
|
||||
VeilidFFIConfigLoggingTerminal.fromJson(Map<String, dynamic> json)
|
||||
: enabled = json['enabled'],
|
||||
level = veilidLogLevelFromJson(json['level']);
|
||||
level = veilidConfigLogLevelFromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLoggingOtlp {
|
||||
bool enabled;
|
||||
VeilidLogLevel level;
|
||||
VeilidConfigLogLevel level;
|
||||
String grpcEndpoint;
|
||||
String serviceName;
|
||||
|
||||
@ -56,27 +56,52 @@ class VeilidFFIConfigLoggingOtlp {
|
||||
|
||||
VeilidFFIConfigLoggingOtlp.fromJson(Map<String, dynamic> json)
|
||||
: enabled = json['enabled'],
|
||||
level = veilidLogLevelFromJson(json['level']),
|
||||
level = veilidConfigLogLevelFromJson(json['level']),
|
||||
grpcEndpoint = json['grpc_endpoint'],
|
||||
serviceName = json['service_name'];
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLoggingApi {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidFFIConfigLoggingApi({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.json,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLoggingApi.fromJson(Map<String, dynamic> json)
|
||||
: enabled = json['enabled'],
|
||||
level = veilidConfigLogLevelFromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfigLogging {
|
||||
VeilidFFIConfigLoggingTerminal terminal;
|
||||
VeilidFFIConfigLoggingOtlp otlp;
|
||||
VeilidFFIConfigLoggingApi api;
|
||||
|
||||
VeilidFFIConfigLogging({required this.terminal, required this.otlp});
|
||||
VeilidFFIConfigLogging(
|
||||
{required this.terminal, required this.otlp, required this.api});
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'terminal': terminal.json,
|
||||
'otlp': otlp.json,
|
||||
'api': api.json,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidFFIConfigLogging.fromJson(Map<String, dynamic> json)
|
||||
: terminal = VeilidFFIConfigLoggingTerminal.fromJson(json['terminal']),
|
||||
otlp = VeilidFFIConfigLoggingOtlp.fromJson(json['otlp']);
|
||||
otlp = VeilidFFIConfigLoggingOtlp.fromJson(json['otlp']),
|
||||
api = VeilidFFIConfigLoggingApi.fromJson(json['api']);
|
||||
}
|
||||
|
||||
class VeilidFFIConfig {
|
||||
@ -101,7 +126,7 @@ class VeilidFFIConfig {
|
||||
|
||||
class VeilidWASMConfigLoggingPerformance {
|
||||
bool enabled;
|
||||
VeilidLogLevel level;
|
||||
VeilidConfigLogLevel level;
|
||||
bool logsInTimings;
|
||||
bool logsInConsole;
|
||||
|
||||
@ -123,25 +148,49 @@ class VeilidWASMConfigLoggingPerformance {
|
||||
|
||||
VeilidWASMConfigLoggingPerformance.fromJson(Map<String, dynamic> json)
|
||||
: enabled = json['enabled'],
|
||||
level = veilidLogLevelFromJson(json['level']),
|
||||
level = veilidConfigLogLevelFromJson(json['level']),
|
||||
logsInTimings = json['logs_in_timings'],
|
||||
logsInConsole = json['logs_in_console'];
|
||||
}
|
||||
|
||||
class VeilidWASMConfigLoggingApi {
|
||||
bool enabled;
|
||||
VeilidConfigLogLevel level;
|
||||
|
||||
VeilidWASMConfigLoggingApi({
|
||||
required this.enabled,
|
||||
required this.level,
|
||||
});
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'enabled': enabled,
|
||||
'level': level.json,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfigLoggingApi.fromJson(Map<String, dynamic> json)
|
||||
: enabled = json['enabled'],
|
||||
level = veilidConfigLogLevelFromJson(json['level']);
|
||||
}
|
||||
|
||||
class VeilidWASMConfigLogging {
|
||||
VeilidWASMConfigLoggingPerformance performance;
|
||||
VeilidWASMConfigLoggingApi api;
|
||||
|
||||
VeilidWASMConfigLogging({required this.performance});
|
||||
VeilidWASMConfigLogging({required this.performance, required this.api});
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'performance': performance.json,
|
||||
'api': api.json,
|
||||
};
|
||||
}
|
||||
|
||||
VeilidWASMConfigLogging.fromJson(Map<String, dynamic> json)
|
||||
: performance =
|
||||
VeilidWASMConfigLoggingPerformance.fromJson(json['performance']);
|
||||
VeilidWASMConfigLoggingPerformance.fromJson(json['performance']),
|
||||
api = VeilidWASMConfigLoggingApi.fromJson(json['api']);
|
||||
}
|
||||
|
||||
class VeilidWASMConfig {
|
||||
@ -899,7 +948,6 @@ class VeilidConfigCapabilities {
|
||||
class VeilidConfig {
|
||||
String programName;
|
||||
String namespace;
|
||||
VeilidConfigLogLevel apiLogLevel;
|
||||
VeilidConfigCapabilities capabilities;
|
||||
VeilidConfigProtectedStore protectedStore;
|
||||
VeilidConfigTableStore tableStore;
|
||||
@ -909,7 +957,6 @@ class VeilidConfig {
|
||||
VeilidConfig({
|
||||
required this.programName,
|
||||
required this.namespace,
|
||||
required this.apiLogLevel,
|
||||
required this.capabilities,
|
||||
required this.protectedStore,
|
||||
required this.tableStore,
|
||||
@ -921,7 +968,6 @@ class VeilidConfig {
|
||||
return {
|
||||
'program_name': programName,
|
||||
'namespace': namespace,
|
||||
'api_log_level': apiLogLevel.json,
|
||||
'capabilities': capabilities.json,
|
||||
'protected_store': protectedStore.json,
|
||||
'table_store': tableStore.json,
|
||||
@ -933,7 +979,6 @@ class VeilidConfig {
|
||||
VeilidConfig.fromJson(Map<String, dynamic> json)
|
||||
: programName = json['program_name'],
|
||||
namespace = json['namespace'],
|
||||
apiLogLevel = json['api_log_level'],
|
||||
capabilities = VeilidConfigCapabilities.fromJson(json['capabilities']),
|
||||
protectedStore =
|
||||
VeilidConfigProtectedStore.fromJson(json['protected_store']),
|
||||
@ -1253,9 +1298,9 @@ abstract class Veilid {
|
||||
static late Veilid instance = getVeilid();
|
||||
|
||||
void configureVeilidPlatform(Map<String, dynamic> platformConfigJson);
|
||||
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel);
|
||||
Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config);
|
||||
Future<VeilidState> getVeilidState();
|
||||
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel);
|
||||
Future<void> shutdownVeilidCore();
|
||||
Future<String> debug(String command);
|
||||
String veilidVersionString();
|
||||
|
@ -32,15 +32,15 @@ typedef _InitializeVeilidFlutterDart = void Function(Pointer<_DartPostCObject>);
|
||||
// fn configure_veilid_platform(platform_config: FfiStr)
|
||||
typedef _ConfigureVeilidPlatformC = Void Function(Pointer<Utf8>);
|
||||
typedef _ConfigureVeilidPlatformDart = void Function(Pointer<Utf8>);
|
||||
// fn change_log_level(layer: FfiStr, log_level: FfiStr)
|
||||
typedef _ChangeLogLevelC = Void Function(Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef _ChangeLogLevelDart = void Function(Pointer<Utf8>, Pointer<Utf8>);
|
||||
// fn startup_veilid_core(port: i64, config: FfiStr)
|
||||
typedef _StartupVeilidCoreC = Void Function(Int64, Pointer<Utf8>);
|
||||
typedef _StartupVeilidCoreDart = void Function(int, Pointer<Utf8>);
|
||||
// fn get_veilid_state(port: i64)
|
||||
typedef _GetVeilidStateC = Void Function(Int64);
|
||||
typedef _GetVeilidStateDart = void Function(int);
|
||||
// fn change_api_log_level(port: i64, log_level: FfiStr)
|
||||
typedef _ChangeApiLogLevelC = Void Function(Int64, Pointer<Utf8>);
|
||||
typedef _ChangeApiLogLevelDart = void Function(int, Pointer<Utf8>);
|
||||
// fn debug(port: i64, log_level: FfiStr)
|
||||
typedef _DebugC = Void Function(Int64, Pointer<Utf8>);
|
||||
typedef _DebugDart = void Function(int, Pointer<Utf8>);
|
||||
@ -246,9 +246,9 @@ class VeilidFFI implements Veilid {
|
||||
// Shared library functions
|
||||
final _FreeStringDart _freeString;
|
||||
final _ConfigureVeilidPlatformDart _configureVeilidPlatform;
|
||||
final _ChangeLogLevelDart _changeLogLevel;
|
||||
final _StartupVeilidCoreDart _startupVeilidCore;
|
||||
final _GetVeilidStateDart _getVeilidState;
|
||||
final _ChangeApiLogLevelDart _changeApiLogLevel;
|
||||
final _ShutdownVeilidCoreDart _shutdownVeilidCore;
|
||||
final _DebugDart _debug;
|
||||
final _VeilidVersionStringDart _veilidVersionString;
|
||||
@ -261,15 +261,15 @@ class VeilidFFI implements Veilid {
|
||||
_configureVeilidPlatform = dylib.lookupFunction<
|
||||
_ConfigureVeilidPlatformC,
|
||||
_ConfigureVeilidPlatformDart>('configure_veilid_platform'),
|
||||
_changeLogLevel =
|
||||
dylib.lookupFunction<_ChangeLogLevelC, _ChangeLogLevelDart>(
|
||||
'change_log_level'),
|
||||
_startupVeilidCore =
|
||||
dylib.lookupFunction<_StartupVeilidCoreC, _StartupVeilidCoreDart>(
|
||||
'startup_veilid_core'),
|
||||
_getVeilidState =
|
||||
dylib.lookupFunction<_GetVeilidStateC, _GetVeilidStateDart>(
|
||||
'get_veilid_state'),
|
||||
_changeApiLogLevel =
|
||||
dylib.lookupFunction<_ChangeApiLogLevelC, _ChangeApiLogLevelDart>(
|
||||
'change_api_log_level'),
|
||||
_shutdownVeilidCore =
|
||||
dylib.lookupFunction<_ShutdownVeilidCoreC, _ShutdownVeilidCoreDart>(
|
||||
'shutdown_veilid_core'),
|
||||
@ -297,6 +297,17 @@ class VeilidFFI implements Veilid {
|
||||
malloc.free(nativePlatformConfig);
|
||||
}
|
||||
|
||||
@override
|
||||
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) {
|
||||
var nativeLogLevel =
|
||||
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)
|
||||
.toNativeUtf8();
|
||||
var nativeLayer = layer.toNativeUtf8();
|
||||
_changeLogLevel(nativeLayer, nativeLogLevel);
|
||||
malloc.free(nativeLayer);
|
||||
malloc.free(nativeLogLevel);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config) {
|
||||
var nativeConfig =
|
||||
@ -317,18 +328,6 @@ class VeilidFFI implements Veilid {
|
||||
return processFutureJson(VeilidState.fromJson, recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel) async {
|
||||
var nativeLogLevel =
|
||||
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)
|
||||
.toNativeUtf8();
|
||||
final recvPort = ReceivePort("change_api_log_level");
|
||||
final sendPort = recvPort.sendPort;
|
||||
_changeApiLogLevel(sendPort.nativePort, nativeLogLevel);
|
||||
malloc.free(nativeLogLevel);
|
||||
return processFutureVoid(recvPort.first);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> shutdownVeilidCore() async {
|
||||
final recvPort = ReceivePort("shutdown_veilid_core");
|
||||
|
@ -27,6 +27,13 @@ class VeilidJS implements Veilid {
|
||||
wasm, "configure_veilid_platform", [platformConfigJsonString]);
|
||||
}
|
||||
|
||||
@override
|
||||
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) {
|
||||
var logLevelJsonString =
|
||||
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable);
|
||||
js_util.callMethod(wasm, "change_log_level", [layer, logLevelJsonString]);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config) async* {
|
||||
var streamController = StreamController<VeilidUpdate>();
|
||||
@ -53,12 +60,6 @@ class VeilidJS implements Veilid {
|
||||
js_util.callMethod(wasm, "get_veilid_state", []))));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel) {
|
||||
return _wrapApiPromise(js_util.callMethod(wasm, "change_api_log_level",
|
||||
[jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)]));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> shutdownVeilidCore() {
|
||||
return _wrapApiPromise(
|
||||
|
@ -7,7 +7,9 @@ use lazy_static::*;
|
||||
use opentelemetry::sdk::*;
|
||||
use opentelemetry::*;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
use parking_lot::Mutex;
|
||||
use serde::*;
|
||||
use std::collections::BTreeMap;
|
||||
use std::os::raw::c_char;
|
||||
use std::sync::Arc;
|
||||
use tracing::*;
|
||||
@ -15,9 +17,10 @@ use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::*;
|
||||
|
||||
// Globals
|
||||
|
||||
lazy_static! {
|
||||
static ref VEILID_API: AsyncMutex<Option<veilid_core::VeilidAPI>> = AsyncMutex::new(None);
|
||||
static ref FILTERS: Mutex<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>> =
|
||||
Mutex::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
async fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
@ -35,17 +38,6 @@ async fn take_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::Veilid
|
||||
.ok_or(veilid_core::VeilidAPIError::NotInitialized)
|
||||
}
|
||||
|
||||
fn logfilter<T: AsRef<str>, V: AsRef<[T]>>(metadata: &Metadata, ignore_list: V) -> bool {
|
||||
// Skip filtered targets
|
||||
!match (metadata.target(), ignore_list.as_ref()) {
|
||||
(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.as_ref()))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
// FFI Helpers
|
||||
|
||||
@ -75,21 +67,28 @@ macro_rules! check_err_json {
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidFFIConfigLoggingTerminal {
|
||||
pub enabled: bool,
|
||||
pub level: veilid_core::VeilidLogLevel,
|
||||
pub level: veilid_core::VeilidConfigLogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidFFIConfigLoggingOtlp {
|
||||
pub enabled: bool,
|
||||
pub level: veilid_core::VeilidLogLevel,
|
||||
pub level: veilid_core::VeilidConfigLogLevel,
|
||||
pub grpc_endpoint: String,
|
||||
pub service_name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidFFIConfigLoggingApi {
|
||||
pub enabled: bool,
|
||||
pub level: veilid_core::VeilidConfigLogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidFFIConfigLogging {
|
||||
pub terminal: VeilidFFIConfigLoggingTerminal,
|
||||
pub otlp: VeilidFFIConfigLoggingOtlp,
|
||||
pub api: VeilidFFIConfigLoggingApi,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
@ -149,40 +148,24 @@ pub extern "C" fn configure_veilid_platform(platform_config: FfiStr) {
|
||||
.expect("failed to deserialize plaform config json");
|
||||
|
||||
// Set up subscriber and layers
|
||||
let mut ignore_list = Vec::<String>::new();
|
||||
for ig in veilid_core::DEFAULT_LOG_IGNORE_LIST {
|
||||
ignore_list.push(ig.to_owned());
|
||||
}
|
||||
|
||||
let subscriber = Registry::default();
|
||||
let mut layers = Vec::new();
|
||||
let mut filters = (*FILTERS).lock();
|
||||
|
||||
// Terminal logger
|
||||
let subscriber = subscriber.with(if platform_config.logging.terminal.enabled {
|
||||
let terminal_max_log_level: level_filters::LevelFilter = platform_config
|
||||
.logging
|
||||
.terminal
|
||||
.level
|
||||
.to_tracing_level()
|
||||
.into();
|
||||
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(std::io::stdout)
|
||||
.with_filter(terminal_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
if platform_config.logging.terminal.enabled {
|
||||
let filter =
|
||||
veilid_core::VeilidLayerFilter::new(platform_config.logging.terminal.level, None);
|
||||
let layer = fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(std::io::stdout)
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("terminal", filter);
|
||||
layers.push(layer.boxed());
|
||||
};
|
||||
|
||||
// OpenTelemetry logger
|
||||
let subscriber = subscriber.with(if platform_config.logging.otlp.enabled {
|
||||
let otlp_max_log_level: level_filters::LevelFilter =
|
||||
platform_config.logging.otlp.level.to_tracing_level().into();
|
||||
if platform_config.logging.otlp.enabled {
|
||||
let grpc_endpoint = platform_config.logging.otlp.grpc_endpoint.clone();
|
||||
|
||||
cfg_if! {
|
||||
@ -218,21 +201,23 @@ pub extern "C" fn configure_veilid_platform(platform_config: FfiStr) {
|
||||
.map_err(|e| format!("failed to install OpenTelemetry tracer: {}", e))
|
||||
.unwrap();
|
||||
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
tracing_opentelemetry::layer()
|
||||
.with_tracer(tracer)
|
||||
.with_filter(otlp_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let filter = veilid_core::VeilidLayerFilter::new(platform_config.logging.otlp.level, None);
|
||||
let layer = tracing_opentelemetry::layer()
|
||||
.with_tracer(tracer)
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("otlp", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
// API logger (always add layer, startup will init this if it is enabled in settings)
|
||||
let subscriber = subscriber.with(veilid_core::ApiTracingLayer::get());
|
||||
// API logger
|
||||
if platform_config.logging.api.enabled {
|
||||
let filter = veilid_core::VeilidLayerFilter::new(platform_config.logging.api.level, None);
|
||||
let layer = veilid_core::ApiTracingLayer::get().with_filter(filter.clone());
|
||||
filters.insert("api", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
let subscriber = subscriber.with(layers);
|
||||
|
||||
subscriber
|
||||
.try_init()
|
||||
@ -240,6 +225,32 @@ pub extern "C" fn configure_veilid_platform(platform_config: FfiStr) {
|
||||
.expect("failed to initalize ffi platform");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[instrument(level = "debug")]
|
||||
pub extern "C" fn change_log_level(layer: FfiStr, log_level: FfiStr) {
|
||||
// get layer to change level on
|
||||
let layer = layer.into_opt_string().unwrap_or("all".to_owned());
|
||||
let layer = if layer == "all" { "".to_owned() } else { layer };
|
||||
|
||||
// get log level to change layer to
|
||||
let log_level = log_level.into_opt_string();
|
||||
let log_level: veilid_core::VeilidConfigLogLevel =
|
||||
veilid_core::deserialize_opt_json(log_level).unwrap();
|
||||
|
||||
// change log level on appropriate layer
|
||||
let filters = (*FILTERS).lock();
|
||||
if layer.is_empty() {
|
||||
// Change all layers
|
||||
for f in filters.values() {
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
} else {
|
||||
// Change a specific layer
|
||||
let f = filters.get(layer.as_str()).unwrap();
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[instrument]
|
||||
pub extern "C" fn startup_veilid_core(port: i64, config: FfiStr) {
|
||||
@ -291,20 +302,6 @@ pub extern "C" fn get_veilid_state(port: i64) {
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[instrument(level = "debug")]
|
||||
pub extern "C" fn change_api_log_level(port: i64, log_level: FfiStr) {
|
||||
let log_level = log_level.into_opt_string();
|
||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||
let log_level: veilid_core::VeilidConfigLogLevel =
|
||||
veilid_core::deserialize_opt_json(log_level)?;
|
||||
//let veilid_api = get_veilid_api().await?;
|
||||
//veilid_api.change_api_log_level(log_level).await;
|
||||
veilid_core::ApiTracingLayer::change_api_log_level(log_level.to_veilid_log_level());
|
||||
APIRESULT_VOID
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[instrument]
|
||||
pub extern "C" fn shutdown_veilid_core(port: i64) {
|
||||
|
@ -36,7 +36,6 @@ capnp = "^0"
|
||||
parking_lot = "^0"
|
||||
capnp-rpc = "^0"
|
||||
config = { version = "^0", features = ["yaml"] }
|
||||
failure = "^0"
|
||||
cfg-if = "^1"
|
||||
serde = "^1"
|
||||
serde_derive = "^1"
|
||||
|
@ -1,20 +1,24 @@
|
||||
@0xd29582d26b2fb073;
|
||||
|
||||
struct ApiResult {
|
||||
union {
|
||||
ok @0 :Text;
|
||||
err @1 :Text;
|
||||
}
|
||||
}
|
||||
|
||||
interface Registration {}
|
||||
|
||||
interface VeilidServer {
|
||||
|
||||
register @0 (veilidClient: VeilidClient) -> (registration: Registration, state: Text);
|
||||
debug @1 (what: Text) -> (output: Text);
|
||||
|
||||
attach @2 ();
|
||||
detach @3 ();
|
||||
debug @1 (command: Text) -> (result :ApiResult);
|
||||
attach @2 () -> (result :ApiResult);
|
||||
detach @3 () -> (result :ApiResult);
|
||||
shutdown @4 ();
|
||||
getState @5 () -> (state: Text);
|
||||
getState @5 () -> (result :ApiResult);
|
||||
changeLogLevel @6 (layer: Text, logLevel: Text) -> (result :ApiResult);
|
||||
}
|
||||
|
||||
interface VeilidClient {
|
||||
|
||||
update @0 (veilidUpdate: Text);
|
||||
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
use crate::tools::*;
|
||||
use crate::veilid_client_capnp::*;
|
||||
use crate::veilid_logs::VeilidLogs;
|
||||
use capnp::capability::Promise;
|
||||
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, RpcSystem};
|
||||
use cfg_if::*;
|
||||
use failure::*;
|
||||
use futures_util::{future::try_join_all, FutureExt as FuturesFutureExt, StreamExt};
|
||||
use serde::*;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
use stop_token::future::FutureExt;
|
||||
@ -14,9 +16,20 @@ use stop_token::*;
|
||||
use tracing::*;
|
||||
use veilid_core::*;
|
||||
|
||||
#[derive(Fail, Debug)]
|
||||
#[fail(display = "Client API error: {}", _0)]
|
||||
pub struct ClientAPIError(String);
|
||||
// Encoding for ApiResult
|
||||
fn encode_api_result<T: Serialize + fmt::Debug>(
|
||||
result: &Result<T, VeilidAPIError>,
|
||||
builder: &mut api_result::Builder,
|
||||
) {
|
||||
match result {
|
||||
Ok(v) => {
|
||||
builder.set_ok(&serialize_json(v));
|
||||
}
|
||||
Err(e) => {
|
||||
builder.set_err(&serialize_json(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- interface Registration ---------------------------------
|
||||
|
||||
@ -67,17 +80,19 @@ impl registration::Server for RegistrationImpl {}
|
||||
|
||||
struct VeilidServerImpl {
|
||||
veilid_api: veilid_core::VeilidAPI,
|
||||
veilid_logs: VeilidLogs,
|
||||
next_id: u64,
|
||||
pub registration_map: Rc<RefCell<RegistrationMap>>,
|
||||
}
|
||||
|
||||
impl VeilidServerImpl {
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub fn new(veilid_api: veilid_core::VeilidAPI) -> Self {
|
||||
pub fn new(veilid_api: veilid_core::VeilidAPI, veilid_logs: VeilidLogs) -> Self {
|
||||
Self {
|
||||
next_id: 0,
|
||||
registration_map: Rc::new(RefCell::new(RegistrationMap::new())),
|
||||
veilid_api,
|
||||
veilid_logs,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,13 +130,7 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
|
||||
let mut res = results.get();
|
||||
res.set_registration(registration);
|
||||
let mut rpc_state = res.init_state(
|
||||
state
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?,
|
||||
);
|
||||
rpc_state.push_str(&state);
|
||||
res.set_state(&state);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@ -135,14 +144,11 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
trace!("VeilidServerImpl::debug");
|
||||
let veilid_api = self.veilid_api.clone();
|
||||
let what = pry!(pry!(params.get()).get_what()).to_owned();
|
||||
let command = pry!(pry!(params.get()).get_command()).to_owned();
|
||||
|
||||
Promise::from_future(async move {
|
||||
let output = veilid_api
|
||||
.debug(what)
|
||||
.await
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
||||
results.get().set_output(output.as_str());
|
||||
let result = veilid_api.debug(command).await;
|
||||
encode_api_result(&result, &mut results.get().init_result());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -151,15 +157,14 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
fn attach(
|
||||
&mut self,
|
||||
_params: veilid_server::AttachParams,
|
||||
mut _results: veilid_server::AttachResults,
|
||||
mut results: veilid_server::AttachResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
trace!("VeilidServerImpl::attach");
|
||||
let veilid_api = self.veilid_api.clone();
|
||||
Promise::from_future(async move {
|
||||
veilid_api
|
||||
.attach()
|
||||
.await
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
||||
let result = veilid_api.attach().await;
|
||||
encode_api_result(&result, &mut results.get().init_result());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
@ -167,15 +172,14 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
fn detach(
|
||||
&mut self,
|
||||
_params: veilid_server::DetachParams,
|
||||
mut _results: veilid_server::DetachResults,
|
||||
mut results: veilid_server::DetachResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
trace!("VeilidServerImpl::detach");
|
||||
let veilid_api = self.veilid_api.clone();
|
||||
Promise::from_future(async move {
|
||||
veilid_api
|
||||
.detach()
|
||||
.await
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
|
||||
let result = veilid_api.detach().await;
|
||||
encode_api_result(&result, &mut results.get().init_result());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
@ -208,24 +212,30 @@ impl veilid_server::Server for VeilidServerImpl {
|
||||
trace!("VeilidServerImpl::get_state");
|
||||
let veilid_api = self.veilid_api.clone();
|
||||
Promise::from_future(async move {
|
||||
let state = veilid_api
|
||||
.get_state()
|
||||
.await
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
|
||||
let state = serialize_json(state);
|
||||
|
||||
let res = results.get();
|
||||
let mut rpc_state = res.init_state(
|
||||
state
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?,
|
||||
);
|
||||
rpc_state.push_str(&state);
|
||||
|
||||
let result = veilid_api.get_state().await;
|
||||
encode_api_result(&result, &mut results.get().init_result());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
fn change_log_level(
|
||||
&mut self,
|
||||
params: veilid_server::ChangeLogLevelParams,
|
||||
mut results: veilid_server::ChangeLogLevelResults,
|
||||
) -> Promise<(), ::capnp::Error> {
|
||||
trace!("VeilidServerImpl::change_log_level");
|
||||
|
||||
let layer = pry!(pry!(params.get()).get_layer()).to_owned();
|
||||
let log_level_json = pry!(pry!(params.get()).get_log_level()).to_owned();
|
||||
let log_level: veilid_core::VeilidConfigLogLevel =
|
||||
pry!(veilid_core::deserialize_json(&log_level_json)
|
||||
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e))));
|
||||
|
||||
let result = self.veilid_logs.change_log_level(layer, log_level);
|
||||
encode_api_result(&result, &mut results.get().init_result());
|
||||
Promise::ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// --- Client API Server-Side ---------------------------------
|
||||
@ -235,6 +245,7 @@ type ClientApiAllFuturesJoinHandle =
|
||||
|
||||
struct ClientApiInner {
|
||||
veilid_api: veilid_core::VeilidAPI,
|
||||
veilid_logs: VeilidLogs,
|
||||
registration_map: Rc<RefCell<RegistrationMap>>,
|
||||
stop: Option<StopSource>,
|
||||
join_handle: Option<ClientApiAllFuturesJoinHandle>,
|
||||
@ -246,10 +257,11 @@ pub struct ClientApi {
|
||||
|
||||
impl ClientApi {
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
pub fn new(veilid_api: veilid_core::VeilidAPI) -> Rc<Self> {
|
||||
pub fn new(veilid_api: veilid_core::VeilidAPI, veilid_logs: VeilidLogs) -> Rc<Self> {
|
||||
Rc::new(Self {
|
||||
inner: RefCell::new(ClientApiInner {
|
||||
veilid_api,
|
||||
veilid_logs,
|
||||
registration_map: Rc::new(RefCell::new(RegistrationMap::new())),
|
||||
stop: Some(StopSource::new()),
|
||||
join_handle: None,
|
||||
@ -393,7 +405,10 @@ impl ClientApi {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
pub fn run(self: Rc<Self>, bind_addrs: Vec<SocketAddr>) {
|
||||
// Create client api VeilidServer
|
||||
let veilid_server_impl = VeilidServerImpl::new(self.inner.borrow().veilid_api.clone());
|
||||
let veilid_server_impl = VeilidServerImpl::new(
|
||||
self.inner.borrow().veilid_api.clone(),
|
||||
self.inner.borrow().veilid_logs.clone(),
|
||||
);
|
||||
self.inner.borrow_mut().registration_map = veilid_server_impl.registration_map.clone();
|
||||
|
||||
// Make a client object for the server to send to each rpc client
|
||||
|
@ -62,9 +62,9 @@ fn main() -> Result<(), String> {
|
||||
// run the server to set the node id and quit
|
||||
return block_on(async {
|
||||
// Init combined console/file logger
|
||||
let _logs = VeilidLogs::setup(settings.clone())?;
|
||||
let veilid_logs = VeilidLogs::setup(settings.clone())?;
|
||||
|
||||
run_veilid_server(settings, server_mode).await
|
||||
run_veilid_server(settings, server_mode, veilid_logs).await
|
||||
})
|
||||
.map(|v| {
|
||||
println!("{}", success);
|
||||
@ -96,8 +96,8 @@ fn main() -> Result<(), String> {
|
||||
// Run the server loop
|
||||
block_on(async {
|
||||
// Init combined console/file logger
|
||||
let _logs = VeilidLogs::setup(settings.clone())?;
|
||||
let veilid_logs = VeilidLogs::setup(settings.clone())?;
|
||||
|
||||
run_veilid_server(settings, server_mode).await
|
||||
run_veilid_server(settings, server_mode, veilid_logs).await
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::client_api;
|
||||
use crate::settings::*;
|
||||
use crate::tools::*;
|
||||
use crate::veilid_logs::*;
|
||||
use flume::{unbounded, Receiver, Sender};
|
||||
use lazy_static::*;
|
||||
use parking_lot::Mutex;
|
||||
@ -29,14 +30,19 @@ pub fn shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_veilid_server(settings: Settings, server_mode: ServerMode) -> Result<(), String> {
|
||||
run_veilid_server_internal(settings, server_mode).await
|
||||
pub async fn run_veilid_server(
|
||||
settings: Settings,
|
||||
server_mode: ServerMode,
|
||||
veilid_logs: VeilidLogs,
|
||||
) -> Result<(), String> {
|
||||
run_veilid_server_internal(settings, server_mode, veilid_logs).await
|
||||
}
|
||||
|
||||
#[instrument(err, skip_all)]
|
||||
pub async fn run_veilid_server_internal(
|
||||
settings: Settings,
|
||||
server_mode: ServerMode,
|
||||
veilid_logs: VeilidLogs,
|
||||
) -> Result<(), String> {
|
||||
trace!(?settings, ?server_mode);
|
||||
|
||||
@ -63,7 +69,7 @@ pub async fn run_veilid_server_internal(
|
||||
|
||||
// Start client api if one is requested
|
||||
let mut capi = if settingsr.client_api.enabled && matches!(server_mode, ServerMode::Normal) {
|
||||
let some_capi = client_api::ClientApi::new(veilid_api.clone());
|
||||
let some_capi = client_api::ClientApi::new(veilid_api.clone(), veilid_logs.clone());
|
||||
some_capi
|
||||
.clone()
|
||||
.run(settingsr.client_api.listen_address.addrs.clone());
|
||||
@ -156,5 +162,9 @@ pub async fn run_veilid_server_internal(
|
||||
// Wait for update receiver to exit
|
||||
let _ = update_receiver_jh.await;
|
||||
|
||||
// Finally, drop logs
|
||||
// this is explicit to ensure we don't accidentally drop them too soon via a move
|
||||
drop(veilid_logs);
|
||||
|
||||
out
|
||||
}
|
||||
|
@ -192,6 +192,7 @@ pub fn load_config(
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum LogLevel {
|
||||
Off,
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
@ -205,6 +206,7 @@ impl<'de> serde::Deserialize<'de> for LogLevel {
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
match s.to_ascii_lowercase().as_str() {
|
||||
"off" => Ok(LogLevel::Off),
|
||||
"error" => Ok(LogLevel::Error),
|
||||
"warn" => Ok(LogLevel::Warn),
|
||||
"info" => Ok(LogLevel::Info),
|
||||
@ -223,6 +225,7 @@ impl serde::Serialize for LogLevel {
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let s = match self {
|
||||
LogLevel::Off => "off",
|
||||
LogLevel::Error => "error",
|
||||
LogLevel::Warn => "warn",
|
||||
LogLevel::Info => "info",
|
||||
@ -233,13 +236,14 @@ impl serde::Serialize for LogLevel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_loglevel(log_level: LogLevel) -> veilid_core::VeilidLogLevel {
|
||||
pub fn convert_loglevel(log_level: LogLevel) -> veilid_core::VeilidConfigLogLevel {
|
||||
match log_level {
|
||||
LogLevel::Error => veilid_core::VeilidLogLevel::Error,
|
||||
LogLevel::Warn => veilid_core::VeilidLogLevel::Warn,
|
||||
LogLevel::Info => veilid_core::VeilidLogLevel::Info,
|
||||
LogLevel::Debug => veilid_core::VeilidLogLevel::Debug,
|
||||
LogLevel::Trace => veilid_core::VeilidLogLevel::Trace,
|
||||
LogLevel::Off => veilid_core::VeilidConfigLogLevel::Off,
|
||||
LogLevel::Error => veilid_core::VeilidConfigLogLevel::Error,
|
||||
LogLevel::Warn => veilid_core::VeilidConfigLogLevel::Warn,
|
||||
LogLevel::Info => veilid_core::VeilidConfigLogLevel::Info,
|
||||
LogLevel::Debug => veilid_core::VeilidConfigLogLevel::Debug,
|
||||
LogLevel::Trace => veilid_core::VeilidConfigLogLevel::Trace,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1016,13 +1020,6 @@ impl Settings {
|
||||
} else {
|
||||
format!("subnode{}", inner.testing.subnode_index)
|
||||
})),
|
||||
"api_log_level" => Ok(Box::new(if inner.logging.api.enabled {
|
||||
veilid_core::VeilidConfigLogLevel::from_veilid_log_level(Some(
|
||||
convert_loglevel(inner.logging.api.level),
|
||||
))
|
||||
} else {
|
||||
veilid_core::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)),
|
||||
|
@ -98,7 +98,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
|
||||
// Now, run the server
|
||||
block_on(async {
|
||||
// Init combined console/file logger
|
||||
let _logs = VeilidLogs::setup(settings.clone())?;
|
||||
let veilid_logs = VeilidLogs::setup(settings.clone())?;
|
||||
|
||||
// Daemonize
|
||||
daemon
|
||||
@ -112,7 +112,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
|
||||
|
||||
let signals_task = spawn(handle_signals(signals));
|
||||
|
||||
let res = run_veilid_server(settings, ServerMode::Normal).await;
|
||||
let res = run_veilid_server(settings, ServerMode::Normal, veilid_logs).await;
|
||||
|
||||
// Terminate the signal stream.
|
||||
handle.close();
|
||||
|
@ -3,25 +3,22 @@ use cfg_if::*;
|
||||
use opentelemetry::sdk::*;
|
||||
use opentelemetry::*;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
use parking_lot::*;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::*;
|
||||
use tracing::*;
|
||||
use std::sync::Arc;
|
||||
use tracing_appender::*;
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::*;
|
||||
|
||||
pub struct VeilidLogs {
|
||||
pub guard: Option<non_blocking::WorkerGuard>,
|
||||
struct VeilidLogsInner {
|
||||
_guard: Option<non_blocking::WorkerGuard>,
|
||||
filters: BTreeMap<&'static str, veilid_core::VeilidLayerFilter>,
|
||||
}
|
||||
|
||||
fn logfilter<T: AsRef<str>, V: AsRef<[T]>>(metadata: &Metadata, ignore_list: V) -> bool {
|
||||
// Skip filtered targets
|
||||
!match (metadata.target(), ignore_list.as_ref()) {
|
||||
(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.as_ref()))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct VeilidLogs {
|
||||
inner: Arc<Mutex<VeilidLogsInner>>,
|
||||
}
|
||||
|
||||
impl VeilidLogs {
|
||||
@ -29,39 +26,26 @@ impl VeilidLogs {
|
||||
let settingsr = settings.read();
|
||||
|
||||
// Set up subscriber and layers
|
||||
let mut ignore_list = Vec::<String>::new();
|
||||
for ig in veilid_core::DEFAULT_LOG_IGNORE_LIST {
|
||||
ignore_list.push(ig.to_owned());
|
||||
}
|
||||
|
||||
let subscriber = Registry::default();
|
||||
let mut layers = Vec::new();
|
||||
let mut filters = BTreeMap::new();
|
||||
|
||||
// Terminal logger
|
||||
let subscriber = subscriber.with(if settingsr.logging.terminal.enabled {
|
||||
let terminal_max_log_level: level_filters::LevelFilter =
|
||||
convert_loglevel(settingsr.logging.terminal.level)
|
||||
.to_tracing_level()
|
||||
.into();
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(std::io::stdout)
|
||||
.with_filter(terminal_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
if settingsr.logging.terminal.enabled {
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.terminal.level),
|
||||
None,
|
||||
);
|
||||
let layer = fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(std::io::stdout)
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("terminal", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
// OpenTelemetry logger
|
||||
let subscriber = subscriber.with(if settingsr.logging.otlp.enabled {
|
||||
let otlp_max_log_level: level_filters::LevelFilter =
|
||||
convert_loglevel(settingsr.logging.otlp.level)
|
||||
.to_tracing_level()
|
||||
.into();
|
||||
if settingsr.logging.otlp.enabled {
|
||||
let grpc_endpoint = settingsr.logging.otlp.grpc_endpoint.name.clone();
|
||||
|
||||
cfg_if! {
|
||||
@ -95,27 +79,20 @@ impl VeilidLogs {
|
||||
.install_batch(batch)
|
||||
.map_err(|e| format!("failed to install OpenTelemetry tracer: {}", e))?;
|
||||
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
tracing_opentelemetry::layer()
|
||||
.with_tracer(tracer)
|
||||
.with_filter(otlp_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.otlp.level),
|
||||
None,
|
||||
);
|
||||
let layer = tracing_opentelemetry::layer()
|
||||
.with_tracer(tracer)
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("otlp", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
// File logger
|
||||
let mut guard = None;
|
||||
let subscriber = subscriber.with(if settingsr.logging.file.enabled {
|
||||
let file_max_log_level: level_filters::LevelFilter =
|
||||
convert_loglevel(settingsr.logging.file.level)
|
||||
.to_tracing_level()
|
||||
.into();
|
||||
|
||||
if settingsr.logging.file.enabled {
|
||||
let log_path = Path::new(&settingsr.logging.file.path);
|
||||
let full_path = std::env::current_dir()
|
||||
.unwrap_or(PathBuf::from(MAIN_SEPARATOR.to_string()))
|
||||
@ -140,50 +117,88 @@ impl VeilidLogs {
|
||||
tracing_appender::non_blocking(appender);
|
||||
guard = Some(non_blocking_guard);
|
||||
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(non_blocking_appender)
|
||||
.with_filter(file_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.file.level),
|
||||
None,
|
||||
);
|
||||
let layer = fmt::Layer::new()
|
||||
.compact()
|
||||
.with_writer(non_blocking_appender)
|
||||
.with_filter(filter.clone());
|
||||
|
||||
filters.insert("file", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
// API logger
|
||||
let subscriber = subscriber.with(if settingsr.logging.api.enabled {
|
||||
// Get layer from veilid core, filtering is done by ApiTracingLayer automatically
|
||||
Some(veilid_core::ApiTracingLayer::get())
|
||||
} else {
|
||||
None
|
||||
});
|
||||
if settingsr.logging.api.enabled {
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.api.level),
|
||||
None,
|
||||
);
|
||||
let layer = veilid_core::ApiTracingLayer::get().with_filter(filter.clone());
|
||||
filters.insert("api", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
// Systemd Journal logger
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
let subscriber = subscriber.with(if settingsr.logging.system.enabled {
|
||||
let ignore_list = ignore_list.clone();
|
||||
let system_max_log_level: level_filters::LevelFilter = convert_loglevel(settingsr.logging.system.level).to_tracing_level().into();
|
||||
Some(tracing_journald::layer().map_err(|e| format!("failed to set up journald logging: {}", e))?
|
||||
.with_filter(system_max_log_level)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
}))
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
if settingsr.logging.system.enabled {
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.system.level),
|
||||
None,
|
||||
);
|
||||
let layer =tracing_journald::layer().map_err(|e| format!("failed to set up journald logging: {}", e))?
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("system", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let subscriber = subscriber.with(layers);
|
||||
subscriber
|
||||
.try_init()
|
||||
.map_err(|e| format!("failed to initialize logging: {}", e))?;
|
||||
|
||||
Ok(VeilidLogs { guard })
|
||||
Ok(VeilidLogs {
|
||||
inner: Arc::new(Mutex::new(VeilidLogsInner {
|
||||
_guard: guard,
|
||||
filters,
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn change_log_level(
|
||||
&self,
|
||||
layer: String,
|
||||
log_level: veilid_core::VeilidConfigLogLevel,
|
||||
) -> Result<(), veilid_core::VeilidAPIError> {
|
||||
// get layer to change level on
|
||||
let layer = if layer == "all" { "".to_owned() } else { layer };
|
||||
|
||||
// change log level on appropriate layer
|
||||
let inner = self.inner.lock();
|
||||
if layer.is_empty() {
|
||||
// Change all layers
|
||||
for f in inner.filters.values() {
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
} else {
|
||||
// Change a specific layer
|
||||
let f = match inner.filters.get(layer.as_str()) {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
return Err(veilid_core::VeilidAPIError::InvalidArgument {
|
||||
context: "change_log_level".to_owned(),
|
||||
argument: "layer".to_owned(),
|
||||
value: layer,
|
||||
});
|
||||
}
|
||||
};
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -32,22 +32,12 @@ pub fn setup() -> () {
|
||||
SETUP_ONCE.call_once(|| {});
|
||||
}
|
||||
|
||||
// Log filtering
|
||||
fn logfilter<T: AsRef<str>, V: AsRef<[T]>>(metadata: &Metadata, ignore_list: V) -> bool {
|
||||
// Skip filtered targets
|
||||
!match (metadata.target(), ignore_list.as_ref()) {
|
||||
(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.as_ref()))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// API Singleton
|
||||
lazy_static! {
|
||||
static ref VEILID_API: SendWrapper<RefCell<Option<veilid_core::VeilidAPI>>> =
|
||||
SendWrapper::new(RefCell::new(None));
|
||||
static ref FILTERS: SendWrapper<RefCell<BTreeMap<&'static str, veilid_core::VeilidLayerFilter>>> =
|
||||
SendWrapper::new(RefCell::new(BTreeMap::new()));
|
||||
}
|
||||
|
||||
fn get_veilid_api() -> Result<veilid_core::VeilidAPI, veilid_core::VeilidAPIError> {
|
||||
@ -123,9 +113,16 @@ pub struct VeilidWASMConfigLoggingPerformance {
|
||||
pub logs_in_console: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidWASMConfigLoggingAPI {
|
||||
pub enabled: bool,
|
||||
pub level: veilid_core::VeilidLogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct VeilidWASMConfigLogging {
|
||||
pub performance: VeilidWASMConfigLoggingPerformance,
|
||||
pub api: VeilidWASMConfigLoggingAPI,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
@ -146,48 +143,61 @@ pub fn configure_veilid_platform(platform_config: String) {
|
||||
.expect("failed to deserialize plaform config json");
|
||||
|
||||
// Set up subscriber and layers
|
||||
let mut ignore_list = Vec::<String>::new();
|
||||
for ig in veilid_core::DEFAULT_LOG_IGNORE_LIST {
|
||||
ignore_list.push(ig.to_owned());
|
||||
}
|
||||
|
||||
let subscriber = Registry::default();
|
||||
let mut layers = Vec::new();
|
||||
let handles = (*FILTER_RELOAD_HANDLES).borrow_mut();
|
||||
|
||||
// Performance logger
|
||||
let subscriber = subscriber.with(if platform_config.logging.performance.enabled {
|
||||
let performance_max_log_level =
|
||||
platform_config.logging.performance.level.to_tracing_level();
|
||||
|
||||
let ignore_list = ignore_list.clone();
|
||||
Some(
|
||||
WASMLayer::new(
|
||||
WASMLayerConfigBuilder::new()
|
||||
.set_report_logs_in_timings(platform_config.logging.performance.logs_in_timings)
|
||||
.set_console_config(if platform_config.logging.performance.logs_in_console {
|
||||
ConsoleConfig::ReportWithConsoleColor
|
||||
} else {
|
||||
ConsoleConfig::NoReporting
|
||||
})
|
||||
.set_max_level(performance_max_log_level)
|
||||
.build(),
|
||||
)
|
||||
.with_filter(filter::FilterFn::new(move |metadata| {
|
||||
logfilter(metadata, &ignore_list)
|
||||
})),
|
||||
if platform_config.logging.performance.enabled {
|
||||
let filter =
|
||||
veilid_core::VeilidLayerFilter::new(platform_config.logging.performance.level, None);
|
||||
let layer = WASMLayer::new(
|
||||
WASMLayerConfigBuilder::new()
|
||||
.set_report_logs_in_timings(platform_config.logging.performance.logs_in_timings)
|
||||
.set_console_config(if platform_config.logging.performance.logs_in_console {
|
||||
ConsoleConfig::ReportWithConsoleColor
|
||||
} else {
|
||||
ConsoleConfig::NoReporting
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
.with_filter(filter.clone());
|
||||
handles.insert("performance", filter);
|
||||
layers.push(layer.boxed());
|
||||
};
|
||||
|
||||
// API logger (always add layer, startup will init this if it is enabled in settings)
|
||||
let subscriber = subscriber.with(veilid_core::ApiTracingLayer::get());
|
||||
// API logger
|
||||
if platform_config.logging.api.enabled {
|
||||
let filter = veilid_core::VeilidLayerFilter::new(platform_config.logging.api.level, None);
|
||||
let layer = veilid_core::ApiTracingLayer::get().with_filter(filter.clone());
|
||||
handles.insert("api", filter);
|
||||
layers.push(layer.boxed());
|
||||
}
|
||||
|
||||
let subscriber = subscriber.with(layers);
|
||||
subscriber
|
||||
.try_init()
|
||||
.map_err(|e| format!("failed to initialize logging: {}", e))
|
||||
.expect("failed to initalize WASM platform");
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn change_log_level(layer: String, log_level: String) {
|
||||
let layer = if layer == "all" { "".to_owned() } else { layer };
|
||||
let log_level: veilid_core::VeilidConfigLogLevel = deserialize_json(&log_level).unwrap();
|
||||
let filters = (*FILTERS).borrow();
|
||||
if layer.is_empty() {
|
||||
// Change all layers
|
||||
for f in filters.values() {
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
} else {
|
||||
// Change a specific layer
|
||||
let f = filters.get(layer.as_str()).unwrap();
|
||||
f.set_max_level(log_level);
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn startup_veilid_core(update_callback: Function, json_config: String) -> Promise {
|
||||
wrap_api_future(async move {
|
||||
@ -221,17 +231,6 @@ pub fn get_veilid_state() -> Promise {
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn change_api_log_level(log_level: String) -> Promise {
|
||||
wrap_api_future(async move {
|
||||
let log_level: veilid_core::VeilidConfigLogLevel = deserialize_json(&log_level)?;
|
||||
//let veilid_api = get_veilid_api()?;
|
||||
//veilid_api.change_api_log_level(log_level).await;
|
||||
veilid_core::ApiTracingLayer::change_api_log_level(log_level.to_veilid_log_level());
|
||||
APIRESULT_UNDEFINED
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen()]
|
||||
pub fn shutdown_veilid_core() -> Promise {
|
||||
wrap_api_future(async move {
|
||||
|
Loading…
Reference in New Issue
Block a user