Skip to content

chore(llc): send sfu stats for thermal and low power mode#1221

Open
Brazol wants to merge 2 commits intomainfrom
chore/sfu-stats-thermal-low-power
Open

chore(llc): send sfu stats for thermal and low power mode#1221
Brazol wants to merge 2 commits intomainfrom
chore/sfu-stats-thermal-low-power

Conversation

@Brazol
Copy link
Copy Markdown
Contributor

@Brazol Brazol commented Apr 23, 2026

Summary by CodeRabbit

  • New Features
    • Added thermal state and battery mode monitoring to RTC statistics telemetry (when enabled)
    • Optimized stats reporting with faster initial reports followed by steady-state intervals for improved responsiveness
    • Added call lifecycle tracing for accept, reject, and leave actions to improve diagnostics

@Brazol Brazol requested a review from a team as a code owner April 23, 2026 15:48
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0f553650-7c3d-4011-bfcc-def9db10ed0a

📥 Commits

Reviewing files that changed from the base of the PR and between ac39d7e and 78a3b04.

📒 Files selected for processing (2)
  • packages/stream_video/lib/src/call/call.dart
  • packages/stream_video/lib/src/call/session/call_session.dart
✅ Files skipped from review due to trivial changes (2)
  • packages/stream_video/lib/src/call/session/call_session.dart
  • packages/stream_video/lib/src/call/call.dart

📝 Walkthrough

Walkthrough

Adds device-level tracing for thermal and battery mode transitions to the SFU stats reporter (gated by statsOptions.enableRtcStats), changes reporting cadence to emit several early short-delay reports before switching to periodic reporting, and surfaces device trace slices in the rtcStats payload; call lifecycle methods now emit call traces.

Changes

Cohort / File(s) Summary
Device Telemetry & Stats Reporting Enhancement
packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart
Adds a private _deviceTracer (enabled by statsOptions.enableRtcStats) to emit traces for thermal and battery-mode changes; modifies run() to schedule initial rapid sends via _initialReportingDelays then switch to periodic reporting; includes device trace slices in rtcStats payload; disposes tracer in stop(); routes send flow through _invokeSendStats() and preserves error swallowing with verbose logs.
Call lifecycle tracing
packages/stream_video/lib/src/call/call.dart, packages/stream_video/lib/src/call/session/call_session.dart
Adds session traces: call.accept in accept(), call.reject with reason?.value in reject(), and call.leave with optional reason in CallSession.leave—all recorded immediately before existing coordinator/websocket actions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I hopped a trace through heat and drain,
Noting battery naps and thermal gain,
Rapid pings at first, then steady song,
Call whispers logged as they move along, 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is entirely missing, lacking all required template sections (Goal, Implementation details, Testing, Contributor Checklist). Add a comprehensive pull request description following the template with Goal, Implementation details, Testing explanation, and complete the Contributor Checklist.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding thermal and low power mode stats reporting to SFU stats collection.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/sfu-stats-thermal-low-power

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

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

Caution

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

⚠️ Outside diff range comments (1)
packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart (1)

36-49: ⚠️ Potential issue | 🟡 Minor

Initial thermal state is never traced.

_deviceTracer.trace('device.thermalState', ...) only fires inside the onThermalStatusChanged listener, so the thermal state at the moment the reporter starts (or any state the device is already in when subscribing) is not captured in traces — only subsequent transitions are. This mirrors the _lastLowPowerMode pattern, but unlike low-power-mode (which is polled each sendSfuStats cycle), thermal state will appear absent from traces for devices that never transition during the call.

Consider emitting an initial trace after subscribing, e.g. by reading/seeding the current ThermalStatus once, or by tracing it on the first sendSfuStats cycle alongside the power-mode trace.

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

