use crate::core::ribosome::CallContext;
use crate::core::ribosome::RibosomeT;
use holochain_types::prelude::*;
use once_cell::unsync::Lazy;
use std::sync::Arc;
use wasmer::RuntimeError;
#[cfg(test)]
use once_cell::sync::Lazy as SyncLazy;
#[cfg(test)]
use std::sync::atomic::AtomicBool;
#[cfg(test)]
static CAPTURE: AtomicBool = AtomicBool::new(false);
#[cfg(test)]
static CAPTURED: SyncLazy<Arc<std::sync::Mutex<Vec<TraceMsg>>>> =
SyncLazy::new(|| Arc::new(std::sync::Mutex::new(Vec::new())));
#[cfg_attr(feature = "instrument", tracing::instrument(skip(input)))]
pub fn wasm_trace(input: TraceMsg) {
match input.level {
holochain_types::prelude::Level::TRACE => tracing::trace!("{}", input.msg),
holochain_types::prelude::Level::DEBUG => tracing::debug!("{}", input.msg),
holochain_types::prelude::Level::INFO => tracing::info!("{}", input.msg),
holochain_types::prelude::Level::WARN => tracing::warn!("{}", input.msg),
holochain_types::prelude::Level::ERROR => tracing::error!("{}", input.msg),
}
}
pub fn trace(
_ribosome: Arc<impl RibosomeT>,
_call_context: Arc<CallContext>,
input: TraceMsg,
) -> Result<(), RuntimeError> {
let wasm_log = Lazy::new(|| {
std::env::var("WASM_LOG").unwrap_or_else(|_| "[wasm_trace]=debug".to_string())
});
let collector = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::new((*wasm_log).clone()))
.with_target(false)
.finish();
#[cfg(test)]
if CAPTURE.load(std::sync::atomic::Ordering::Relaxed) {
CAPTURED.lock().unwrap().push(input.clone());
}
tracing::subscriber::with_default(collector, || wasm_trace(input));
Ok(())
}
#[cfg(test)]
#[cfg(feature = "slow_tests")]
pub mod wasm_test {
use super::*;
use crate::fixt::CallContextFixturator;
use crate::fixt::RealRibosomeFixturator;
use crate::test_utils::RibosomeTestFixture;
use holochain_wasm_test_utils::TestWasm;
use std::sync::Arc;
#[tokio::test(flavor = "multi_thread")]
async fn trace_test() {
let ribosome = RealRibosomeFixturator::new(crate::fixt::Zomes(vec![]))
.next()
.unwrap();
let call_context = CallContextFixturator::new(::fixt::Unpredictable)
.next()
.unwrap();
let input = TraceMsg {
level: holochain_types::prelude::Level::DEBUG,
msg: "ribosome trace works".to_string(),
};
let _: () = trace(Arc::new(ribosome), Arc::new(call_context), input).unwrap();
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "Doesn't work concurrently"]
async fn wasm_trace_test() {
use holochain_types::prelude::Level::*;
CAPTURE.store(true, std::sync::atomic::Ordering::SeqCst);
holochain_trace::test_run();
let RibosomeTestFixture {
conductor, alice, ..
} = RibosomeTestFixture::new(TestWasm::Debug).await;
let _: () = conductor.call(&alice, "debug", ()).await;
let r: Vec<_> = CAPTURED.lock().unwrap().clone();
let expect = vec![
TraceMsg {
msg:
"integrity_test_wasm_debug:debug/src/integrity.rs:5 tracing in validation works"
.to_string(),
level: INFO,
},
TraceMsg {
msg:
"integrity_test_wasm_debug:debug/src/integrity.rs:5 tracing in validation works"
.to_string(),
level: INFO,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:5 tracing works!".to_string(),
level: TRACE,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:6 debug works".to_string(),
level: DEBUG,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:7 info works".to_string(),
level: INFO,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:8 warn works".to_string(),
level: WARN,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:9 error works".to_string(),
level: ERROR,
},
TraceMsg {
msg: "test_wasm_debug:debug/src/lib.rs:10 foo = \"fields\"; bar = \"work\"; too"
.to_string(),
level: DEBUG,
},
];
assert_eq!(r, expect);
}
}