Skip to content

Conversation

@yujonglee
Copy link
Contributor

@yujonglee yujonglee commented Dec 5, 2025

Summary

The k6 WebSocket test was showing all zeros for most metrics because wsConnectionSuccess was recorded after ws.connect() returns, which only happens after the socket closes. When sessions are interrupted (test ends before the 5-minute SESSION_DURATION_MS), the code after ws.connect() never runs.

From the GitHub Actions logs:

running (3m01.2s), 0/3 VUs, 0 complete and 3 interrupted iterations

Changes:

  • Move wsConnectionSuccess.add(1) inside socket.on("open") callback so success is recorded immediately when connection opens
  • Record failure in error handler and as fallback after ws.connect() returns
  • Fix vus_max to use data.metrics.vus_max with fallback to VUS constant (was showing undefined)

Updates since last revision

Added message count metrics to track WebSocket activity:

  • ws_messages_sent: total outgoing messages (audio chunks + keepalive)
  • ws_messages_received: total incoming messages
  • ws_audio_chunks_sent: audio chunks specifically

These are recorded inside callbacks so they work even when sessions are interrupted. Added to both JSON report and text summary output.

Review & Testing Checklist for Human

  • Verify no double-counting of failures: The error handler records failure if !connectionOpened, and there's also a fallback check after ws.connect() returns. If an error occurs before connection opens, both paths could execute. Consider if this is the intended behavior.
  • Session duration still only recorded on close: wsConnectionDuration is still recorded in socket.on("close"), so it may still show 0 for interrupted sessions. This was not changed.
  • Run the k6 workflow manually to verify metrics are now recorded correctly when sessions are interrupted
  • Check Rate metric semantics: Confirm that recording success in on("open") and failure in error/fallback maintains correct rate calculation

Notes

The k6 WebSocket test was showing all zeros for most metrics because:
1. wsConnectionSuccess was recorded after ws.connect() returns, which only
   happens after the socket closes
2. When sessions are interrupted (test ends before SESSION_DURATION_MS),
   the code after ws.connect() never runs

Changes:
- Move wsConnectionSuccess.add(1) inside socket.on('open') callback
- Record failure (wsConnectionSuccess.add(0)) in error handler and fallback
- Fix vus_max to use metrics.vus_max or fallback to VUS constant

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote-storybook failed.

Name Link
🔨 Latest commit 6bf3bd2
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/6932a162ee9cb900090e2ea9

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote failed.

Name Link
🔨 Latest commit 6bf3bd2
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/6932a1622c0c260008e5fcfc

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

The k6 load test script adds explicit WebSocket connection state tracking and new message-related metrics (sent, received, audio_chunks_sent), refines success/failure recording for connection attempts, and updates summary reporting (vus_max source and text summary output).

Changes

Cohort / File(s) Summary
WebSocket Connection Tracking & Metrics
apps/k6/scripts/stt-live.js
Adds connectionOpened flag to track handshake success; records wsConnections, wsConnectionSuccess, wsMessagesSent, wsMessagesReceived, and wsAudioChunksSent; increments message counters on chunk sends, keep-alive, and incoming messages; on early errors emits zero success; runSession now returns connectionOpened.
Summary / Reporting Updates
apps/k6/scripts/stt-live.js
handleSummary now sources vus_max from data.metrics.vus_max?.values?.max with fallback to configured VUS; textSummary updated to include a Messages block showing Sent, Received, and Audio Chunks; client metrics structure expanded to include messages counters.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas requiring attention:
    • Correct initialization and lifecycle transitions of connectionOpened
    • Proper emission of zero-value for failed early connections and effects on metrics aggregation
    • Ensure changing runSession return semantics doesn't break callers or status logic
    • Verify vus_max extraction fallback behaves correctly when metric data is missing

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main fix: recording metrics inside callbacks to handle interrupted sessions.
Description check ✅ Passed The description comprehensively explains the problem, root cause, solution, and includes added message metrics with testing guidance.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1764923482-fix-k6-metrics

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
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

🧹 Nitpick comments (2)
apps/k6/scripts/stt-live.js (2)

133-144: Confirm that connectionOpened is the right success criterion for reconnects

runSession now returns connectionOpened, so the default function only increments wsReconnects and sleeps longer when the WebSocket never reaches the "open" state:

const success = runSession(data);

if (!success) {
  wsReconnects.add(1);
  sleep(5);
} else {
  sleep(1);
}

That means sessions that open successfully but then error/close early will not be treated as reconnect cases here (they’ll just start a new iteration after a short sleep).

If your intent is “reconnect aggressively only on connection-establishment failures”, this is fine. If you also want early-terminated sessions (open → immediate error/close) to count as reconnects, you may want a separate flag (e.g., sessionCompleted) or adjust the success condition / naming to make this explicit.


