refactor checkpoint

This commit is contained in:
John Smith 2022-06-07 21:31:05 -04:00
parent 182af30b97
commit 1d8c63786a
28 changed files with 822 additions and 626 deletions

288
Cargo.lock generated
View File

@ -131,14 +131,20 @@ dependencies = [
"log",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
dependencies = [
"backtrace",
]
[[package]]
name = "arraydeque"
@ -738,7 +744,7 @@ dependencies = [
"libc",
"num-integer",
"num-traits 0.2.14",
"time",
"time 0.1.43",
"winapi",
]
@ -795,6 +801,33 @@ dependencies = [
"bitflags",
]
[[package]]
name = "color-eyre"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90"
dependencies = [
"backtrace",
"color-spantrace",
"eyre",
"indenter",
"once_cell",
"owo-colors",
"tracing-error",
]
[[package]]
name = "color-spantrace"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
dependencies = [
"once_cell",
"owo-colors",
"tracing-core",
"tracing-error",
]
[[package]]
name = "combine"
version = "4.6.3"
@ -1274,7 +1307,6 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer 0.10.2",
"crypto-common",
"subtle",
]
[[package]]
@ -1324,7 +1356,7 @@ dependencies = [
"curve25519-dalek",
"ed25519",
"rand 0.7.3",
"sha2 0.9.9",
"sha2",
"zeroize",
]
@ -1466,6 +1498,16 @@ version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "failure"
version = "0.1.8"
@ -1847,7 +1889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
dependencies = [
"digest 0.9.0",
"hmac 0.10.1",
"hmac",
]
[[package]]
@ -1860,15 +1902,6 @@ dependencies = [
"digest 0.9.0",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.3",
]
[[package]]
name = "hostname"
version = "0.3.1"
@ -1962,6 +1995,12 @@ dependencies = [
"syn",
]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "1.8.0"
@ -2239,24 +2278,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "libsystemd"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8144587c71c16756b1055d3dcb0c75cb605a10ecd6523cc33702d5f90902bf6d"
dependencies = [
"hmac 0.12.1",
"libc",
"log",
"nix 0.23.1",
"nom 7.1.0",
"once_cell",
"serde 1.0.136",
"sha2 0.10.2",
"thiserror",
"uuid",
]
[[package]]
name = "linked-hash-map"
version = "0.3.0"
@ -2331,6 +2352,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata",
]
[[package]]
name = "matches"
version = "0.1.9"
@ -2754,6 +2784,15 @@ dependencies = [
"syn",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.27.1"
@ -3335,6 +3374,9 @@ name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
@ -3590,7 +3632,7 @@ dependencies = [
"num 0.3.1",
"rand 0.8.5",
"serde 1.0.136",
"sha2 0.9.9",
"sha2",
"zbus",
"zbus_macros",
"zvariant",
@ -3839,14 +3881,12 @@ dependencies = [
]
[[package]]
name = "sha2"
version = "0.10.2"
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures 0.2.1",
"digest 0.10.3",
"lazy_static",
]
[[package]]
@ -4023,16 +4063,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "systemd-journal-logger"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2b2b2ff370208ad472629786a66dc252933843755a1d620a54a8fdd0fccb31f"
dependencies = [
"libsystemd",
"log",
]
[[package]]
name = "tap"
version = "1.0.1"
@ -4097,6 +4127,15 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
[[package]]
name = "time"
version = "0.1.43"
@ -4107,6 +4146,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "time"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
dependencies = [
"itoa 1.0.1",
"libc",
"num_threads",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
@ -4161,6 +4211,112 @@ dependencies = [
"serde 1.0.136",
]
[[package]]
name = "tracing"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
dependencies = [
"cfg-if 1.0.0",
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-appender"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
dependencies = [
"crossbeam-channel",
"time 0.3.9",
"tracing-subscriber",
]
[[package]]
name = "tracing-attributes"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
dependencies = [
"lazy_static",
"valuable",
]
[[package]]
name = "tracing-error"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-journald"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd"
dependencies = [
"libc",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
dependencies = [
"ansi_term",
"lazy_static",
"matchers",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "tracing-wasm"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07"
dependencies = [
"tracing",
"tracing-subscriber",
"wasm-bindgen",
]
[[package]]
name = "trust-dns-proto"
version = "0.21.2"
@ -4340,13 +4496,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "uuid"
version = "0.8.2"
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"serde 1.0.136",
]
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
@ -4399,7 +4552,6 @@ name = "veilid-core"
version = "0.1.0"
dependencies = [
"android_logger",
"anyhow",
"async-io",
"async-lock",
"async-std",
@ -4416,6 +4568,7 @@ dependencies = [
"chacha20",
"chacha20poly1305",
"chrono",
"color-eyre",
"config 0.12.0",
"console_error_panic_hook",
"curve25519-dalek-ng",
@ -4441,7 +4594,6 @@ dependencies = [
"keyvaluedb-web",
"lazy_static",
"libc",
"log",
"lru",
"maplit",
"ndk",
@ -4468,6 +4620,9 @@ dependencies = [
"socket2",
"static_assertions",
"thiserror",
"tracing",
"tracing-error",
"tracing-subscriber",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test",
@ -4487,17 +4642,17 @@ name = "veilid-flutter"
version = "0.1.0"
dependencies = [
"allo-isolate",
"anyhow",
"async-std",
"backtrace",
"ffi-support",
"futures",
"jni",
"lazy_static",
"log",
"parking_lot 0.12.0",
"serde 1.0.136",
"serde_json",
"tracing",
"tracing-subscriber",
"veilid-core",
]
@ -4505,6 +4660,7 @@ dependencies = [
name = "veilid-server"
version = "0.1.0"
dependencies = [
"ansi_term",
"async-std",
"async-tungstenite 0.17.1",
"bugsalot",
@ -4521,7 +4677,6 @@ dependencies = [
"flume",
"futures",
"lazy_static",
"log",
"nix 0.23.1",
"parking_lot 0.12.0",
"rpassword 6.0.1",
@ -4531,8 +4686,10 @@ dependencies = [
"serial_test 0.6.0",
"signal-hook",
"signal-hook-async-std",
"simplelog",
"systemd-journal-logger",
"tracing",
"tracing-appender",
"tracing-journald",
"tracing-subscriber",
"url",
"veilid-core",
"windows-service",
@ -4547,10 +4704,11 @@ dependencies = [
"futures-util",
"js-sys",
"lazy_static",
"log",
"send_wrapper",
"serde 1.0.136",
"serde_json",
"tracing-subscriber",
"tracing-wasm",
"veilid-core",
"wasm-bindgen",
"wasm-bindgen-futures",

View File

@ -15,12 +15,14 @@ ios_tests = [ "simplelog", "backtrace" ]
tracking = [ "backtrace" ]
[dependencies]
tracing = { version = "^0", features = ["log", "attributes"] }
tracing-subscriber = "^0"
tracing-error = "^0"
color-eyre = "^0"
capnp = { version = "^0", default_features = false }
rust-fsm = "^0"
static_assertions = "^1"
log = "^0"
cfg-if = "^1"
anyhow = "^1"
thiserror = "^1"
hex = "^0"
generic-array = "^0"

View File

@ -1,150 +0,0 @@
use crate::core_context::*;
use crate::veilid_api::*;
use crate::xx::*;
use log::{set_boxed_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record};
use once_cell::sync::OnceCell;
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
use send_wrapper::*;
struct ApiLoggerInner {
level: LevelFilter,
filter_ignore: Cow<'static, [Cow<'static, str>]>,
update_callback: SendWrapper<UpdateCallback>,
}
} else {
struct ApiLoggerInner {
level: LevelFilter,
filter_ignore: Cow<'static, [Cow<'static, str>]>,
update_callback: UpdateCallback,
}
}
}
#[derive(Clone)]
pub struct ApiLogger {
inner: Arc<Mutex<Option<ApiLoggerInner>>>,
}
static API_LOGGER: OnceCell<ApiLogger> = OnceCell::new();
impl ApiLogger {
fn new_inner(level: LevelFilter, update_callback: UpdateCallback) -> ApiLoggerInner {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
ApiLoggerInner {
level,
filter_ignore: Default::default(),
update_callback: SendWrapper::new(update_callback),
}
} else {
ApiLoggerInner {
level,
filter_ignore: Default::default(),
update_callback,
}
}
}
}
pub async fn init(log_level: LevelFilter, update_callback: UpdateCallback) {
set_max_level(log_level);
let api_logger = API_LOGGER.get_or_init(|| {
let api_logger = ApiLogger {
inner: Arc::new(Mutex::new(None)),
};
set_boxed_logger(Box::new(api_logger.clone())).expect("failed to set api logger");
api_logger
});
let apilogger_inner = Some(Self::new_inner(log_level, update_callback));
*api_logger.inner.lock() = apilogger_inner;
}
pub async fn terminate() {
if let Some(api_logger) = API_LOGGER.get() {
let mut inner = api_logger.inner.lock();
*inner = None;
// Clear everything and we're done
set_max_level(LevelFilter::Off);
}
}
pub fn change_log_level(log_level: LevelFilter) {
if let Some(api_logger) = API_LOGGER.get() {
if let Some(inner) = &mut *api_logger.inner.lock() {
set_max_level(log_level);
inner.level = log_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 Log for ApiLogger {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
if let Some(inner) = &mut *self.inner.lock() {
return metadata.level() <= inner.level;
}
false
}
fn log(&self, record: &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();
if level <= inner.level {
let ll = VeilidLogLevel::from_log_level(level);
let file = record.file().unwrap_or("<unknown>");
let loc = if level >= 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 s = format!("{}{}{}", tgt, loc, record.args());
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
log_level: ll,
message: s,
}))
}
}
}
fn flush(&self) {
// always flushes
}
}

View File

@ -0,0 +1,310 @@
use crate::core_context::*;
use crate::veilid_api::*;
use crate::xx::*;
use core::fmt::Write;
use once_cell::sync::OnceCell;
use tracing_subscriber::*;
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
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,
}
}
}
#[derive(Clone)]
pub struct ApiTracingLayer {
inner: Arc<Mutex<Option<ApiLoggerInner>>>,
}
static API_LOGGER: OnceCell<ApiTracingLayer> = OnceCell::new();
impl ApiTracingLayer {
fn new_inner(
max_level: Option<VeilidLogLevel>,
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,
}
}
}
}
pub async fn init(max_level: Option<VeilidLogLevel>, 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));
*api_logger.inner.lock() = apilogger_inner;
}
pub async fn terminate() {
if let Some(api_logger) = API_LOGGER.get() {
let mut inner = api_logger.inner.lock();
*inner = None;
}
}
pub fn get() -> ApiTracingLayer {
API_LOGGER
.get_or_init(|| ApiTracingLayer {
inner: Arc::new(Mutex::new(None)),
})
.clone()
}
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 = Self::new_inner(max_level, inner.update_callback.clone());
}
}
}
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);
}
}
}
}
fn display_current_thread_id() -> String {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
"".to_owned()
} else {
format!("({}:{:?})",
if let Some(n) = async_std::task::current().name() {
n.to_string()
}
else {
async_std::task::current().id().to_string()
},
std::thread::current().id()
)
}
}
}
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<'_>,
id: &tracing::Id,
ctx: layer::Context<'_, S>,
) {
if let Some(_inner) = &mut *self.inner.lock() {
let mut new_debug_record = StringRecorder::new();
attrs.record(&mut new_debug_record);
if let Some(span_ref) = ctx.span(id) {
span_ref
.extensions_mut()
.insert::<StringRecorder>(new_debug_record);
}
}
}
fn on_record(
&self,
id: &tracing::Id,
values: &tracing::span::Record<'_>,
ctx: layer::Context<'_, S>,
) {
if let Some(_inner) = &mut *self.inner.lock() {
if let Some(span_ref) = ctx.span(id) {
if let Some(debug_record) = span_ref.extensions_mut().get_mut::<StringRecorder>() {
values.record(debug_record);
}
}
}
}
fn on_event(&self, event: &tracing::Event<'_>, _ctx: layer::Context<'_, S>) {
if let Some(inner) = &mut *self.inner.lock() {
let mut recorder = StringRecorder::new();
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 origin = meta
.file()
.and_then(|file| meta.line().map(|ln| format!("{}:{}", file, ln)))
.unwrap_or_default();
let message = format!("{}{} {}", origin, display_current_thread_id(), recorder);
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
log_level,
message,
}))
}
}
}
}
}
struct StringRecorder {
display: String,
is_following_args: bool,
}
impl StringRecorder {
fn new() -> Self {
StringRecorder {
display: String::new(),
is_following_args: false,
}
}
}
impl tracing::field::Visit for StringRecorder {
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn core::fmt::Debug) {
if field.name() == "message" {
if !self.display.is_empty() {
self.display = format!("{:?}\n{}", value, self.display)
} else {
self.display = format!("{:?}", value)
}
} else {
if self.is_following_args {
// following args
writeln!(self.display).unwrap();
} else {
// first arg
write!(self.display, " ").unwrap();
self.is_following_args = true;
}
write!(self.display, "{} = {:?};", field.name(), value).unwrap();
}
}
}
impl core::fmt::Display for StringRecorder {
fn fmt(&self, mut f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if !self.display.is_empty() {
write!(&mut f, " {}", self.display)
} else {
Ok(())
}
}
}
impl core::default::Default for StringRecorder {
fn default() -> Self {
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

@ -1,4 +1,4 @@
use crate::api_logger::*;
use crate::api_tracing_layer::*;
use crate::attachment_manager::*;
use crate::dht::Crypto;
use crate::intf::*;
@ -60,11 +60,15 @@ impl ServicesContext {
}
pub async fn startup(&mut self) -> Result<(), VeilidAPIError> {
let log_level: VeilidConfigLogLevel = self.config.get().log_level;
if log_level != VeilidConfigLogLevel::Off {
ApiLogger::init(log_level.to_level_filter(), self.update_callback.clone()).await;
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 {
ApiLogger::add_filter_ignore_str(ig);
ApiTracingLayer::add_filter_ignore_str(ig);
}
info!("Veilid logging initialized");
}
@ -154,7 +158,7 @@ impl ServicesContext {
info!("Veilid API shutdown complete");
// api logger terminate is idempotent
ApiLogger::terminate().await;
ApiTracingLayer::terminate().await;
// send final shutdown update
(self.update_callback)(VeilidUpdate::Shutdown);

View File

@ -4,7 +4,7 @@
#[macro_use]
extern crate alloc;
mod api_logger;
mod api_tracing_layer;
mod attachment_manager;
mod callback_state_machine;
mod core_context;
@ -21,6 +21,7 @@ mod veilid_rng;
#[macro_use]
pub mod xx;
pub use self::api_tracing_layer::ApiTracingLayer;
pub use self::attachment_manager::AttachmentState;
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
pub use self::veilid_api::*;

View File

@ -169,7 +169,7 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
match key.as_str() {
"program_name" => Ok(Box::new(String::from("Veilid"))),
"namespace" => Ok(Box::new(String::from(""))),
"log_level" => Ok(Box::new(VeilidConfigLogLevel::Off)),
"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)),
@ -291,7 +291,7 @@ pub async fn test_config() {
let inner = vc.get();
assert_eq!(inner.program_name, String::from("Veilid"));
assert_eq!(inner.namespace, String::from(""));
assert_eq!(inner.log_level, VeilidConfigLogLevel::Off);
assert_eq!(inner.api_log_level, VeilidConfigLogLevel::Off);
assert_eq!(inner.capabilities.protocol_udp, true);
assert_eq!(inner.capabilities.protocol_connect_tcp, true);
assert_eq!(inner.capabilities.protocol_accept_tcp, true);

View File

@ -1,7 +1,9 @@
#![allow(dead_code)]
mod debug;
mod serialize_helpers;
pub use debug::*;
pub use serialize_helpers::*;
use crate::*;
@ -21,6 +23,7 @@ pub use network_manager::NetworkManager;
pub use routing_table::RoutingTable;
pub use rpc_processor::StatusAnswer;
use api_tracing_layer::*;
use core::fmt;
use core_context::{api_shutdown, VeilidCoreContext};
use enumset::*;
@ -146,7 +149,7 @@ macro_rules! parse_error {
/////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize)]
pub enum VeilidLogLevel {
Error = 1,
Warn,
@ -156,13 +159,22 @@ pub enum VeilidLogLevel {
}
impl VeilidLogLevel {
pub fn from_tracing_level(level: tracing::Level) -> VeilidLogLevel {
match level {
tracing::Level::ERROR => VeilidLogLevel::Error,
tracing::Level::WARN => VeilidLogLevel::Warn,
tracing::Level::INFO => VeilidLogLevel::Info,
tracing::Level::DEBUG => VeilidLogLevel::Debug,
tracing::Level::TRACE => VeilidLogLevel::Trace,
}
}
pub fn from_log_level(level: log::Level) -> VeilidLogLevel {
match level {
Level::Error => VeilidLogLevel::Error,
Level::Warn => VeilidLogLevel::Warn,
Level::Info => VeilidLogLevel::Info,
Level::Debug => VeilidLogLevel::Debug,
Level::Trace => VeilidLogLevel::Trace,
log::Level::Error => VeilidLogLevel::Error,
log::Level::Warn => VeilidLogLevel::Warn,
log::Level::Info => VeilidLogLevel::Info,
log::Level::Debug => VeilidLogLevel::Debug,
log::Level::Trace => VeilidLogLevel::Trace,
}
}
}
@ -1804,15 +1816,8 @@ impl VeilidAPI {
}
// Change api logging level if it is enabled
pub async fn change_log_level(&self, log_level: VeilidConfigLogLevel) {
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
set_max_level(log_level.to_level_filter());
} else {
use api_logger::ApiLogger;
ApiLogger::change_log_level(log_level.to_level_filter());
}
}
pub async fn change_api_log_level(&self, log_level: VeilidConfigLogLevel) {
ApiTracingLayer::change_api_log_level(log_level.to_veilid_log_level());
}
////////////////////////////////////////////////////////////////

View File

@ -1,9 +1,9 @@
use serde::*;
use super::*;
pub fn deserialize_json<'a, T: de::Deserialize<'a>>(
arg: &'a str,
) -> Result<T, veilid_core::VeilidAPIError> {
serde_json::from_str(arg).map_err(|e| veilid_core::VeilidAPIError::ParseError {
) -> Result<T, super::VeilidAPIError> {
serde_json::from_str(arg).map_err(|e| VeilidAPIError::ParseError {
message: e.to_string(),
value: String::new(),
})
@ -11,9 +11,9 @@ pub fn deserialize_json<'a, T: de::Deserialize<'a>>(
pub fn deserialize_opt_json<T: de::DeserializeOwned>(
arg: Option<String>,
) -> Result<T, veilid_core::VeilidAPIError> {
let arg = arg.ok_or_else(|| veilid_core::VeilidAPIError::ParseError {
message: "invalid null string passed to rust".to_owned(),
) -> Result<T, VeilidAPIError> {
let arg = arg.ok_or_else(|| VeilidAPIError::ParseError {
message: "invalid null string".to_owned(),
value: String::new(),
})?;
deserialize_json(&arg)

View File

@ -1,7 +1,5 @@
use crate::dht::*;
use crate::intf;
use crate::xx::*;
use crate::*;
use serde::*;
////////////////////////////////////////////////////////////////////////////////////////////////
@ -195,14 +193,24 @@ pub enum VeilidConfigLogLevel {
}
impl VeilidConfigLogLevel {
pub fn to_level_filter(&self) -> LevelFilter {
pub fn to_veilid_log_level(&self) -> Option<VeilidLogLevel> {
match self {
Self::Off => LevelFilter::Off,
Self::Error => LevelFilter::Error,
Self::Warn => LevelFilter::Warn,
Self::Info => LevelFilter::Info,
Self::Debug => LevelFilter::Debug,
Self::Trace => LevelFilter::Trace,
Self::Off => None,
Self::Error => Some(VeilidLogLevel::Error),
Self::Warn => Some(VeilidLogLevel::Warn),
Self::Info => Some(VeilidLogLevel::Info),
Self::Debug => Some(VeilidLogLevel::Debug),
Self::Trace => Some(VeilidLogLevel::Trace),
}
}
pub fn from_veilid_log_level(level: Option<VeilidLogLevel>) -> Self {
match level {
None => Self::Off,
Some(VeilidLogLevel::Error) => Self::Error,
Some(VeilidLogLevel::Warn) => Self::Warn,
Some(VeilidLogLevel::Info) => Self::Info,
Some(VeilidLogLevel::Debug) => Self::Debug,
Some(VeilidLogLevel::Trace) => Self::Trace,
}
}
}
@ -216,7 +224,7 @@ impl Default for VeilidConfigLogLevel {
pub struct VeilidConfigInner {
pub program_name: String,
pub namespace: String,
pub log_level: VeilidConfigLogLevel,
pub api_log_level: VeilidConfigLogLevel,
pub capabilities: VeilidConfigCapabilities,
pub protected_store: VeilidConfigProtectedStore,
pub table_store: VeilidConfigTableStore,
@ -272,7 +280,7 @@ impl VeilidConfig {
let mut inner = self.inner.write();
get_config!(inner.program_name);
get_config!(inner.namespace);
get_config!(inner.log_level);
get_config!(inner.api_log_level);
get_config!(inner.capabilities.protocol_udp);
get_config!(inner.capabilities.protocol_connect_tcp);
get_config!(inner.capabilities.protocol_accept_tcp);
@ -552,7 +560,7 @@ impl VeilidConfig {
// If we have a node id from storage, check it
if node_id.valid && node_id_secret.valid {
// Validate node id
if !validate_key(&node_id, &node_id_secret) {
if !dht::validate_key(&node_id, &node_id_secret) {
return Err("node id secret and node id key don't match".to_owned());
}
}

View File

@ -20,12 +20,12 @@ pub use futures_util::future::{select, Either};
pub use futures_util::select;
pub use futures_util::stream::FuturesUnordered;
pub use futures_util::{AsyncRead, AsyncWrite};
pub use log::*;
pub use log_thru::*;
pub use owo_colors::OwoColorize;
pub use parking_lot::*;
pub use split_url::*;
pub use static_assertions::*;
pub use tracing::*;
pub type PinBox<T> = Pin<Box<T>>;
pub type PinBoxFuture<T> = PinBox<dyn Future<Output = T> + 'static>;

View File

@ -745,7 +745,7 @@ class VeilidConfigCapabilities {
class VeilidConfig {
String programName;
String namespace;
VeilidConfigLogLevel logLevel;
VeilidConfigLogLevel apiLogLevel;
VeilidConfigCapabilities capabilities;
VeilidConfigProtectedStore protectedStore;
VeilidConfigTableStore tableStore;
@ -755,7 +755,7 @@ class VeilidConfig {
VeilidConfig({
required this.programName,
required this.namespace,
required this.logLevel,
required this.apiLogLevel,
required this.capabilities,
required this.protectedStore,
required this.tableStore,
@ -767,7 +767,7 @@ class VeilidConfig {
return {
'program_name': programName,
'namespace': namespace,
'log_level': logLevel.json,
'api_log_level': apiLogLevel.json,
'capabilities': capabilities.json,
'protected_store': protectedStore.json,
'table_store': tableStore.json,
@ -779,7 +779,7 @@ class VeilidConfig {
VeilidConfig.fromJson(Map<String, dynamic> json)
: programName = json['program_name'],
namespace = json['namespace'],
logLevel = json['log_level'],
apiLogLevel = json['api_log_level'],
capabilities = VeilidConfigCapabilities.fromJson(json['capabilities']),
protectedStore =
VeilidConfigProtectedStore.fromJson(json['protected_store']),
@ -797,7 +797,7 @@ abstract class VeilidUpdate {
case "Log":
{
return VeilidUpdateLog(
veilidLogLevelFromJson(json["log_level"]), json["message"]);
veilidLogLevelFromJson(json["api_log_level"]), json["message"]);
}
case "Attachment":
{
@ -1072,7 +1072,7 @@ abstract class Veilid {
Stream<VeilidUpdate> startupVeilidCore(VeilidConfig config);
Future<VeilidState> getVeilidState();
Future<void> changeLogLevel(VeilidConfigLogLevel logLevel);
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel);
Future<void> shutdownVeilidCore();
Future<String> debug(String command);
String veilidVersionString();

View File

@ -35,9 +35,9 @@ 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_log_level(port: i64, log_level: FfiStr)
typedef _ChangeLogLevelC = Void Function(Int64, Pointer<Utf8>);
typedef _ChangeLogLevelDart = void Function(int, Pointer<Utf8>);
// 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>);
@ -243,7 +243,7 @@ class VeilidFFI implements Veilid {
final _FreeStringDart _freeString;
final _StartupVeilidCoreDart _startupVeilidCore;
final _GetVeilidStateDart _getVeilidState;
final _ChangeLogLevelDart _changeLogLevel;
final _ChangeApiLogLevelDart _changeApiLogLevel;
final _ShutdownVeilidCoreDart _shutdownVeilidCore;
final _DebugDart _debug;
final _VeilidVersionStringDart _veilidVersionString;
@ -259,9 +259,9 @@ class VeilidFFI implements Veilid {
_getVeilidState =
dylib.lookupFunction<_GetVeilidStateC, _GetVeilidStateDart>(
'get_veilid_state'),
_changeLogLevel =
dylib.lookupFunction<_ChangeLogLevelC, _ChangeLogLevelDart>(
'change_log_level'),
_changeApiLogLevel =
dylib.lookupFunction<_ChangeApiLogLevelC, _ChangeApiLogLevelDart>(
'change_api_log_level'),
_shutdownVeilidCore =
dylib.lookupFunction<_ShutdownVeilidCoreC, _ShutdownVeilidCoreDart>(
'shutdown_veilid_core'),
@ -299,11 +299,11 @@ class VeilidFFI implements Veilid {
}
@override
Future<void> changeLogLevel(VeilidConfigLogLevel logLevel) async {
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel) async {
var nativeLogLevel = logLevel.json.toNativeUtf8();
final recvPort = ReceivePort("change_log_level");
final recvPort = ReceivePort("change_api_log_level");
final sendPort = recvPort.sendPort;
_changeLogLevel(sendPort.nativePort, nativeLogLevel);
_changeApiLogLevel(sendPort.nativePort, nativeLogLevel);
malloc.free(nativeLogLevel);
return processFutureVoid(recvPort.first);
}

View File

@ -46,8 +46,8 @@ class VeilidJS implements Veilid {
}
@override
Future<void> changeLogLevel(VeilidConfigLogLevel logLevel) {
return _wrapApiPromise(js_util.callMethod(wasm, "change_log_level",
Future<void> changeApiLogLevel(VeilidConfigLogLevel logLevel) {
return _wrapApiPromise(js_util.callMethod(wasm, "change_api_log_level",
[jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable)]));
}

View File

@ -8,8 +8,9 @@ crate-type = ["cdylib", "staticlib", "rlib"]
[dependencies]
veilid-core = { path="../../veilid-core" }
tracing = { version = "^0", features = ["log", "attributes"] }
tracing-subscriber = "^0"
parking_lot = "^0"
log = "^0"
backtrace = "^0"
serde_json = "^1"
serde = "^1"
@ -19,11 +20,13 @@ futures = "^0"
# Linux, Windows, Mac, iOS, Android
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
async-std = { version = "^1", features = ["unstable"] }
anyhow = { version = "^1", features = ["backtrace"] }
allo-isolate = "^0"
ffi-support = "^0"
lazy_static = "^1"
# Dependencies for WASM builds only
# [target.'cfg(target_arch = "wasm32")'.dependencies]
# Dependencies for Android builds only
[target.'cfg(target_os = "android")'.dependencies]
jni = "^0"

View File

@ -1,13 +1,11 @@
use crate::dart_isolate_wrapper::*;
use crate::dart_serialize::*;
use allo_isolate::*;
use async_std::sync::Mutex as AsyncMutex;
use ffi_support::*;
use lazy_static::*;
use log::*;
use std::os::raw::c_char;
use std::sync::Arc;
use tracing::*;
// Globals
@ -71,7 +69,7 @@ pub extern "C" fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPos
} else {
("<unknown>", 0)
};
log::error!("### Rust `panic!` hit at file '{}', line {}", file, line);
error!("### Rust `panic!` hit at file '{}', line {}", file, line);
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
error!("panic payload: {:?}", s);
} else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
@ -81,7 +79,7 @@ pub extern "C" fn initialize_veilid_flutter(dart_post_c_object_ptr: ffi::DartPos
} else {
error!("no panic payload");
}
log::error!(" Complete stack trace:\n{:?}", backtrace::Backtrace::new());
error!(" Complete stack trace:\n{:?}", backtrace::Backtrace::new());
// And stop the process, no recovery is going to be possible here
std::process::abort();
@ -143,12 +141,13 @@ pub extern "C" fn get_veilid_state(port: i64) {
}
#[no_mangle]
pub extern "C" fn change_log_level(port: i64, log_level: FfiStr) {
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 = deserialize_opt_json(log_level)?;
let log_level: veilid_core::VeilidConfigLogLevel =
veilid_core::deserialize_opt_json(log_level)?;
let veilid_api = get_veilid_api().await?;
veilid_api.change_log_level(log_level).await;
veilid_api.change_api_log_level(log_level).await;
APIRESULT_VOID
});
}

View File

@ -1,4 +1,3 @@
use crate::dart_serialize::*;
pub use allo_isolate::ffi::DartCObject;
pub use allo_isolate::IntoDart;
use allo_isolate::Isolate;
@ -71,7 +70,7 @@ impl DartIsolateWrapper {
pub fn ok_json<T: Serialize>(self, value: T) -> bool {
self.isolate.post(vec![
MESSAGE_OK_JSON.into_dart(),
serialize_json(value).into_dart(),
veilid_core::serialize_json(value).into_dart(),
])
}
@ -83,7 +82,7 @@ impl DartIsolateWrapper {
pub fn err_json<E: Serialize>(self, error: E) -> bool {
self.isolate.post(vec![
MESSAGE_ERR_JSON.into_dart(),
serialize_json(error).into_dart(),
veilid_core::serialize_json(error).into_dart(),
])
}
}
@ -128,7 +127,7 @@ impl DartIsolateStream {
if let Some(isolate) = &inner.isolate {
isolate.post(vec![
MESSAGE_STREAM_ITEM_JSON.into_dart(),
serialize_json(value).into_dart(),
veilid_core::serialize_json(value).into_dart(),
])
} else {
false
@ -149,7 +148,7 @@ impl DartIsolateStream {
if let Some(isolate) = inner.isolate.take() {
isolate.post(vec![
MESSAGE_STREAM_ABORT_JSON.into_dart(),
serialize_json(error).into_dart(),
veilid_core::serialize_json(error).into_dart(),
])
} else {
false

View File

@ -1,6 +1,5 @@
mod dart_ffi;
mod dart_isolate_wrapper;
mod dart_serialize;
#[cfg(target_os = "android")]
use jni::{objects::JClass, objects::JObject, JNIEnv};

View File

@ -11,8 +11,9 @@ name = "veilid-server"
path = "src/main.rs"
[dependencies]
log = "^0"
simplelog = { version = "^0", features = ["test"] }
tracing = { version = "^0", features = ["log", "attributes"] }
tracing-subscriber = { version = "^0", features = ["env-filter"] }
tracing-appender = "^0"
clap = "^3"
async-std = { version = "^1", features = ["unstable"] }
async-tungstenite = { version = "^0", features = ["async-std-runtime", "async-tls"] }
@ -37,6 +38,7 @@ rpassword = "^6"
[target.'cfg(windows)'.dependencies]
windows-service = "^0"
ansi_term = "^0"
[target.'cfg(unix)'.dependencies]
daemonize = "^0"
@ -45,7 +47,7 @@ signal-hook-async-std = "^0"
nix = "^0"
[target.'cfg(target_os = "linux")'.dependencies]
systemd-journal-logger = "^0"
tracing-journald = "^0"
[dev-dependencies]
serial_test = "^0"

View File

@ -1,55 +1,20 @@
@0xd29582d26b2fb073;
enum AttachmentState {
detached @0;
attaching @1;
attachedWeak @2;
attachedGood @3;
attachedStrong @4;
fullyAttached @5;
overAttached @6;
detaching @7;
}
struct VeilidStateAttachment {
state @0 :AttachmentState;
}
struct VeilidStateNetwork {
started @0 :Bool;
bpsDown @1 :UInt64;
bpsUp @2 :UInt64;
}
struct VeilidUpdate {
union {
attachment @0 :VeilidStateAttachment;
network @1 :VeilidStateNetwork;
shutdown @2 :Void;
}
}
struct VeilidState {
attachment @0 :VeilidStateAttachment;
network @1 :VeilidStateNetwork;
}
interface Registration {}
interface VeilidServer {
register @0 (veilidClient: VeilidClient) -> (registration: Registration, state: VeilidState);
register @0 (veilidClient: VeilidClient) -> (registration: Registration, state: Text);
debug @1 (what: Text) -> (output: Text);
attach @2 ();
detach @3 ();
shutdown @4 ();
getState @5 () -> (state: VeilidState);
getState @5 () -> (state: Text);
}
interface VeilidClient {
update @0 (veilidUpdate: VeilidUpdate);
logMessage @1 (message: Text);
update @0 (veilidUpdate: Text);
}

View File

@ -7,74 +7,18 @@ use failure::*;
use futures::io::AsyncReadExt;
use futures::FutureExt as FuturesFutureExt;
use futures::StreamExt;
use log::*;
use std::cell::RefCell;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::rc::Rc;
use tracing::*;
use veilid_core::xx::Eventual;
use veilid_core::*;
#[derive(Fail, Debug)]
#[fail(display = "Client API error: {}", _0)]
pub struct ClientAPIError(String);
fn convert_attachment_state(state: &veilid_core::AttachmentState) -> AttachmentState {
match state {
veilid_core::AttachmentState::Detached => AttachmentState::Detached,
veilid_core::AttachmentState::Attaching => AttachmentState::Attaching,
veilid_core::AttachmentState::AttachedWeak => AttachmentState::AttachedWeak,
veilid_core::AttachmentState::AttachedGood => AttachmentState::AttachedGood,
veilid_core::AttachmentState::AttachedStrong => AttachmentState::AttachedStrong,
veilid_core::AttachmentState::FullyAttached => AttachmentState::FullyAttached,
veilid_core::AttachmentState::OverAttached => AttachmentState::OverAttached,
veilid_core::AttachmentState::Detaching => AttachmentState::Detaching,
}
}
fn convert_update(
update: &veilid_core::VeilidUpdate,
mut rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
) {
match update {
veilid_core::VeilidUpdate::Log(veilid_core::VeilidStateLog {
log_level: _,
message: _,
}) => {
panic!("Should not be logging to api in server!");
}
veilid_core::VeilidUpdate::Attachment(veilid_core::VeilidStateAttachment { state }) => {
let mut att = rpc_update.init_attachment();
att.set_state(convert_attachment_state(state));
}
veilid_core::VeilidUpdate::Network(veilid_core::VeilidStateNetwork {
started,
bps_down,
bps_up,
}) => {
let mut nb = rpc_update.init_network();
nb.set_started(*started);
nb.set_bps_down(*bps_down);
nb.set_bps_up(*bps_up);
}
veilid_core::VeilidUpdate::Shutdown => {
rpc_update.set_shutdown(());
}
}
}
fn convert_state(
state: &veilid_core::VeilidState,
mut rpc_state: crate::veilid_client_capnp::veilid_state::Builder,
) {
let mut ab = rpc_state.reborrow().init_attachment();
ab.set_state(convert_attachment_state(&state.attachment.state));
let mut nb = rpc_state.reborrow().init_network();
nb.set_started(state.network.started);
nb.set_bps_down(state.network.bps_down);
nb.set_bps_up(state.network.bps_up);
}
// --- interface Registration ---------------------------------
struct RegistrationHandle {
@ -166,11 +110,17 @@ impl veilid_server::Server for VeilidServerImpl {
.get_state()
.await
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?;
let state = serialize_json(state);
let mut res = results.get();
res.set_registration(registration);
let rpc_state = res.init_state();
convert_state(&state, rpc_state);
let mut rpc_state = res.init_state(
state
.len()
.try_into()
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?,
);
rpc_state.push_str(&state);
Ok(())
})
@ -256,9 +206,17 @@ impl veilid_server::Server for VeilidServerImpl {
.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 rpc_state = results.get().init_state();
convert_state(&state, rpc_state);
Ok(())
})
}
@ -345,7 +303,7 @@ impl ClientApi {
fn send_request_to_all_clients<F, T>(self: Rc<Self>, request: F)
where
F: Fn(u64, &mut RegistrationHandle) -> ::capnp::capability::RemotePromise<T>,
F: Fn(u64, &mut RegistrationHandle) -> Option<::capnp::capability::RemotePromise<T>>,
T: capnp::traits::Pipelined + for<'a> capnp::traits::Owned<'a> + 'static + Unpin,
{
// Send status update to each registered client
@ -361,40 +319,44 @@ impl ClientApi {
}
registration.requests_in_flight += 1;
let request_promise = request(id, registration);
let registration_map2 = registration_map1.clone();
async_std::task::spawn_local(request_promise.promise.map(move |r| match r {
Ok(_) => {
if let Some(ref mut s) =
registration_map2.borrow_mut().registrations.get_mut(&id)
{
s.requests_in_flight -= 1;
if let Some(request_promise) = request(id, registration) {
let registration_map2 = registration_map1.clone();
async_std::task::spawn_local(request_promise.promise.map(move |r| match r {
Ok(_) => {
if let Some(ref mut s) =
registration_map2.borrow_mut().registrations.get_mut(&id)
{
s.requests_in_flight -= 1;
}
}
}
Err(e) => {
println!("Got error: {:?}. Dropping registation.", e);
registration_map2.borrow_mut().registrations.remove(&id);
}
}));
Err(e) => {
println!("Got error: {:?}. Dropping registation.", e);
registration_map2.borrow_mut().registrations.remove(&id);
}
}));
}
}
}
pub fn handle_update(self: Rc<Self>, veilid_update: veilid_core::VeilidUpdate) {
// serialize update
let veilid_update = serialize_json(veilid_update);
// Pass other updates to clients
self.send_request_to_all_clients(|_id, registration| {
let mut request = registration.client.update_request();
let rpc_veilid_update = request.get().init_veilid_update();
convert_update(&veilid_update, rpc_veilid_update);
request.send()
});
}
pub fn handle_client_log(self: Rc<Self>, message: String) {
self.send_request_to_all_clients(|_id, registration| {
let mut request = registration.client.log_message_request();
request.get().set_message(&message);
request.send()
match veilid_update
.len()
.try_into()
.map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))
{
Ok(len) => {
let mut request = registration.client.update_request();
let mut rpc_veilid_update = request.get().init_veilid_update(len);
rpc_veilid_update.push_str(&veilid_update);
Some(request.send())
}
Err(_) => None,
}
});
}

View File

@ -24,6 +24,9 @@ pub mod veilid_client_capnp {
}
fn main() -> Result<(), String> {
#[cfg(windows)]
let _ = ansi_term::enable_ansi_support();
let (settings, matches) = cmdline::process_command_line()?;
// --- Dump Config ---
@ -55,7 +58,7 @@ fn main() -> Result<(), String> {
// Handle non-normal server modes
if !matches!(server_mode, ServerMode::Normal) {
// Init combined console/file logger
let logs = VeilidLogs::setup_normal_logs(settings.clone())?;
let logs = VeilidLogs::setup(settings.clone())?;
// run the server to set the node id and quit
return task::block_on(async { run_veilid_server(settings, logs, server_mode).await })
.map(|v| {
@ -80,7 +83,7 @@ fn main() -> Result<(), String> {
}
// Init combined console/file logger
let logs = VeilidLogs::setup_normal_logs(settings.clone())?;
let logs = VeilidLogs::setup(settings.clone())?;
// --- Normal Startup ---
ctrlc::set_handler(move || {

View File

@ -3,10 +3,10 @@ use crate::settings::*;
use crate::veilid_logs::*;
use flume::{bounded, Receiver, Sender};
use lazy_static::*;
use log::*;
use parking_lot::Mutex;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tracing::*;
use veilid_core::xx::SingleShotEventual;
#[derive(Copy, Clone, PartialEq, Eq)]
@ -91,41 +91,6 @@ pub async fn run_veilid_server_internal(
}
}
});
// Handle log messages on main thread for capnproto rpc
let client_log_receiver_jh = capi.clone().and_then(|capi| {
logs.client_log_channel
.clone()
.map(|mut client_log_channel| {
async_std::task::spawn_local(async move {
// Batch messages to either 16384 chars at once or every second to minimize packets
let rate = Duration::from_secs(1);
let mut start = Instant::now();
let mut messages = String::new();
loop {
let timeout_dur =
rate.checked_sub(start.elapsed()).unwrap_or(Duration::ZERO);
match async_std::future::timeout(timeout_dur, client_log_channel.recv())
.await
{
Ok(Ok(message)) => {
messages += &message;
if messages.len() > 16384 {
capi.clone()
.handle_client_log(core::mem::take(&mut messages));
start = Instant::now();
}
}
Ok(Err(_)) => break,
Err(_) => {
capi.clone()
.handle_client_log(core::mem::take(&mut messages));
start = Instant::now();
}
}
}
})
})
});
// Auto-attach if desired
let mut out = Ok(());
@ -193,18 +158,8 @@ pub async fn run_veilid_server_internal(
// Shut down Veilid API to release state change sender
veilid_api.shutdown().await;
// Close the client api log channel if it is open to release client log sender
if let Some(client_log_channel_closer) = logs.client_log_channel_closer {
client_log_channel_closer.close();
}
// Wait for update receiver to exit
update_receiver_jh.await;
// Wait for client api log receiver to exit
if let Some(client_log_receiver_jh) = client_log_receiver_jh {
client_log_receiver_jh.await;
}
out
}

View File

@ -1,7 +1,6 @@
#![allow(clippy::bool_assert_comparison)]
use directories::*;
use log::*;
use parking_lot::*;
use serde_derive::*;
@ -34,7 +33,7 @@ logging:
path: ''
append: true
level: 'info'
client:
api:
enabled: false
level: 'info'
testing:
@ -226,13 +225,13 @@ impl serde::Serialize for LogLevel {
}
}
pub fn convert_loglevel(log_level: LogLevel) -> LevelFilter {
pub fn convert_loglevel(log_level: LogLevel) -> veilid_core::VeilidLogLevel {
match log_level {
LogLevel::Error => LevelFilter::Error,
LogLevel::Warn => LevelFilter::Warn,
LogLevel::Info => LevelFilter::Info,
LogLevel::Debug => LevelFilter::Debug,
LogLevel::Trace => LevelFilter::Trace,
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,
}
}
@ -419,7 +418,7 @@ pub struct System {
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Client {
pub struct Api {
pub enabled: bool,
pub level: LogLevel,
}
@ -435,7 +434,7 @@ pub struct Logging {
pub system: System,
pub terminal: Terminal,
pub file: File,
pub client: Client,
pub api: Api,
}
#[derive(Debug, Deserialize, Serialize)]
@ -862,7 +861,13 @@ impl Settings {
} else {
format!("subnode{}", inner.testing.subnode_index)
})),
"log_level" => Ok(Box::new(veilid_core::VeilidConfigLogLevel::Off)),
"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)),
@ -1257,8 +1262,8 @@ mod tests {
assert_eq!(s.logging.file.path, "");
assert_eq!(s.logging.file.append, true);
assert_eq!(s.logging.file.level, LogLevel::Info);
assert_eq!(s.logging.client.enabled, false);
assert_eq!(s.logging.client.level, LogLevel::Info);
assert_eq!(s.logging.api.enabled, false);
assert_eq!(s.logging.api.level, LogLevel::Info);
assert_eq!(s.testing.subnode_index, 0);
assert_eq!(

View File

@ -93,7 +93,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
};
// Init combined console/file logger
let logs = VeilidLogs::setup_normal_logs(settings.clone())?;
let logs = VeilidLogs::setup(settings.clone())?;
// Daemonize
daemon

View File

@ -1,162 +1,127 @@
use crate::log_safe_channel::*;
use crate::settings::*;
use cfg_if::*;
use log::*;
use simplelog::*;
use std::fs::OpenOptions;
use std::path::Path;
use std::path::*;
use tracing::*;
use tracing_appender::*;
use tracing_subscriber::prelude::*;
use tracing_subscriber::*;
pub struct VeilidLogs {
pub client_log_channel: Option<LogSafeChannel>,
pub client_log_channel_closer: Option<LogSafeChannelCloser>,
pub guard: Option<non_blocking::WorkerGuard>,
}
cfg_if! {
if #[cfg(target_os = "linux")] {
use systemd_journal_logger::JournalLog;
pub struct SystemLogger {
level_filter: LevelFilter,
config: Config,
journal_log: JournalLog<String,String>,
}
impl SystemLogger {
pub fn new(level_filter: LevelFilter, config: Config) -> Box<Self> {
Box::new(Self {
level_filter,
config,
journal_log: JournalLog::with_extra_fields(Vec::new())
})
}
pub fn should_skip(record: &Record<'_>) -> bool {
// // If a module path and allowed list are available
// match (record.target(), &*config.filter_allow) {
// (path, allowed) if !allowed.is_empty() => {
// // Check that the module path matches at least one allow filter
// if !allowed.iter().any(|v| path.starts_with(&**v)) {
// // If not, skip any further writing
// return true;
// }
// }
// _ => {}
// }
// If a module path and ignore list are available
match (record.target(), &veilid_core::DEFAULT_LOG_IGNORE_LIST) {
(path, ignore) if !ignore.is_empty() => {
// Check that the module path does not match any ignore filters
if ignore.iter().any(|v| path.starts_with(&**v)) {
// If not, skip any further writing
return true;
}
}
_ => {}
}
false
}
}
impl Log for SystemLogger {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.level() <= self.level_filter
}
fn log(&self, record: &Record<'_>) {
if self.enabled(record.metadata()) && ! Self::should_skip(record) {
self.journal_log.log(record);
}
}
fn flush(&self) {
self.journal_log.flush();
}
}
impl SharedLogger for SystemLogger {
fn level(&self) -> LevelFilter {
self.level_filter
}
fn config(&self) -> Option<&Config> {
Some(&self.config)
}
fn as_log(self: Box<Self>) -> Box<dyn Log> {
Box::new(*self)
}
fn logfilter<T: AsRef<str>, V: AsRef<[T]>>(
metadata: &Metadata,
max_level: veilid_core::VeilidLogLevel,
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,
}
}
impl VeilidLogs {
pub fn setup_normal_logs(settings: Settings) -> Result<VeilidLogs, String> {
pub fn setup(settings: Settings) -> Result<VeilidLogs, String> {
let settingsr = settings.read();
// Set up loggers
let mut logs: Vec<Box<dyn SharedLogger>> = Vec::new();
let mut client_log_channel: Option<LogSafeChannel> = None;
let mut client_log_channel_closer: Option<LogSafeChannelCloser> = None;
let mut cb = ConfigBuilder::new();
// Set up subscriber and layers
let mut ignore_list = Vec::<String>::new();
for ig in veilid_core::DEFAULT_LOG_IGNORE_LIST {
cb.add_filter_ignore_str(ig);
ignore_list.push(ig.to_owned());
}
if settingsr.logging.terminal.enabled {
logs.push(TermLogger::new(
convert_loglevel(settingsr.logging.terminal.level),
cb.build(),
TerminalMode::Mixed,
ColorChoice::Auto,
))
}
if settingsr.logging.file.enabled {
let subscriber = Registry::default();
let subscriber = subscriber.with(
EnvFilter::builder()
.with_default_directive(level_filters::LevelFilter::INFO.into())
.from_env_lossy(),
);
let subscriber = subscriber.with(if settingsr.logging.terminal.enabled {
let terminal_max_log_level = convert_loglevel(settingsr.logging.terminal.level);
Some(
fmt::Layer::new()
.compact()
.with_writer(std::io::stdout)
.with_filter(filter::FilterFn::new(move |metadata| {
logfilter(metadata, terminal_max_log_level, &ignore_list)
})),
)
} else {
None
});
let mut guard = None;
let subscriber = subscriber.with(if settingsr.logging.file.enabled {
let file_max_log_level = convert_loglevel(settingsr.logging.file.level);
let log_path = Path::new(&settingsr.logging.file.path);
let full_path = std::env::current_dir()
.unwrap_or(PathBuf::from(MAIN_SEPARATOR.to_string()))
.join(log_path);
let log_parent = full_path
.parent()
.unwrap_or(Path::new(&MAIN_SEPARATOR.to_string()))
.canonicalize()
.map_err(|e| {
format!(
"File log path parent does not exist: {} ({})",
settingsr.logging.file.path, e
)
})?;
let log_filename = full_path.file_name().ok_or(format!(
"File log filename not specified in path: {}",
settingsr.logging.file.path
))?;
let logfile = if settingsr.logging.file.append {
OpenOptions::new()
.create(true)
.append(true)
.open(log_path)
.map_err(|e| format!("failed to open log file: {}", e))?
} else {
OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(log_path)
.map_err(|e| format!("failed to open log file: {}", e))?
};
logs.push(WriteLogger::new(
convert_loglevel(settingsr.logging.file.level),
cb.build(),
logfile,
))
}
if settingsr.logging.client.enabled {
let (clog, clogwriter, clogcloser) = LogSafeChannel::new();
client_log_channel = Some(clog);
client_log_channel_closer = Some(clogcloser);
logs.push(WriteLogger::new(
convert_loglevel(settingsr.logging.client.level),
cb.build(),
clogwriter,
))
}
let appender = tracing_appender::rolling::never(log_parent, Path::new(log_filename));
let (non_blocking_appender, non_blocking_guard) =
tracing_appender::non_blocking(appender);
guard = Some(non_blocking_guard);
Some(
fmt::Layer::new()
.compact()
.with_writer(non_blocking_appender)
.with_filter(filter::FilterFn::new(|metadata| {
logfilter(metadata, file_max_log_level, &ignore_list)
})),
)
} else {
None
});
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
});
cfg_if! {
if #[cfg(target_os = "linux")] {
if settingsr.logging.system.enabled {
logs.push(SystemLogger::new(convert_loglevel(settingsr.logging.system.level), cb.build()))
}
let subscriber = subscriber.with(if settingsr.logging.system.enabled {
let system_max_log_level = convert_loglevel(settingsr.logging.system.level);
Some(tracing_journald::layer().map_err(|e| format!("failed to set up journald logging: {}", e))?.with_filter(filter::FilterFn::new(|metadata| {
logfilter(metadata, system_max_log_level, &ignore_list)
})))
} else {
None
});
}
}
CombinedLogger::init(logs).map_err(|e| format!("failed to init logs: {}", e))?;
subscriber
.try_init()
.map_err(|e| format!("failed to initialize logging: {}", e))?;
Ok(VeilidLogs {
client_log_channel,
client_log_channel_closer,
})
Ok(VeilidLogs { guard })
}
}

View File

@ -12,7 +12,8 @@ crate-type = ["cdylib", "rlib"]
wasm-bindgen = { version = "^0", features = ["serde-serialize"] }
console_error_panic_hook = "^0"
wee_alloc = "^0"
log = "^0"
tracing-wasm = "^0"
tracing-subscriber = "^0"
veilid-core = { path = "../veilid-core" }
cfg-if = "^1"
wasm-bindgen-futures = "^0"

View File

@ -139,11 +139,11 @@ pub fn get_veilid_state() -> Promise {
}
#[wasm_bindgen()]
pub fn change_log_level(log_level: String) -> Promise {
pub fn change_api_log_level(log_level: String) -> Promise {
wrap_api_future(async move {
let veilid_api = get_veilid_api()?;
let log_level: veilid_core::VeilidConfigLogLevel = deserialize_json(&log_level)?;
veilid_api.change_log_level(log_level).await;
veilid_api.change_api_log_level(log_level).await;
APIRESULT_UNDEFINED
})
}