In `@packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart` around
lines 36 - 49, The reporter subscribes to Thermal().onThermalStatusChanged but
never emits the current thermal state at startup, so initial state is missing
from traces; after creating _thermalStatusSubscription (or immediately after the
try block succeeds) read the current ThermalStatus (e.g., call
Thermal().thermalStatus or otherwise obtain the current status) and set
_thermalStatus and call _deviceTracer.trace('device.thermalState',
_thermalStatus.name) to seed the initial value; alternatively, ensure
sendSfuStats emits the thermal state if _thermalStatus is null (similar to the
_lastLowPowerMode pattern) so the first sendSfuStats call traces the initial
thermal state.
🧹 Nitpick comments (1)
packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart (1)

115-121: try/catch in _invokeSendStats cannot catch async failures.

sendSfuStats() returns a Future and is not awaited here, so any asynchronous error it raises will not be intercepted by this synchronous try/catch — only errors thrown synchronously before the first await would be. In practice sendSfuStats already wraps its body in its own try/catch, so this wrapper is effectively dead code. Consider either removing it, or switching to .catchError / unawaited(...) with a proper async handler to make the intent explicit.

♻️ Suggested simplification
-  void _invokeSendStats() {
-    try {
-      sendSfuStats();
-    } catch (e) {
-      _logger.v(() => 'Failed to send SFU stats');
-    }
-  }
+  void _invokeSendStats() {
+    unawaited(sendSfuStats());
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart` around
lines 115 - 121, The try/catch in _invokeSendStats cannot catch async errors
from sendSfuStats because sendSfuStats returns a Future; either remove the dead
synchronous try/catch or make the intent explicit: 1) if you want
fire-and-forget, call sendSfuStats().catchError((e, st) => _logger.v(() =>
'Failed to send SFU stats: $e')) (or wrap with unawaited(...) and attach a
catchError), or 2) if you want to await and handle errors inline, make
_invokeSendStats async and use try { await sendSfuStats(); } catch (e, st) {
_logger.v(() => 'Failed to send SFU stats: $e'); } — update the code around
_invokeSendStats and sendSfuStats accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart`:
- Around line 36-49: The reporter subscribes to Thermal().onThermalStatusChanged
but never emits the current thermal state at startup, so initial state is
missing from traces; after creating _thermalStatusSubscription (or immediately
after the try block succeeds) read the current ThermalStatus (e.g., call
Thermal().thermalStatus or otherwise obtain the current status) and set
_thermalStatus and call _deviceTracer.trace('device.thermalState',
_thermalStatus.name) to seed the initial value; alternatively, ensure
sendSfuStats emits the thermal state if _thermalStatus is null (similar to the
_lastLowPowerMode pattern) so the first sendSfuStats call traces the initial
thermal state.

---

Nitpick comments:
In `@packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart`:
- Around line 115-121: The try/catch in _invokeSendStats cannot catch async
errors from sendSfuStats because sendSfuStats returns a Future; either remove
the dead synchronous try/catch or make the intent explicit: 1) if you want
fire-and-forget, call sendSfuStats().catchError((e, st) => _logger.v(() =>
'Failed to send SFU stats: $e')) (or wrap with unawaited(...) and attach a
catchError), or 2) if you want to await and handle errors inline, make
_invokeSendStats async and use try { await sendSfuStats(); } catch (e, st) {
_logger.v(() => 'Failed to send SFU stats: $e'); } — update the code around
_invokeSendStats and sendSfuStats accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6726338-8716-4b88-9a7a-1ad13f50cee3

📥 Commits

Reviewing files that changed from the base of the PR and between 4a2e21a and ac39d7e.

📒 Files selected for processing (1)
  • packages/stream_video/lib/src/call/stats/sfu_stats_reporter.dart

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 39.13043% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 5.79%. Comparing base (4a2e21a) to head (78a3b04).

Files with missing lines Patch % Lines
...m_video/lib/src/call/stats/sfu_stats_reporter.dart 40.00% 12 Missing ⚠️
packages/stream_video/lib/src/call/call.dart 50.00% 1 Missing ⚠️
...tream_video/lib/src/call/session/call_session.dart 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main   #1221      +/-   ##
========================================
+ Coverage   5.77%   5.79%   +0.02%     
========================================
  Files        676     676              
  Lines      49335   49345      +10     
========================================
+ Hits        2848    2860      +12     
+ Misses     46487   46485       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

1 participant