mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-16 04:18:17 +08:00
log(webchat): raise SSE timeout and error lifecycle logs
Raise WebChat SSE timeout and non-benign error lifecycle logs to INFO while keeping routine client disconnects at DEBUG, preserving detach-based subscriber lifecycle semantics.
This commit is contained in:
parent
55cf53b9b4
commit
a11c7ccb52
@ -196,14 +196,23 @@ public class WebChatController {
|
|||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
});
|
});
|
||||||
emitter.onTimeout(() -> {
|
emitter.onTimeout(() -> {
|
||||||
log.debug("[WebChat] SSE timeout: {}", conversationId);
|
// INFO: a timeout means the stream went idle past the SseEmitter
|
||||||
|
// budget, which is a key signal when diagnosing stream stalls.
|
||||||
|
log.info("[WebChat] SSE timeout (stream went idle past the emitter budget): {}", conversationId);
|
||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
// Explicitly complete after timeout so the servlet container does
|
// Explicitly complete after timeout so the servlet container does
|
||||||
// not rethrow AsyncRequestTimeoutException.
|
// not rethrow AsyncRequestTimeoutException.
|
||||||
emitter.complete();
|
emitter.complete();
|
||||||
});
|
});
|
||||||
emitter.onError(e -> {
|
emitter.onError(e -> {
|
||||||
log.debug("[WebChat] SSE error: {} - {}", conversationId, e.getMessage());
|
// INFO only for non-benign causes; a client simply closing the tab
|
||||||
|
// (broken pipe / connection reset) is routine and stays DEBUG so it
|
||||||
|
// doesn't flood production logs.
|
||||||
|
if (isClientDisconnect(e)) {
|
||||||
|
log.debug("[WebChat] SSE client disconnected: {} - {}", conversationId, e.getMessage());
|
||||||
|
} else {
|
||||||
|
log.info("[WebChat] SSE error: {} - {}", conversationId, e.getMessage());
|
||||||
|
}
|
||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1262,12 +1271,16 @@ public class WebChatController {
|
|||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
});
|
});
|
||||||
emitter.onTimeout(() -> {
|
emitter.onTimeout(() -> {
|
||||||
log.debug("[WebChat] approve SSE timeout: {}", conversationId);
|
log.info("[WebChat] approve SSE timeout (stream went idle past the emitter budget): {}", conversationId);
|
||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
emitter.complete();
|
emitter.complete();
|
||||||
});
|
});
|
||||||
emitter.onError(e -> {
|
emitter.onError(e -> {
|
||||||
log.debug("[WebChat] approve SSE error: {} - {}", conversationId, e.getMessage());
|
if (isClientDisconnect(e)) {
|
||||||
|
log.debug("[WebChat] approve SSE client disconnected: {} - {}", conversationId, e.getMessage());
|
||||||
|
} else {
|
||||||
|
log.info("[WebChat] approve SSE error: {} - {}", conversationId, e.getMessage());
|
||||||
|
}
|
||||||
streamTracker.detach(conversationId, emitter);
|
streamTracker.detach(conversationId, emitter);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1417,6 +1430,22 @@ public class WebChatController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when the SSE error is a routine client-side disconnect (closed tab,
|
||||||
|
* network drop) rather than a server-side failure. Used to keep the
|
||||||
|
* lifecycle log noise down: a visitor closing the tab is expected and
|
||||||
|
* stays DEBUG; anything else is worth an INFO line for production triage.
|
||||||
|
* Mirrors ChatController#isClientDisconnect.
|
||||||
|
*/
|
||||||
|
private static boolean isClientDisconnect(Throwable e) {
|
||||||
|
if (e instanceof IOException) return true;
|
||||||
|
String msg = e.getMessage();
|
||||||
|
if (msg == null) return false;
|
||||||
|
String lower = msg.toLowerCase();
|
||||||
|
return lower.contains("broken pipe") || lower.contains("connection reset")
|
||||||
|
|| lower.contains("client abort") || lower.contains("closed");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast a {@code tool_approval_resolved} event so the SDK clears its
|
* Broadcast a {@code tool_approval_resolved} event so the SDK clears its
|
||||||
* approval banner in real time. Shared by approve / deny / stop-sweep.
|
* approval banner in real time. Shared by approve / deny / stop-sweep.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user