Skip to main content

gwr_track/
lib.rs

1// Copyright (c) 2020 Graphcore Ltd. All rights reserved.
2
3//! This module provides combined _track_ capabilities for the GWR project.
4//!
5//! _Track_ means the combination of _log_ and _trace_ where:
6//!
7//!   - _log_ are text-based human-readable messages emitted at various levels
8//!     of verbosity (from `Trace` through to `Error`).
9//!   - _trace_ provides a standard set of modelling events that can be emitted.
10//!     For example, object creation/destruction or objects entering/exitting
11//!     simulation [`Entities`](crate::entity::Entity).
12//!
13//! The _track_ events can be emitted using:
14//!
15//!   - a textual output based on the [log](https://docs.rs/log) crate.
16//!   - a packed binary output based on [Cap'n Proto](https://capnproto.org/).
17//!   - a packed binary output based output based on [Perfetto TrackEvents](https://perfetto.dev/docs/instrumentation/track-events)
18//!     Protobufs (only avaliable with the `perfetto` feature enabled).
19
20// Enable warnings for missing documentation
21#![warn(missing_docs)]
22
23use std::cell::RefCell;
24use std::rc::Rc;
25use std::str::FromStr;
26
27#[doc(hidden)]
28pub use log;
29
30pub mod builder;
31pub mod entity;
32pub mod id;
33
34#[cfg(feature = "perfetto")]
35pub mod perfetto_trace_builder;
36
37/// Include the trackers.
38pub mod tracker;
39pub use tracker::{Track, Tracker};
40
41/// A type alias for objects that receive _log_ / _trace_ events.
42pub type Writer = Box<dyn std::io::Write>;
43type SharedWriter = Rc<RefCell<Writer>>;
44
45/// Take the command-line string and convert it to a Level
46#[must_use]
47pub fn str_to_level(lvl: &str) -> log::Level {
48    match log::Level::from_str(lvl) {
49        Ok(level) => level,
50        Err(_) => panic!("Unable to parse level string '{lvl}'"),
51    }
52}
53
54/// Type used for unique IDs
55///
56/// Each _log_/_trace_ event within the application is given a unique ID to
57/// identify it. There are two reserved ID values: [NO_ID](constant.NO_ID.html)
58/// and [ROOT](constant.ROOT.html)
59pub use id::Id;
60
61pub mod test_helpers;
62pub mod trace_visitor;
63
64/// ID value which indicates where there is no valid ID
65pub const NO_ID: Id = id::Id(0);
66
67/// The root ID from which all other IDs are derived
68pub const ROOT: Id = id::Id(1);
69
70/// Create a unique ID for tracking.
71///
72/// The user must specify an entity with a [`Tracker`] to create the ID.
73///
74/// **Note:** this macro should be used when the object being assigned the
75///           [`Id`] will have its creation tracked with the
76///           [`track_create_object`] macro.
77#[macro_export]
78macro_rules! create_id {
79    ($entity:expr) => {{ $entity.tracker.unique_id() }};
80}
81
82/// Add an object creation event.
83///
84/// The details string is only formatted when trace-level events are enabled for
85/// the entity.
86#[macro_export]
87macro_rules! track_create_object {
88    ($entity:expr ; $created:expr, $size:expr, $units:expr, $req_type:expr, $($details:tt)+) => {{
89        let entity = &$entity;
90        if entity.trace_enabled() {
91            let details = format!($($details)+);
92            entity.tracker.create_object(
93                entity.id,
94                $created,
95                $size,
96                $units,
97                $req_type,
98                &details,
99            );
100        }
101    }};
102}
103
104/// Destroy an ID
105///
106/// Destroying an ID indicates to the logging system that this ID is finished
107/// with and should therefore not be used any more. This is not enforced at
108/// runtime, and therefore will not cause any errors to be reported if it is
109/// used.
110#[macro_export]
111macro_rules! destroy_id {
112    ($entity:expr ; $id:expr) => {{
113        $entity.tracker.destroy($entity.id, $id);
114    }};
115}
116
117/// Add an entity destroy event
118#[macro_export]
119macro_rules! destroy {
120    ($entity:expr) => {{
121        match &$entity.parent {
122            Some(parent) => $entity.tracker.destroy($entity.id, parent.id),
123            None => $entity.tracker.destroy($entity.id, $crate::NO_ID),
124        };
125    }};
126}
127
128/// Connect two entities
129#[macro_export]
130macro_rules! connect {
131    ($from_entity:expr ; $to_entity:expr) => {{
132        $from_entity.tracker.connect($from_entity.id, $to_entity.id);
133    }};
134}
135
136/// Update the current time.
137#[macro_export]
138macro_rules! set_time {
139    ($entity:expr ; $time_ns:expr) => {{
140        $entity.tracker.time($entity.id, $time_ns);
141    }};
142}
143
144/// Base macro for log messages of all level.
145///
146/// This wrapper calls both the [`log`](https://docs.rs/log)::log macro and also the
147/// [`Trace`](trait.Trace.html) [message](trait.Trace.html#tymethod.message)
148/// function which will emit `message` tracking events to the Cap'n Proto binary
149/// stream.
150#[macro_export]
151macro_rules! log_base {
152    ($entity:expr ; $lvl:expr, $($arg:tt)+) => {{
153        let entity = &$entity;
154        let level = $lvl;
155        if entity.enabled_for(level) {
156            entity.tracker.log(entity.id, level, format_args!($($arg)+));
157        }
158    }};
159}
160
161/// The `trace` macro provides a wrapper for the [`log`](macro.log.html) macro
162/// at level `log::Level::Trace`
163#[macro_export]
164macro_rules! trace {
165    ($entity:expr ; $($arg:tt)+) => (
166        $crate::log_base!($entity ; $crate::log::Level::Trace, $($arg)+);
167    );
168}
169
170/// The `debug` macro provides a wrapper for the [`log`](macro.log.html) macro
171/// at level `log::Level::Debug`
172#[macro_export]
173macro_rules! debug {
174    ($entity:expr ; $($arg:tt)+) => (
175        $crate::log_base!($entity ; $crate::log::Level::Debug, $($arg)+);
176    );
177}
178
179/// The `info` macro provides a wrapper for the [`log`](macro.log.html) macro at
180/// level `log::Level::Info`
181#[macro_export]
182macro_rules! info {
183    ($entity:expr ; $($arg:tt)+) => (
184        $crate::log_base!($entity ; $crate::log::Level::Info, $($arg)+);
185    );
186}
187
188/// The `warn` macro provides a wrapper for the [`log`](macro.log.html) macro at
189/// level `log::Level::Info`
190#[macro_export]
191macro_rules! warn {
192    ($entity:expr ; $($arg:tt)+) => (
193        $crate::log_base!($entity ; $crate::log::Level::Warn, $($arg)+);
194    );
195}
196
197/// the `error` macro provides a wrapper for the [`log`](macro.log.html) macro
198/// at level `log::Level::Error`
199#[macro_export]
200macro_rules! error {
201    ($entity:expr ; $($arg:tt)+) => (
202        $crate::log_base!($entity ; $crate::log::Level::Error, $($arg)+);
203    );
204}
205
206/// Auto-generated [Cap'n Proto](https://capnproto.org/) module
207///
208/// The contents of this file are created by `build.rs` at compile-time. They
209/// provide all the functions required to build up
210/// [Cap'n Proto](https://capnproto.org/) events as defined in the
211/// `schemas/gwr_trace.capnp` file.
212pub mod gwr_track_capnp {
213    // No need to emit warnings for auto-generated Cap'n Proto code
214    #![allow(missing_docs)]
215    #![allow(clippy::all)]
216    #![allow(clippy::pedantic)]
217    include!(concat!(env!("OUT_DIR"), "/gwr_track_capnp.rs"));
218}