reqray 0.4.3

Log 'request x-rays' for rust programs instrumented with `tracing`.
Documentation
use std::{
    fs::File,
    sync::{Arc, Mutex},
};

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use quanta::Mock;
use reqray::{CallTreeCollector, CallTreeCollectorBuilder, FinishedCallTreeProcessor};

use tracing::info;
use tracing_subscriber::fmt;
use tracing_subscriber::prelude::*;

#[tracing::instrument]
fn one_ns(mock: &Mock) {
    info!("one_ns");
    mock.increment(1);
}

#[tracing::instrument]
fn compound_call(mock: &Mock) {
    mock.increment(10);
    one_ns(mock);
    mock.increment(100);
    one_ns(mock);
    for _ in 0..10 {
        one_ns(mock);
    }
    mock.increment(1000);
}

pub fn sync_compound(c: &mut Criterion) {
    let (_clock, mock) = quanta::Clock::mock();
    c.bench_function("without subscriber", |b| {
        b.iter(|| compound_call(black_box(&mock)))
    });
    c.bench_function("log with layers", |b| {
        let f = File::create("benches_without_calltree.txt").unwrap();
        let fmt_layer = fmt::layer()
            .with_thread_ids(true)
            .without_time()
            .with_target(false)
            .with_writer(f);
        let subscriber = tracing_subscriber::registry().with(fmt_layer);
        tracing::subscriber::with_default(subscriber, || {
            b.iter(|| compound_call(black_box(&mock)))
        });
    });
    c.bench_function("log with call tree collector", |b| {
        let call_tree_collector = CallTreeCollector::default();
        let f = File::create("benches_with_calltree.txt").unwrap();
        let fmt_layer = fmt::layer()
            .with_thread_ids(true)
            .without_time()
            .with_target(false)
            .with_writer(f);
        let subscriber = tracing_subscriber::registry()
            .with(call_tree_collector)
            .with(fmt_layer);
        tracing::subscriber::with_default(subscriber, || {
            b.iter(|| compound_call(black_box(&mock)))
        });
    });

    c.bench_function("log with silent call tree collector", |b| {
        let counting = CountingCallTreeProcessor::default();
        let call_tree_collector =
            CallTreeCollectorBuilder::default().build_with_collector(counting.clone());
        let f = File::create("benches_with_silent_calltree.txt").unwrap();
        let fmt_layer = fmt::layer()
            .with_thread_ids(true)
            .without_time()
            .with_target(false)
            .with_writer(f);
        let subscriber = tracing_subscriber::registry()
            .with(call_tree_collector)
            .with(fmt_layer);
        tracing::subscriber::with_default(subscriber, || {
            b.iter(|| compound_call(black_box(&mock)))
        });
        assert!(*counting.root_child_count.lock().unwrap() > 0);
    });
}

#[derive(Default, Clone)]
struct CountingCallTreeProcessor {
    root_child_count: Arc<Mutex<usize>>,
}

impl FinishedCallTreeProcessor for CountingCallTreeProcessor {
    fn process_finished_call(&self, pool: reqray::CallPathPool) {
        let mut locked = self.root_child_count.lock().unwrap();
        *locked += pool.root().children().count();
    }
}

criterion_group!(benches, sync_compound);
criterion_main!(benches);