1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use crate::counter::{get_counter_value, COUNTER_SUFFIX, __COUNTERS_LIST};
use bytesize::ByteSize;
use json::{object, JsonValue};
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::thread::sleep;
use std::time::{Duration, Instant};

pub fn enable_counters_logging(
    file: impl AsRef<Path>,
    interval: Duration,
    callback: impl Fn(&mut JsonValue) + Send + 'static,
) {
    let mut file = File::create(file).unwrap();
    let time = Instant::now();

    std::thread::spawn(move || {
        let mut keys = Vec::new();
        loop {
            sleep(interval);
            {
                keys.clear();
                let list = __COUNTERS_LIST.lock();
                keys.extend(list.keys().cloned());
            }

            let mut json_values = object! {};

            json_values["_time"] = time.elapsed().as_secs_f64().into();

            for name in &keys {
                // Skip average counters
                if name.ends_with(COUNTER_SUFFIX) {
                    continue;
                }

                let (value, avg_counter) = get_counter_value(&name);

                // Average, use floating point
                if avg_counter > 0 {
                    let avg_value = (value as f64) / (avg_counter as f64);
                    let values: [JsonValue; 3] = [
                        avg_value.into(),
                        avg_counter.into(),
                        format!("{}", ByteSize(avg_value as u64)).into(),
                    ];
                    json_values[name] = values.as_ref().into();
                } else {
                    let values: [JsonValue; 2] = [
                        value.into(),
                        format!("{}", ByteSize(value.abs() as u64)).into(),
                    ];
                    json_values[name] = values.as_ref().into();
                }
            }

            callback(&mut json_values);

            let _ = writeln!(file, "{}", json_values);
        }
    });
}