tuwunel_core/metrics/
dump.rs1use std::{fs, path::Path, process};
8
9use serde::Serialize;
10#[cfg(tokio_unstable)]
11use tokio_metrics::RuntimeMetrics;
12
13use crate::{
14 Result, debug_info, error,
15 utils::{sys::Usage, time::now_millis},
16 version,
17};
18
19#[cfg(tokio_unstable)]
20const RUNTIME_METRICS_PREFIX: &str = "tuwunel.runtime_metrics";
21const RUNTIME_USAGE_PREFIX: &str = "tuwunel.runtime_usage";
22
23#[derive(Serialize)]
24struct Dump<'a> {
25 meta: DumpMeta,
26 payload: &'a str,
27}
28
29#[derive(Serialize)]
30struct DumpMeta {
31 pid: u32,
32 wrote_at_ms: u64,
33 tuwunel_version: &'static str,
34 scope: &'static str,
35}
36
37impl DumpMeta {
38 fn new(scope: &'static str) -> Self {
39 Self {
40 pid: process::id(),
41 wrote_at_ms: now_millis(),
42 tuwunel_version: version(),
43 scope,
44 }
45 }
46}
47
48#[cfg(tokio_unstable)]
49pub fn write_runtime_metrics(dir: &Path, metrics: &RuntimeMetrics) {
50 let pid = process::id();
51 let path = dir.join(format!("{RUNTIME_METRICS_PREFIX}.{pid}.json"));
52 let payload = format!("{metrics:?}");
53 let dump = Dump {
54 meta: DumpMeta::new("runtime_metrics"),
55 payload: &payload,
56 };
57
58 report(&path, "runtime_metrics", write_json(&path, &dump));
59}
60
61pub fn write_resource_usage(dir: &Path, usage: &Usage) {
62 let pid = process::id();
63 let path = dir.join(format!("{RUNTIME_USAGE_PREFIX}.{pid}.json"));
64 let payload = format!("{usage:?}");
65 let dump = Dump {
66 meta: DumpMeta::new("runtime_usage"),
67 payload: &payload,
68 };
69
70 report(&path, "runtime_usage", write_json(&path, &dump));
71}
72
73fn write_json<T: Serialize>(path: &Path, value: &T) -> Result {
74 if let Some(parent) = path.parent()
75 && !parent.as_os_str().is_empty()
76 {
77 fs::create_dir_all(parent)?;
78 }
79
80 let json = serde_json::to_string_pretty(value)?;
81 fs::write(path, json)?;
82
83 Ok(())
84}
85
86fn report(path: &Path, scope: &'static str, result: Result) {
87 match result {
88 | Ok(()) => debug_info!(?path, %scope, "Wrote metrics."),
89 | Err(error) => error!(?path, %scope, %error, "Failed to write metrics."),
90 }
91}