1
0
forked from ROMEO/nexosim

Add model tracing spans + tracing feature flag

This commit is contained in:
Serge Barral
2024-09-10 11:12:49 +02:00
parent c7d86b9df1
commit e376f17c7c
4 changed files with 87 additions and 5 deletions

View File

@ -379,6 +379,61 @@
//! [pony]: https://www.ponylang.io/
//!
//!
//! # Feature flags
//!
//! ## Tracing support
//!
//! The `tracing` feature flag provides support for the
//! [`tracing`](https://docs.rs/tracing/latest/tracing/) crate and can be
//! activated in `Cargo.toml` with:
//!
//! ```toml
//! [dependencies]
//! asynchronix = { version = "0.3", features = ["tracing"] }
//! ```
//!
//! Each tracing event or span emitted by a model is then wrapped in a span
//! named `model` with a target `asynchronix` and an attribute `name`. The value
//! of the attribute is the name provided to
//! [`SimInit::add_model`](simulation::SimInit::add_model).
//!
//! Note that model spans are always emitted at
//! [`Level::INFO`](tracing::Level::INFO) .
//!
//! ### Tracing examples
//!
//! The examples below assume that the `tracing` feature flag is activated, the
//! `tracing_subscriber` crate is used with the `env-filter` feature flag
//! activated and the default subscriber is set up, e.g. with:
//!
//! ```ignore
//! tracing_subscriber::fmt::init();
//! ```
//!
//! In order to let only warnings and errors pass through but still see model
//! span information (which is emitted as info), you may run the bench with:
//!
//! ```{.bash}
//! $ RUST_LOG="warn,[model]=info" cargo run --release my_bench
//! 2024-09-09T21:05:47.891984Z WARN model{name="kettle"}: my_bench: water is boiling
//! 2024-09-09T21:08:13.284753Z WARN model{name="timer"}: my_bench: ring ring
//! 2024-09-09T21:08:13.284753Z WARN model{name="kettle"}: my_bench: water is hot
//! ```
//!
//! In order to see warnings or errors for the `kettle` model only, you may
//! instead run the bench with:
//!
//! ```{.bash}
//! $ RUST_LOG="[model{name=kettle}]=warn" cargo run --release my_bench
//! 2024-09-09T21:05:47.891984Z WARN model{name="kettle"}: my_bench: water is boiling
//! 2024-09-09T21:08:13.284753Z WARN model{name="kettle"}: my_bench: water is hot
//! ```
//!
//! If the `model` span name collides with that of spans defined outside
//! `asynchronix`, the above filters can be made more specific using
//! `asynchronix[model]` instead of just `[model]`.
//!
//!
//! # Other resources
//!
//! ## Other examples

View File

@ -257,7 +257,7 @@ impl Simulation {
Ok(())
}
/// Returns scheduler.
/// Returns a scheduler handle.
pub fn scheduler(&self) -> Scheduler {
Scheduler::new(self.scheduler_queue.clone(), self.time.reader())
}
@ -488,14 +488,22 @@ pub(crate) fn add_model<M: Model>(
scheduler: Scheduler,
executor: &Executor,
) {
#[cfg(feature = "tracing")]
let span = tracing::span!(target: env!("CARGO_PKG_NAME"), tracing::Level::INFO, "model", name);
let context = Context::new(name, LocalScheduler::new(scheduler, mailbox.address()));
let setup_context = SetupContext::new(&mailbox, &context, executor);
model.setup(&setup_context);
let mut receiver = mailbox.0;
executor.spawn_and_forget(async move {
let fut = async move {
let mut model = model.init(&context).await.0;
while receiver.recv(&mut model, &context).await.is_ok() {}
});
};
#[cfg(feature = "tracing")]
let fut = tracing::Instrument::instrument(fut, span);
executor.spawn_and_forget(fut);
}

View File

@ -16,6 +16,8 @@ pub struct SimInit {
scheduler_queue: Arc<Mutex<SchedulerQueue>>,
time: SyncCell<TearableAtomicTime>,
clock: Box<dyn Clock + 'static>,
#[cfg(feature = "tracing")]
log_level: tracing::Level,
}
impl SimInit {
@ -44,6 +46,8 @@ impl SimInit {
scheduler_queue: Arc::new(Mutex::new(PriorityQueue::new())),
time: SyncCell::new(TearableAtomicTime::new(MonotonicTime::EPOCH)),
clock: Box::new(NoClock::new()),
#[cfg(feature = "tracing")]
log_level: tracing::Level::INFO,
}
}
@ -74,6 +78,16 @@ impl SimInit {
self
}
/// Set the level of verbosity for model spans.
///
/// By default, model spans use [`Level::INFO`](tracing::Level::INFO).
#[cfg(feature = "tracing")]
pub fn with_log_level(mut self, level: tracing::Level) -> Self {
self.log_level = level;
self
}
/// Builds a simulation initialized at the specified simulation time,
/// executing the [`Model::init()`](crate::model::Model::init) method on all
/// model initializers.