失败日志去重键带上项目路径
export/draft/xhs_minitool/commands.rs:LAST_FAILURE 的键从命令名改为(命令名, 项目路径),避免不同项目的同一句失败被静默吞掉。
This commit is contained in:
@@ -96,7 +96,7 @@ pub(crate) async fn run_xhs_minitool_export_build(
|
||||
let result = run_build(&project_path).await;
|
||||
match &result {
|
||||
Ok(run) => {
|
||||
clear_failure("build");
|
||||
clear_failure("build", &project_path);
|
||||
app_log!(
|
||||
"export.build.ok project={project_path} outputChars={} omittedCharacters={}",
|
||||
run.output_tail.chars().count(),
|
||||
@@ -172,14 +172,17 @@ async fn run_build(
|
||||
build::run(&root).await
|
||||
}
|
||||
|
||||
/// 上一次记过的失败(按命令名)。面板每 2 秒重读,同一个失败会反复落到同一条命令上。
|
||||
static LAST_FAILURE: LazyLock<Mutex<HashMap<&'static str, String>>> =
|
||||
/// 上一次记过的失败(按命令名 + 项目路径)。面板每 2 秒重读,同一个失败会反复落到同一条命令上。
|
||||
///
|
||||
/// 去重键必须带上项目:`registryMalformed` 之类的现场文案不含文件路径,两个项目可能给出同一句
|
||||
/// `Debug`,只按命令名去重会把项目 B 的失败当成项目 A 的重复现场静默吞掉。
|
||||
static LAST_FAILURE: LazyLock<Mutex<HashMap<(&'static str, String), String>>> =
|
||||
LazyLock::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
/// 命令边界的统一收口:成功清掉去重记录,失败记一条。
|
||||
fn report<T, E: std::fmt::Debug>(command: &'static str, project_path: &str, result: &Result<T, E>) {
|
||||
match result {
|
||||
Ok(_) => clear_failure(command),
|
||||
Ok(_) => clear_failure(command, project_path),
|
||||
Err(error) => log_failure(command, project_path, error),
|
||||
}
|
||||
}
|
||||
@@ -193,11 +196,12 @@ const MAX_LOGGED_FAILURE_CHARS: usize = 512;
|
||||
|
||||
fn log_failure(command: &'static str, project_path: &str, error: &impl std::fmt::Debug) {
|
||||
let message = bounded_for_log(&format!("{error:?}"), MAX_LOGGED_FAILURE_CHARS);
|
||||
let key = (command, project_path.trim().to_string());
|
||||
if let Ok(mut last) = LAST_FAILURE.lock() {
|
||||
if last.get(command).is_some_and(|seen| *seen == message) {
|
||||
if last.get(&key).is_some_and(|seen| *seen == message) {
|
||||
return;
|
||||
}
|
||||
last.insert(command, message.clone());
|
||||
last.insert(key, message.clone());
|
||||
}
|
||||
app_log!("export.{command}.failed project={project_path}: {message}");
|
||||
}
|
||||
@@ -211,9 +215,9 @@ fn bounded_for_log(message: &str, max_chars: usize) -> String {
|
||||
format!("{head}…")
|
||||
}
|
||||
|
||||
fn clear_failure(command: &'static str) {
|
||||
fn clear_failure(command: &'static str, project_path: &str) {
|
||||
if let Ok(mut last) = LAST_FAILURE.lock() {
|
||||
last.remove(command);
|
||||
last.remove(&(command, project_path.trim().to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user