Skip to main content

forge/
trace.rs

1//! Shared TRACE-log initialization for Forge simulation commands.
2
3use std::sync::Mutex;
4
5use anyhow::{Context, Result};
6use wowlab_fs::{file::File, path::PathBuf, temporary};
7
8pub(crate) fn init_trace_log(enabled: bool, label: &str) -> Result<Option<PathBuf>> {
9    if !enabled {
10        return Ok(None);
11    }
12
13    let file = create_trace_log(label)?;
14    let path = file.path().to_path_buf();
15    let subscriber = tracing_subscriber::fmt()
16        .with_max_level(tracing::Level::TRACE)
17        .with_writer(Mutex::new(file))
18        .with_ansi(false)
19        .finish();
20
21    tracing::subscriber::set_global_default(subscriber)
22        .context("failed to set tracing subscriber")?;
23
24    Ok(Some(path))
25}
26
27fn create_trace_log(label: &str) -> Result<File> {
28    let temporary = temporary::File::with_affixes(&format!("forge-trace-{label}-"), ".log")
29        .context("failed to create trace log")?;
30
31    temporary.retain().context("failed to create trace log")
32}
33
34#[cfg(test)]
35mod tests {
36    use std::io::Write as _;
37
38    use googletest::prelude::*;
39    use wowlab_fs::{directory, file};
40
41    use super::create_trace_log;
42
43    #[gtest]
44    fn trace_logs_are_unique_named_and_retained_after_the_writer_closes() -> Result<()> {
45        let mut left = create_trace_log("outlaw_rogue").or_fail()?;
46        let right = create_trace_log("outlaw_rogue").or_fail()?;
47        let left_path = left.path().to_path_buf();
48        let right_path = right.path().to_path_buf();
49        let left_name = left_path
50            .file_name()
51            .and_then(|name| name.to_str())
52            .or_fail()?;
53        let left_extension = left_path.extension().and_then(|value| value.to_str());
54
55        left.write_all(b"trace event").or_fail()?;
56        left.sync().or_fail()?;
57
58        verify_that!(left_path, not(eq(&right_path)))?;
59        verify_true!(left_name.starts_with("forge-trace-outlaw_rogue-"))?;
60        verify_eq!(left_extension, Some("log"))?;
61
62        drop(left);
63        drop(right);
64
65        verify_that!(file::read_text(&left_path).or_fail()?, eq("trace event"))?;
66        verify_that!(directory::inspect(&right_path).or_fail()?, some(anything()))?;
67
68        directory::remove_file_if_exists(&left_path).or_fail()?;
69        directory::remove_file_if_exists(&right_path).or_fail()?;
70
71        Ok(())
72    }
73}