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}