Crate si_trace_print

Crate si_trace_print 

Source
Expand description

Macros for printing stack-indented trace-like print statements.

Library users should use macros provided in printers (which are also listed here).

§Basic Usage

use si_trace_print::{
    den, deo, dex, defn, defo, defx,
};

fn main() {
    den!("hello from main");
    deo!("main will be doing stuff...");
    func1(3);
    deo!("main is done doing stuff.");
    dex!("goodbye from main");
}

fn func1(_var: usize) {
    defn!("({:?})", _var);
    defo!("doing even more stuff...");
    defx!();
}

this should print to stderr

$ cargo run
→hello from main
 main will be doing stuff...
    →func1: (3)
     func1: doing even more stuff...
    ←func1:
 main is done doing stuff.
←goodbye from main

An example using a variety of the available println macros. These compile into debug and release builds and print to stdout.

extern crate si_trace_print;
use si_trace_print::{pf1n, pf2n, pfn, pn, po, px};

fn main() {
    pn!("hello from main");
    pfn!("hello again from main");
    pf1n!("hello again from main!");
    pf2n!("HELLO AGAIN FROM MAIN!!!");
    po!("main will be doing stuff...");
    mod1::mod2::func1(3);
    po!("main is done doing stuff...");
    px!("goodbye from main");
}

mod mod1 {
    pub mod mod2 {
        use si_trace_print::{
            pf1n, pf1o, pf1x, pf1ñ, pf2n, pf2o, pf2x, pf2ñ, pfn, pfo, pfx, pfñ, pñ,
        };
        pub fn func1(var: usize) {
            pf1n!("({:?})", var);
            pf1o!("func1 calling func2...");
            func2(var + 1);
            pf1x!("({:?})", var);
        }
        fn func2(var: usize) {
            pf2n!("({:?})", var);
            pf2o!("calling func3...");
            func3();
            pf2x!("({:?})", var);
        }
        fn func3() {
            pfn!();
            func4();
            pfo!("almost complete...");
            pfx!();
        }
        fn func4() {
            pñ!("func4 is a short function.");
            pfñ!("func4 is a short function.");
            pf1ñ!("func4 is a short function.");
            pf2ñ!("func4 is a short function.");
        }
    }
}

should print to stdout

→hello from main
→main: hello again from main
→main: hello again from main!
→main: HELLO AGAIN FROM MAIN!!!
 main will be doing stuff...
    →mod2::func1: (3)
     mod2::func1: func1 calling func2...
        →mod1::mod2::func2: (4)
         mod1::mod2::func2: calling func3...
            →func3:
                ↔func4 is a short function.
                ↔func4: func4 is a short function.
                ↔mod2::func4: func4 is a short function.
                ↔mod1::mod2::func4: func4 is a short function.
             func3: almost complete...
            ←func3:
        ←mod1::mod2::func2: (4)
    ←mod2::func1: (3)
 main is done doing stuff...
←goodbye from main

§Multi-threaded printing and the global lock

To avoid interleaved printing among threads, surround your println! or eprintln! statements in the global lock guard GLOBAL_LOCK_PRINTER. Helper functions print_guard or debug_print_guard are provided.

use ::si_trace_print::{efn, efx};
use ::si_trace_print::printers::print_guard;

let mut handles: Vec<std::thread::JoinHandle<()>> = vec![];
for n in 0..10 {
    let h = std::thread::spawn(move || {
        efn!("time to do some work...");
        // ...do some work...
        let result = n;
        // ...a few moments later...
        // get the guard before printing
        let guard = print_guard();
        println!("{}", result);
        // drop the guard before calling another si_trace_print macro
        drop(guard);
        efx!("work complete");
    });
    handles.push(h);
}
for h in handles {
    h.join().unwrap();
}

If using si_trace_print debug macros (the recommended way to use this module) then call the debug_print_guard helper function.

In this code example, guard is a MutexGuard in debug builds and a () in non-debug release builds (which is likely optimized away).

use ::si_trace_print::{defn, defx};
use ::si_trace_print::printers::debug_print_guard;

