Skip to content

fix: reduce WebSocket log noise and protect connection data #230

Closed
RohitKumar717 wants to merge 2 commits into
AOSSIE-Org:mainfrom
RohitKumar717:fix/cleanup-websocket-logs
Closed

fix: reduce WebSocket log noise and protect connection data #230
RohitKumar717 wants to merge 2 commits into
AOSSIE-Org:mainfrom
RohitKumar717:fix/cleanup-websocket-logs

Conversation

@RohitKumar717
Copy link
Copy Markdown

@RohitKumar717 RohitKumar717 commented Mar 1, 2026

Description -

Downgraded high-frequency WebSocket connection logs from 'logger.info' to 'logger.debug' to reduce log noise and protect sensitive connection data. The following logs were changed:

  • 'Upgrade request received from [IP]'
  • 'Localhost connection allowed'
  • 'Client connected from [IP]'

These logs fire on every single connection and cluttered the log output. Moving them to debug level means they only appear when debug logging is explicitly enabled.

Related Issue -

Closes #213

Testing -

  1. Run the server
  2. Connect a client via WebSocket
  3. Verify that connection logs no longer appear at info level
  4. Enable debug logging and confirm the logs still appear correctly

Checklist -

  • Code follows style guidelines ( verified )
  • Self-review completed (verified )
  • Tests added/updated (verified

Summary by CodeRabbit

  • New Features

    • Added screen sharing via WebRTC and integrated start/stop controls into the app.
  • Bug Fixes

    • Improved WebSocket error logging and added disconnection handling to clean up connections.
  • Chores

    • Optimized localhost connection flow to stop further processing when appropriate.
    • Adjusted logging verbosity for clearer diagnostics.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 1, 2026

Walkthrough

Adds a new React WebRTC hook for screen sharing, wires it into the root route, and updates WebSocket server logging and connection lifecycle handling (downgraded verbose logs, replaced console.error with logger.error, added close handler and early return for localhost upgrades). Also small package.json edits.

Changes

Cohort / File(s) Summary
Server WebSocket
src/server/websocket.ts
Downgraded high-frequency logs to debug, added early return for localhost upgrade handling, added ws.on("close") to stopMirror and log disconnects, replaced console.error with logger.error for WS errors.
WebRTC Hook (new)
src/hooks/useWebRTCProvider.ts
New React hook implementing screen-sharing via WebRTC: captures display media, creates RTCPeerConnection (Google STUN), adds tracks, sends ICE candidates and offer over provided WebSocket, exposes isSharing, startSharing, stopSharing.
Route wiring
src/routes/__root.tsx
Replaced useCaptureProvider with useWebRTCProvider and updated DesktopCaptureProvider usage to call the new hook with wsRef.
Manifest
package.json
Minor lines changed (+8/-4) — manifest edits included (no exported API changes).

Sequence Diagram(s)

sequenceDiagram
    participant User as User (UI)
    participant Hook as useWebRTCProvider
    participant PC as RTCPeerConnection
    participant WS as Signaling WebSocket
    participant Server as Remote Server

    User->>Hook: click "Start Sharing"
    Hook->>Hook: navigator.mediaDevices.getDisplayMedia
    Hook->>PC: create RTCPeerConnection (STUN)
    Hook->>PC: add tracks (local stream)
    PC->>WS: send ice-candidate (via wsRef)
    PC->>PC: createOffer / setLocalDescription
    Hook->>WS: send webrtc-offer (SDP)
    WS->>Server: forward offer
    Server->>WS: send webrtc-answer
    WS->>Hook: deliver answer
    Hook->>PC: setRemoteDescription (answer)
    PC->>PC: establish connection
    User->>Hook: click "Stop Sharing"
    Hook->>PC: close, stop tracks
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Typescript Lang

Poem

🐰
Hop, I shared my screen tonight,
Tracks and offers in the light,
WS sings the signaling song,
Peer connects and hums along,
Close the stream — a tidy bite.

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially addresses issue #213. It downgrades high-frequency connection logs to debug level and replaces console.error with logger.error in websocket.ts, but the raw summary shows additional unrelated changes to WebRTC functionality that appear outside the scope of the logging refactor issue. The PR introduces useWebRTCProvider hook and replaces useCaptureProvider, which are unrelated to the logging refactor objectives in issue #213. Remove these WebRTC-related changes or address them in a separate PR focused on that feature.
Out of Scope Changes check ⚠️ Warning The PR includes out-of-scope changes: introduction of useWebRTCProvider hook in src/hooks/useWebRTCProvider.ts and replacement of useCaptureProvider in src/routes/__root.tsx are unrelated to the logging refactor objective defined in issue #213. Separate the WebRTC screen sharing feature implementation into a distinct PR. Keep this PR focused solely on the WebSocket logging refactor to maintain clarity of scope and ease code review.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: reducing WebSocket log noise by downgrading connection logs to debug level and protecting sensitive data.
Description check ✅ Passed The description clearly explains the log level changes, specific logs modified, rationale, related issue #213, and testing steps. However, the provided description does not follow the repository's template structure (e.g., missing functional verification checklist).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/server/websocket.ts`:
- Line 127: The "Client disconnected" log should be downgraded to debug for
consistency with the recently-changed connect logging; locate the logger call
that emits the literal "Client disconnected" message in src/server/websocket.ts
(the same file where logger.debug(`Client connected from
${request.socket.remoteAddress}`) appears) and change the logger.info (or
logger.warn) invocation to logger.debug so both connect and disconnect events
use the same debug level.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bccde32 and b73aed6.

📒 Files selected for processing (1)
  • src/server/websocket.ts

Comment thread src/server/websocket.ts Outdated
// Localhost: only store token if it's already known (trusted scan)
// Remote: token is already validated in the upgrade handler
logger.info(`Client connected from ${request.socket.remoteAddress}`)
logger.debug(`Client connected from ${request.socket.remoteAddress}`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Good change, but consider consistency with disconnect logging.

The connection log is correctly downgraded to debug. However, line 364 still logs "Client disconnected" at info level. Since disconnect events fire just as frequently as connect events, consider downgrading that log to debug as well for consistency with the PR's noise-reduction goal.

🔧 Suggested fix for consistency
 		ws.on("close", () => {
 			stopMirror()
-			logger.info("Client disconnected")
+			logger.debug("Client disconnected")
 		})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/websocket.ts` at line 127, The "Client disconnected" log should be
downgraded to debug for consistency with the recently-changed connect logging;
locate the logger call that emits the literal "Client disconnected" message in
src/server/websocket.ts (the same file where logger.debug(`Client connected from
${request.socket.remoteAddress}`) appears) and change the logger.info (or
logger.warn) invocation to logger.debug so both connect and disconnect events
use the same debug level.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/__root.tsx (1)

1-15: ⚠️ Potential issue | 🟡 Minor

Missing "use client" directive.

This file uses React hooks (useEffect, useRef), accesses browser APIs (navigator.userAgent, localStorage), and renders interactive components. Per coding guidelines, files with client-side rendering features must include the "use client" directive at the top.

🛡️ Proposed fix
+"use client"
+
 import {
 	HeadContent,
 	Link,

As per coding guidelines: **/*.{ts,tsx,js,jsx}: NextJS: Ensure that "use client" is being used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/__root.tsx` around lines 1 - 15, This file uses client-only hooks
and browser APIs (useEffect, useRef, navigator.userAgent, localStorage) and must
be marked as a client component; add the "use client" directive as the very
first line of the file (before any imports) so React treats the module as
client-rendered; ensure this is applied to the module that declares
useEffect/useRef and imports ConnectionProvider and useWebRTCProvider so the
runtime and bundler know to include client-side behavior.
♻️ Duplicate comments (1)
src/server/websocket.ts (1)

366-369: 🛠️ Refactor suggestion | 🟠 Major

Downgrade disconnect log to debug for consistency with PR goals.

The PR downgrades connection logs to debug level to reduce noise, but both disconnect handlers still use logger.info. Since disconnect events fire just as frequently as connect events, downgrade this to logger.debug for consistency.

♻️ Proposed fix
 		ws.on("close", () => {
 			stopMirror()
-			logger.info("Client disconnected")
+			logger.debug("Client disconnected")
 		})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/websocket.ts` around lines 366 - 369, The disconnect handler
registered on the websocket (ws.on("close", ...)) uses logger.info; change that
call to logger.debug to match the PR's reduced-noise logging policy and be
consistent with the connect handler; update the closure that calls stopMirror()
and logger.info("Client disconnected") so it instead calls logger.debug("Client
disconnected") while leaving stopMirror() intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useWebRTCProvider.ts`:
- Around line 49-51: The catch block in useWebRTCProvider (the try/catch that
currently calls console.error("Failed to start WebRTC capture:", err)) should
use the project's structured logger instead of console.error; replace that call
with logger.error and include the error object and context message, and ensure
the module either imports the shared logger (e.g., import { logger } from '...')
or uses the injected/logger available in the hook (so the error is logged
consistently with other server logs).
- Around line 39-44: The offer send currently calls wsRef.current?.send(...)
unguarded; update the send in useWebRTCProvider (the block that constructs
{type: "webrtc-offer", offer}) to first verify wsRef.current?.readyState ===
WebSocket.OPEN before calling send, and otherwise handle the not-open case
(e.g., queue the offer, retry, or log an error) so the offer won't be silently
dropped.
- Around line 21-23: The track 'ended' event isn't handled so stopping
screen-share via browser leaves isSharing true; update the track setup in
startSharing (where stream.getTracks().forEach and pc.addTrack are used) to
attach a 'ended' listener on each track that calls stopSharing (or the shared
cleanup routine) to update isSharing and remove tracks/peer connections; to
avoid a circular reference, either define stopSharing before startSharing or
extract the cleanup logic into a separate function (e.g., cleanupSharing) and
call that from both stopSharing and the track 'ended' handler.

In `@src/server/websocket.ts`:
- Around line 127-130: Remove the duplicate close event handler that calls
stopMirror() and logs "Client disconnected": locate the earlier ws.on("close",
...) registration (the one that invokes stopMirror() and logger.info("Client
disconnected")) and delete the redundant ws.on("close", ...) block so
stopMirror() and logger.info are only executed once; ensure only the intended
close handler remains and that any necessary cleanup logic is preserved in the
retained handler.

---

Outside diff comments:
In `@src/routes/__root.tsx`:
- Around line 1-15: This file uses client-only hooks and browser APIs
(useEffect, useRef, navigator.userAgent, localStorage) and must be marked as a
client component; add the "use client" directive as the very first line of the
file (before any imports) so React treats the module as client-rendered; ensure
this is applied to the module that declares useEffect/useRef and imports
ConnectionProvider and useWebRTCProvider so the runtime and bundler know to
include client-side behavior.

---

Duplicate comments:
In `@src/server/websocket.ts`:
- Around line 366-369: The disconnect handler registered on the websocket
(ws.on("close", ...)) uses logger.info; change that call to logger.debug to
match the PR's reduced-noise logging policy and be consistent with the connect
handler; update the closure that calls stopMirror() and logger.info("Client
disconnected") so it instead calls logger.debug("Client disconnected") while
leaving stopMirror() intact.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b73aed6 and d6c5972.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/hooks/useWebRTCProvider.ts
  • src/routes/__root.tsx
  • src/server/websocket.ts

Comment on lines +21 to +23
stream.getTracks().forEach((track) => {
pc.addTrack(track, stream)
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle track ended event to sync isSharing state.

When users stop sharing via the browser's native "Stop sharing" button, the track fires an ended event but isSharing remains true. This causes UI state to become stale.

🛡️ Proposed fix: Add track ended listener
 		stream.getTracks().forEach((track) => {
 			pc.addTrack(track, stream)
+			track.onended = () => {
+				stopSharing()
+			}
 		})

Note: You'll need to define stopSharing before startSharing or extract the cleanup logic to avoid the circular reference.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useWebRTCProvider.ts` around lines 21 - 23, The track 'ended' event
isn't handled so stopping screen-share via browser leaves isSharing true; update
the track setup in startSharing (where stream.getTracks().forEach and
pc.addTrack are used) to attach a 'ended' listener on each track that calls
stopSharing (or the shared cleanup routine) to update isSharing and remove
tracks/peer connections; to avoid a circular reference, either define
stopSharing before startSharing or extract the cleanup logic into a separate
function (e.g., cleanupSharing) and call that from both stopSharing and the
track 'ended' handler.

Comment on lines +39 to +44
wsRef.current?.send(
JSON.stringify({
type: "webrtc-offer",
offer,
}),
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Check WebSocket readyState before sending offer.

Line 26 correctly checks wsRef.current?.readyState === WebSocket.OPEN before sending ICE candidates, but the offer is sent without this check. If the WebSocket is not open, the offer will silently fail to send.

🐛 Proposed fix
-		wsRef.current?.send(
-			JSON.stringify({
-				type: "webrtc-offer",
-				offer,
-			}),
-		)
+		if (wsRef.current?.readyState === WebSocket.OPEN) {
+			wsRef.current.send(
+				JSON.stringify({
+					type: "webrtc-offer",
+					offer,
+				}),
+			)
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
wsRef.current?.send(
JSON.stringify({
type: "webrtc-offer",
offer,
}),
)
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(
JSON.stringify({
type: "webrtc-offer",
offer,
}),
)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useWebRTCProvider.ts` around lines 39 - 44, The offer send
currently calls wsRef.current?.send(...) unguarded; update the send in
useWebRTCProvider (the block that constructs {type: "webrtc-offer", offer}) to
first verify wsRef.current?.readyState === WebSocket.OPEN before calling send,
and otherwise handle the not-open case (e.g., queue the offer, retry, or log an
error) so the offer won't be silently dropped.

Comment on lines +49 to +51
} catch (err) {
console.error("Failed to start WebRTC capture:", err)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using a structured logger instead of console.error.

The server-side code uses logger.error for consistency. Using console.error here works but diverges from the project's logging patterns. This is a minor inconsistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useWebRTCProvider.ts` around lines 49 - 51, The catch block in
useWebRTCProvider (the try/catch that currently calls console.error("Failed to
start WebRTC capture:", err)) should use the project's structured logger instead
of console.error; replace that call with logger.error and include the error
object and context message, and ensure the module either imports the shared
logger (e.g., import { logger } from '...') or uses the injected/logger
available in the hook (so the error is logged consistently with other server
logs).

Comment thread src/server/websocket.ts
Comment on lines +127 to +130
ws.on("close", () => {
stopMirror()
logger.info("Client disconnected")
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Duplicate close event handler will cause double execution.

A second ws.on("close") handler already exists at lines 366-369. Registering this additional handler means stopMirror() runs twice and "Client disconnected" is logged twice on each disconnect. This can cause unexpected behavior if stopMirror() has side effects.

Remove this duplicate handler and keep only the one at lines 366-369.

🐛 Proposed fix: Remove the duplicate handler
-		ws.on("close", () => {
-			stopMirror()
-			logger.info("Client disconnected")
-		})
-
-	
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ws.on("close", () => {
stopMirror()
logger.info("Client disconnected")
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/websocket.ts` around lines 127 - 130, Remove the duplicate close
event handler that calls stopMirror() and logs "Client disconnected": locate the
earlier ws.on("close", ...) registration (the one that invokes stopMirror() and
logger.info("Client disconnected")) and delete the redundant ws.on("close", ...)
block so stopMirror() and logger.info are only executed once; ensure only the
intended close handler remains and that any necessary cleanup logic is preserved
in the retained handler.

@RohitKumar717 RohitKumar717 closed this by deleting the head repository Mar 2, 2026
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.

Refactor Server-Side Logging

1 participant