Skip to content

Commit 699c186

Browse files
committed
Add --trace-tmp
1 parent be224b9 commit 699c186

6 files changed

Lines changed: 66 additions & 5 deletions

File tree

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
- New: Support for reading and writing archives over SFTP. Credentials currently must come from an sftp-agent.
1010

11+
- New: Added `--trace-tmp`, which writes a detailed trace to a temporary file, whose name is printed to stderr.
12+
1113
## 24.8.0
1214

1315
- Fixed: `restore --only` specifying a subdirectory no longer fails due to parent directories missing from the destination.

src/bin/conserve.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ struct Args {
5353
#[arg(long, short = 'D', global = true)]
5454
debug: bool,
5555

56+
/// Write a detailed trace to a temporary file.
57+
#[arg(long, global = true)]
58+
trace_tmp: bool,
59+
5660
/// Control timestamps prefixes on stderr.
5761
#[arg(long, value_enum, global = true, default_value_t = TraceTimeStyle::None)]
5862
trace_time: TraceTimeStyle,
@@ -714,7 +718,13 @@ fn main() -> Result<ExitCode> {
714718
Level::INFO
715719
};
716720
let monitor = Arc::new(TermUiMonitor::new(!args.no_progress));
717-
let _flush_tracing = enable_tracing(&monitor, &args.trace_time, console_level, &args.log_json);
721+
let _flush_tracing = enable_tracing(
722+
&monitor,
723+
&args.trace_time,
724+
console_level,
725+
&args.log_json,
726+
args.trace_tmp,
727+
);
718728
let result = args.command.run(monitor.clone());
719729
debug!(elapsed = ?start_time.elapsed());
720730
if let Some(metrics_path) = args.metrics_json {

src/misc.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
1616
use std::time::Duration;
1717

18-
1918
use crate::stats::Sizes;
2019

2120
pub fn bytes_to_human_mb(s: u64) -> String {

src/termui/trace.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt::Debug;
77
use std::fs::OpenOptions;
88
use std::path::PathBuf;
99

10-
use tracing::{Level, trace};
10+
use tracing::{Level, info, trace};
1111
use tracing_appender::non_blocking::WorkerGuard;
1212
use tracing_subscriber::{
1313
Registry, filter,
@@ -35,6 +35,7 @@ pub fn enable_tracing(
3535
time_style: &TraceTimeStyle,
3636
console_level: Level,
3737
json_path: &Option<PathBuf>,
38+
trace_tmp: bool,
3839
) -> Option<WorkerGuard> {
3940
let time_style = time_style.clone();
4041
let console_layer = tracing_subscriber::fmt::Layer::default()
@@ -43,6 +44,23 @@ pub fn enable_tracing(
4344
.with_timer(time_style)
4445
.with_filter(filter::Targets::new().with_target("conserve", console_level));
4546
let json_layer;
47+
let (trace_tmp_layer, tmp_path) = if trace_tmp {
48+
let (tmp_file, tmp_path) = tempfile::Builder::new()
49+
.prefix(&format!("conserve-trace-{}-", std::process::id()))
50+
.suffix(".log")
51+
.tempfile()
52+
.expect("create trace temp file")
53+
.keep()
54+
.expect("keep trace temp file");
55+
let layer = tracing_subscriber::fmt::Layer::default()
56+
.with_writer(tmp_file)
57+
.with_ansi(false)
58+
.with_timer(time::uptime())
59+
.with_filter(filter::Targets::new().with_target("conserve", Level::TRACE));
60+
(Some(layer), Some(tmp_path))
61+
} else {
62+
(None, None)
63+
};
4664
let flush_guard;
4765
if let Some(json_path) = json_path {
4866
let file_writer = OpenOptions::new()
@@ -65,9 +83,13 @@ pub fn enable_tracing(
6583
Registry::default()
6684
.with(console_layer)
6785
.with(json_layer)
86+
.with(trace_tmp_layer)
6887
.init();
6988

7089
trace!("Tracing enabled");
90+
if let Some(tmp_path) = tmp_path {
91+
info!("Trace temp file: {}", tmp_path.display());
92+
}
7193
flush_guard
7294
}
7395

tests/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Conserve backup system.
2-
// Copyright 2016-2024 Martin Pool.
2+
// Copyright 2016-2026 Martin Pool.
33

44
// This program is free software; you can redistribute it and/or modify
55
// it under the terms of the GNU General Public License as published by

tests/cli_tests/trace.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
// Copyright 2023 Martin Pool
1+
// Copyright 2023-2026 Martin Pool
22

33
//! Tests for trace-related options and behaviors of the Conserve CLI.
44
5+
use std::fs::read_to_string;
6+
use std::path::Path;
7+
58
use assert_cmd::prelude::*;
69
use assert_fs::TempDir;
710
use assert_fs::prelude::*;
@@ -21,3 +24,28 @@ fn no_trace_timestamps_by_default() {
2124
"TRACE conserve::termui::trace: Tracing enabled",
2225
));
2326
}
27+
28+
#[test]
29+
fn trace_to_tmp_file() {
30+
let temp_dir = TempDir::new().unwrap();
31+
let assert = run_conserve()
32+
.args(["init", "--trace-tmp"])
33+
.arg(temp_dir.child("archive").path())
34+
.assert()
35+
.success();
36+
let stderr = String::from_utf8(assert.get_output().stderr.clone())
37+
.expect("stderr should be valid UTF-8");
38+
println!("Stderr output:\n{stderr}");
39+
let tmp_file = stderr
40+
.lines()
41+
.find_map(|line| line.strip_prefix(" INFO conserve::termui::trace: Trace temp file: "))
42+
.expect("couldn't extract trace file path from stderr");
43+
let tmp_path = Path::new(tmp_file);
44+
assert!(tmp_path.exists(), "trace file {tmp_path:?} should exist");
45+
let trace_content = read_to_string(tmp_path).expect("read trace file");
46+
println!("Trace file content:\n{trace_content}");
47+
assert!(
48+
trace_content.contains("TRACE conserve::termui::trace: Tracing enabled"),
49+
"trace file should contain trace lines"
50+
);
51+
}

0 commit comments

Comments
 (0)