let mut handles: Vec<std::thread::JoinHandle<()>> = vec![];
for n in 0..10 {
    let h = std::thread::spawn(move || {
        defn!("time to do some work...");
        // ...do some work...
        let result = n;
        // ...a little while later...
        // get the guard before printing
        let guard = debug_print_guard();
        println!("{}", result);
        // explicitly drop the guard before calling another si_trace_print macro
        drop(guard);
        defx!("work complete");
    });
    handles.push(h);
}
for h in handles {
    h.join().unwrap();
}

Modules§

function_name
Macros to derive the current function name.
printers
Macros to print trace statements with stack offset indentation.
stack
Functions to store a stack offset for indented trace prints and return the appropriate preprint str.

Macros§

de
debug eprintln!
def1n
debug eprintln! in a function plus one namespace level when entering.
def1o
debug eprintln! in a function plus one namespace level with offset.
def1x
debug eprintln! in a function plus one namespace level when exiting.
def1ñ
debug eprintln! in a function with one namespace levels when entering and exiting.
def2n
debug eprintln! in a function plus two namespace levels when entering.
def2o
debug eprintln! in a function plus two namespace levels with offset.
def2x
debug eprintln! in a function plus two namespace levels when exiting.
def2ñ
debug eprintln! in a function plus two namespace levels when entering and exiting.
defn
debug eprintln! in a function when entering.
defo
debug eprintln! in a function with offset.
defx
debug eprintln! in a function when exiting.
defñ
debug eprintln! in a function when entering and exiting.
den
debug eprintln! when entering.
deo
debug eprintln! with offset.
dex
debug eprintln! when exiting.
deñ
debug eprintln! when entering and exiting.
dp
debug println!
dpf1n
debug println! in a function plus one namespace level when entering.
dpf1o
debug println! in a function plus one namespace level with offset.
dpf1x
debug println! in a function plus one namespace level when exiting.
dpf1ñ
debug println! in a function plus one namespace level when entering and exiting.
dpf2n
debug println! in a function plus two namespace levels when entering.
dpf2o
debug println! in a function plus two namespace levels with offset
dpf2x
debug println! in a function plus two namespace levels when exiting.
dpf2ñ
debug println! in a function plus two namespace levels when entering and exiting.
dpfn
debug println! in a function when entering.
dpfo
debug println! in a function with offset.
dpfx
debug println! in a function when exiting.
dpfñ
debug println! in a function when entering and exiting.
dpn
debug println! when entering.
dpo
debug println! with offset.
dpx
debug println! when exiting.
dpñ
debug println! when entering and exiting.
e
eprintln!
ef1n
eprintln! in a function plus one namespace level when entering.
ef1o
eprintln! in a function with one namespace levels and offset.
ef1x
eprintln! in a function plus one namespace level when exiting.
ef1ñ
eprintln! in a function plus one namespace level when entering and exiting.
ef2n
eprintln! in a function plus two namespace levels when entering.
ef2o
eprintln! in a function with two namespace levels and offset.
ef2x
eprintln! in a function plus two namespace levels when exiting.
ef2ñ
eprintln! in a function plus two namespace levels when entering and exiting.
efn
eprintln! in a function when entering.
efo
eprintln! in a function with offset.
efx
eprintln! in a function when exiting.
efñ
eprintln! in a function when entering and exiting.
en
eprintln! when entering.
eo
eprintln! with offset.
ex
eprintln! when exiting.
eprintln! when entering and exiting.
function_name
Return the current function name as a &'static str, e.g. "my_func".
function_name_full
Return the current function name full path as a &'static str, e.g. "my_lib::my_mod::my_func".
function_name_plus
Return the current function name plus preceding namespaces as a &'static str.
p
println!
pf1n
println! in a function plus one namespace level when entering.
pf1o
println! in a function plus one namespace level with offset.
pf1x
println! in a function plus one namespace level when exiting.
pf1ñ
println! in a function plus one namespace level when entering and exiting.
pf2n
println! in a function plus two namespace levels when entering.
pf2o
println! in a function plus two namespace levels with offset.
pf2x
println! in a function plus two namespace levels when exiting.
pf2ñ
println! in a function plus two namespace levels when entering and exiting.
pfn
println! in a function when entering.
pfo
println! in a function with offset.
pfx
println! in a function when exiting.
pfñ
println! in a function when entering and exiting.
pn
println! when entering.
po
println! with offset.
px
println! when exiting.
println! when entering and exiting.