147-157: Prefer ?? over || for vus_max fallback to avoid treating 0 as missing

Here:

vus_max: data.metrics.vus_max?.values?.max || VUS,

using || will replace a legitimate 0 with VUS, which can misrepresent runs that report vus_max = 0 (e.g., very short or failed runs).

Safer to only fall back when the metric is null/undefined:

-    vus_max: data.metrics.vus_max?.values?.max || VUS,
+    vus_max: data.metrics.vus_max?.values?.max ?? VUS,

This keeps edge-case runs accurately reflected while still defaulting when the metric is absent.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 775c138 and f8144c2.

📒 Files selected for processing (1)
  • apps/k6/scripts/stt-live.js (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: fmt
  • GitHub Check: Devin

Track WebSocket message activity:
- ws_messages_sent: total outgoing messages (audio + keepalive)
- ws_messages_received: total incoming messages
- ws_audio_chunks_sent: audio chunks specifically

These metrics are recorded inside callbacks so they work even when
sessions are interrupted before completing.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Copy link
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: 0

♻️ Duplicate comments (1)
apps/k6/scripts/stt-live.js (1)

63-71: Avoid double-counting ws_connection_success failures between the error handler and the fallback

As written, a failed connection that triggers socket.on("error") before "open" will:

  • Add wsConnectionSuccess.add(0) in the error handler when !connectionOpened, and
  • Add another wsConnectionSuccess.add(0) in the final if (!connectionOpened) block after ws.connect returns.

That records two failures for a single attempted session and will skew the ws_connection_success rate and thresholds.

You likely want exactly one success/failure event per runSession attempt. A simple way is to track whether the outcome has already been recorded:

   let firstTranscriptTime = null;
   let loopCount = 0;
   let connectionOpened = false;
+  let connectionResultRecorded = false;
@@
     socket.on("open", () => {
       connectionOpened = true;
       wsConnections.add(1);
       wsConnectionSuccess.add(1);
+      connectionResultRecorded = true;
@@
     socket.on("error", (e) => {
       if (e.error() !== "websocket: close sent") {
         wsErrors.add(1);
-        if (!connectionOpened) {
-          wsConnectionSuccess.add(0);
-        }
+        if (!connectionOpened && !connectionResultRecorded) {
+          wsConnectionSuccess.add(0);
+          connectionResultRecorded = true;
+        }
         console.log(`[VU ${__VU}] Error: ${e.error()}`);
       }
     });
@@
-  if (!connectionOpened) {
-    wsConnectionSuccess.add(0);
-  }
+  if (!connectionResultRecorded) {
+    wsConnectionSuccess.add(0);
+  }

This keeps the Rate metric aligned with “one outcome per attempted session” and satisfies the “no double-counting failures” checklist item from the PR description.

Also applies to: 112-120, 132-141

🧹 Nitpick comments (1)
apps/k6/scripts/stt-live.js (1)

20-22: Message metrics wiring is consistent; consider whether to include CloseStream sends

The new message counters (wsMessagesSent, wsMessagesReceived, wsAudioChunksSent) are correctly:

  • Defined at Lines 20-22.
  • Incremented on audio chunk sends and KeepAlive sends (Lines 79-81, 90).
  • Incremented on every inbound message (Line 95).
  • Surfaced in handleSummary and textSummary (Lines 189-194, 286-290).

This gives a coherent view of WS traffic volume.

One small design question: the { type: "CloseStream" } send at Line 127 is not counted in wsMessagesSent. If you intend “Messages: Sent” to mean all outbound messages, you might optionally increment wsMessagesSent there as well; if you meant to track only steady-state traffic (audio + keepalives), the current behavior is fine, but it could be worth a brief comment in code or PR description for clarity.

Also applies to: 79-81, 90-90, 95-95, 189-194, 286-290

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8144c2 and e7b7a1b.

📒 Files selected for processing (1)
  • apps/k6/scripts/stt-live.js (9 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Devin
🔇 Additional comments (1)
apps/k6/scripts/stt-live.js (1)

163-163: vus_max fallback looks correct; minor note on || VUS edge case

Using data.metrics.vus_max?.values?.max || VUS fixes the previous undefined access and aligns with k6’s vus_max metric:

vus_max: data.metrics.vus_max?.values?.max || VUS,

This will correctly report the observed max VUs when present and fall back to the configured VUS when that metric is missing. The only theoretical edge case is if values.max could legitimately be 0, in which case || VUS would substitute VUS; in practice vus_max should never be 0 in a meaningful run, so this is acceptable.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
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.

2 participants