wasmer_c_api/tracing.rs
1//! Utilities to set up tracing and logging.
2//!
3//! By default, wasmer does not generate any tracing output. To
4//! enable tracing, one must call the `wasmer_setup_tracing()`
5//! function during the initialization stage of their program.
6//!
7//! Tracing levels can be enabled/disabled using the [RUST_LOG
8//! env var](https://docs.rs/env_logger/latest/env_logger/#enabling-logging).
9//!
10//! # Example
11//!
12//! ```rust
13//! # use wasmer_inline_c::assert_c;
14//! # fn main() {
15//! # (assert_c! {
16//! # #include "tests/wasmer.h"
17//! #
18//! int main() {
19//! // This can go up to 4, which is the most verbose
20//! int verbosity_level = 0;
21//! // Whether to use colors when logging information
22//! int use_colors = 1;
23//! wasmer_setup_tracing(verbosity_level, use_colors);
24//!
25//! return 0;
26//! }
27//! # })
28//! # .success();
29//! # }
30
31use std::ffi::c_int;
32
33use tracing::level_filters::LevelFilter;
34use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
35
36const WHITELISTED_LOG_TARGETS: &[&str] = &["wasmer", "wasmer_wasix", "virtual_fs"];
37
38#[unsafe(no_mangle)]
39pub extern "C" fn wasmer_setup_tracing(verbosity_level: c_int, use_color: c_int) {
40 let fmt_layer = fmt::layer()
41 .with_target(true)
42 .with_span_events(fmt::format::FmtSpan::CLOSE)
43 .with_ansi(use_color > 0)
44 .with_thread_ids(true)
45 .with_writer(std::io::stderr);
46
47 let filter_layer = {
48 let default_filters = [
49 LevelFilter::OFF,
50 LevelFilter::WARN,
51 LevelFilter::INFO,
52 LevelFilter::DEBUG,
53 ];
54
55 // First, we set up the default log level.
56 let default_level = default_filters
57 .get(verbosity_level as usize)
58 .copied()
59 .unwrap_or(LevelFilter::TRACE);
60 let mut filter = EnvFilter::builder()
61 .with_default_directive(default_level.into())
62 .from_env_lossy();
63
64 // Next we add level-specific directives, where verbosity=0 means don't
65 // override anything. Note that these are shifted one level up so we'll
66 // get something like RUST_LOG="warn,wasmer_wasix=info"
67 let specific_filters = [LevelFilter::WARN, LevelFilter::INFO, LevelFilter::DEBUG];
68 if verbosity_level > 0 {
69 let level = specific_filters
70 .get(verbosity_level as usize)
71 .copied()
72 .unwrap_or(LevelFilter::TRACE);
73
74 for target in WHITELISTED_LOG_TARGETS {
75 let directive = format!("{target}={level}").parse().unwrap();
76 filter = filter.add_directive(directive);
77 }
78 }
79
80 filter
81 };
82
83 tracing_subscriber::registry()
84 .with(filter_layer)
85 .with(fmt_layer.compact().with_target(true))
86 .init();
87}