fix(diagnostics): include service errors after launcher readiness

This commit is contained in:
Дмитрий committed 2026-10-13 06:10:56 +05:00
1 parent d86a1676fe
commit acd04fae2f
2 files changed
+32 -2

No files matched your search

@@ -0,0 +1,7 @@
---
area: manager
type: fixed
audience: admins
title: Failed server startup shows service errors even when the launcher reported ready
---
Update rehearsal and startup failures include recent world, authentication and database error lines. Missing tables and late startup failures are visible directly in the error details, with secrets redacted.
+25 -2
View File
@@ -279,8 +279,19 @@ pub(crate) fn startup_failure(root: &Path, started: &DriverOutcome) -> String {
let title = code.map(|c| c.human().title).unwrap_or("The server did not become ready");
let output = crate::diag::redact(&started.output);
let lines: Vec<_> = output.lines().rev().take(12).collect();
if lines.is_empty() { title.into() }
else { format!("{title}\n{}", lines.into_iter().rev().collect::<Vec<_>>().join("\n")) }
let mut reason = if lines.is_empty() { title.into() }
else { format!("{title}\n{}", lines.into_iter().rev().collect::<Vec<_>>().join("\n")) };
for relative in ["Core/Logs/world-console.log", "Core/Logs/auth-console.log", "mysql/logs/mysql-error.log"] {
let tail = crate::health::tail(&root.join(relative), 64 * 1024);
let failures: Vec<_> = tail.lines().filter(|line| {
let lower = line.to_ascii_lowercase();
crate::health::diagnose(line).is_some() || lower.contains("fatal") || lower.contains("error") || lower.contains("aborting")
}).rev().take(8).collect();
if !failures.is_empty() {
reason.push_str(&format!("\n{relative}:\n{}", crate::diag::redact(&failures.into_iter().rev().collect::<Vec<_>>().join("\n"))));
}
}
reason
}
#[cfg(test)]
@@ -381,6 +392,18 @@ mod tests {
assert!(run(dir.path(), Verb::StartAll).is_err());
}
#[test]
fn startup_failure_reports_late_world_errors_after_launcher_ready() {
let dir = tempfile::tempdir().unwrap();
std::fs::create_dir_all(dir.path().join("Core/Logs")).unwrap();
std::fs::write(dir.path().join("Core/Logs/world-console.log"), "ERROR [1146] Table 'acore_characters.playerbots_names' doesn't exist\nFATAL Could not prepare statements\n").unwrap();
let started = DriverOutcome { ok: true, code: None, exit_code: Some(0), human: None, output: "Worldserver and automatic bug reporting are ready.".into() };
let reason = startup_failure(dir.path(), &started);
assert!(reason.contains("playerbots_names"));
assert!(reason.contains("Core/Logs/world-console.log"));
assert!(reason.contains("Could not prepare statements"));
}
#[test]
fn startup_failure_keeps_the_launcher_reason_without_secrets() {
let dir = tempfile::tempdir().unwrap();