Skip to content

Downgrade expected WebSocket disconnect exceptions from Error to Debug#8

Merged
nnhy merged 2 commits into
masterfrom
copilot/fix-websocket-exception-logging
Jul 20, 2026
Merged

Downgrade expected WebSocket disconnect exceptions from Error to Debug#8
nnhy merged 2 commits into
masterfrom
copilot/fix-websocket-exception-logging

Conversation

Copilot AI commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Normal WebSocket disconnections (server restart, network jitter, client close) were generating ObjectDisposedException, SocketException, and WebSocketException at ERROR level in the DoPull receive loops, flooding logs and masking real errors.

Changes

WsChannel.cs (non-NETCOREAPP client)

  • Added protected static IsNormalDisconnect(SocketError) helper — matches ConnectionReset (10054), ConnectionAborted (10053), OperationAborted (995)
  • New catch clauses before the generic Exception handler:
    • ObjectDisposedException → silent break
    • SocketException matching normal codes → Debug log + break

WsChannelCore.cs (NETCOREAPP client, System.Net.WebSockets)

  • Same ObjectDisposedException and SocketException handling (reuses IsNormalDisconnect from base class)
  • Additional catch for WebSocketException when WebSocketErrorCode == ConnectionClosedPrematurely or socket.State == Aborted → Debug log + break, replacing the previous ad-hoc inline suppression
// Before: all unexpected exceptions logged as Error
catch (Exception ex)
{
    if (source.IsCancellationRequested) break;
    if (ex is not WebSocketException || socket.State != WebSocketState.Aborted)
        _client.Log?.Error("[{0}]WebSocket异常[{1}]: {2}", ...);
    if (ex is WebSocketException) break;
}

// After: normal disconnects caught early, only genuine errors reach Error
catch (ObjectDisposedException) { break; }
catch (WebSocketException wex) when (
    wex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely ||
    socket.State == WebSocketState.Aborted)
{
    _client.Log?.Debug("[{0}]WebSocket连接断开[{1}]", _client.Name, wex.WebSocketErrorCode);
    break;
}
catch (SocketException sex) when (IsNormalDisconnect(sex.SocketErrorCode))
{
    _client.Log?.Debug("[{0}]WebSocket连接断开[{1}]", _client.Name, sex.SocketErrorCode);
    break;
}
catch (Exception ex)
{
    if (source.IsCancellationRequested) break;
    _client.Log?.Error("[{0}]WebSocket异常[{1}]: {2}", ...);
    if (ex is WebSocketException) break;
}

When a WebSocket connection closes normally (server restart, network
jitter, client close), exceptions such as ObjectDisposedException,
SocketException (ConnectionReset/ConnectionAborted/OperationAborted)
and WebSocketException (ConnectionClosedPrematurely / Aborted state)
are expected and should not flood the log at ERROR level.

Changes:
- WsChannel.cs: Add ObjectDisposedException silent break, add
  IsNormalDisconnect helper, downgrade normal SocketException codes
  (ConnectionReset 10054, ConnectionAborted 10053, OperationAborted 995)
  to Debug log in DoPull receive loop.
- WsChannelCore.cs: Same ObjectDisposedException and SocketException
  handling; additionally catch WebSocketException with
  ConnectionClosedPrematurely or Aborted socket state and downgrade
  to Debug, simplifying the redundant state check in the generic handler.

Fixes NewLifeX/NewLife.Remoting#<issue>
Copilot AI changed the title [WIP] Fix excessive error logs on WebSocket disconnection Downgrade expected WebSocket disconnect exceptions from Error to Debug Jul 20, 2026
Copilot AI requested a review from nnhy July 20, 2026 14:14
Copilot finished work on behalf of nnhy July 20, 2026 14:18
@nnhy
nnhy marked this pull request as ready for review July 20, 2026 15:02
Copilot AI review requested due to automatic review settings July 20, 2026 15:02
@nnhy
nnhy merged commit 0031cf8 into master Jul 20, 2026
@nnhy
nnhy deleted the copilot/fix-websocket-exception-logging branch July 20, 2026 15:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces log noise in the WebSocket client receive loops by treating expected disconnect-related exceptions (e.g., disposal, connection resets, premature close) as normal termination conditions, logging them at Debug (or silently breaking) instead of Error.

Changes:

  • Added explicit handling for ObjectDisposedException and “normal” SocketException disconnect codes in WsChannel.DoPull.
  • Added explicit handling for ObjectDisposedException, “normal” SocketException, and selected WebSocketException disconnect scenarios in WsChannelCore.DoPull.
  • Introduced a shared IsNormalDisconnect(SocketError) helper to standardize what’s considered a normal disconnect.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
NewLife.Remoting/Clients/WsChannel.cs Adds normal-disconnect detection (IsNormalDisconnect) and downgrades common disconnect exceptions to non-error handling in the receive loop.
NewLife.Remoting/Clients/WsChannelCore.cs Adds normal-disconnect handling for WebSocketException/SocketException in the NETCOREAPP receive loop to avoid flooding Error logs on expected disconnects.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +146 to +148
catch (WebSocketException wex) when (
wex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely ||
socket.State == WebSocketState.Aborted)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebSocket 连接断开时产生大量异常日志刷屏

3 participants