chore(hooks): tracing::warn on hook failures (#455 follow-up)
Hook failures were silent — the executor returned a `HookResult` with `success=false`, but every call site discards it with `let _ = ...`. Operators tailing `deepseek` had no visibility into hook errors short of running each hook command by hand. Centralizes the logging inside `HookExecutor::execute` so every fire site benefits without sprinkling instrumentation. Logs through `tracing::warn!` with structured fields (`hook`, `event`, `exit_code`, `duration_ms`, `error`, `stderr_head`) so operators can `RUST_LOG=warn deepseek` and immediately see which hooks are misbehaving. Successful runs log nothing — `tool_call_before` / `tool_call_after` fire on every tool dispatch, so per-call success logging would be unreadably noisy. No behavioral change for users with no hooks (the function fast-paths out before reaching this branch). No behavioral change for users with passing hooks. Failed hooks still respect `continue_on_error` and the surrounding loop is unchanged.
This commit is contained in:
@@ -521,6 +521,24 @@ impl HookExecutor {
|
||||
self.execute_sync(hook, &env_vars)
|
||||
};
|
||||
|
||||
// Log failures via tracing so operators tailing
|
||||
// `deepseek` with `RUST_LOG=warn` can see hook errors
|
||||
// without instrumenting each call site. Successful runs
|
||||
// log nothing (would be too noisy on per-tool events).
|
||||
if !result.success {
|
||||
let label = result.name.as_deref().unwrap_or("(unnamed)");
|
||||
tracing::warn!(
|
||||
target: "hooks",
|
||||
hook = label,
|
||||
event = event.as_str(),
|
||||
exit_code = ?result.exit_code,
|
||||
duration_ms = result.duration.as_millis() as u64,
|
||||
error = result.error.as_deref().unwrap_or(""),
|
||||
stderr_head = %result.stderr.lines().next().unwrap_or(""),
|
||||
"hook failed"
|
||||
);
|
||||
}
|
||||
|
||||
let should_continue = result.success || hook.continue_on_error;
|
||||
results.push(result);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user