Skip to content

Conversation

@christerswahn
Copy link
Collaborator

@christerswahn christerswahn commented Oct 28, 2025

This is a backwards-compatible change that opens up the analytics configuration and sending behavior to be overridden by subclasses.

Summary by CodeRabbit

  • New Features

    • Dynamic analytics enablement that determines and applies analytics settings at startup and can change behavior before commands run.
  • Refactor

    • Centralized analytics handling to ensure events are only emitted when enabled, with consistent routing across help, error, and command flows and clearer behavior documentation.

@christerswahn christerswahn requested a review from Isakdl October 28, 2025 11:26
@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Centralizes analytics in BetterCommandRunner: makes _onAnalyticsEvent final, adds _analyticsEnabled state initialized in the constructor, introduces async determineAnalyticsSettings() to set analytics before run, and routes all analytics emissions through sendAnalyticsEvent() with a public onAnalyticsEvent getter and analyticsEnabled() accessor.

Changes

Cohort / File(s) Summary
Analytics enablement & routing
packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart
Added private bool _analyticsEnabled; made _onAnalyticsEvent final; added public getter onAnalyticsEvent, analyticsEnabled() method, sendAnalyticsEvent(String) method, and async determineAnalyticsSettings(); initialize _analyticsEnabled in constructor; run() now awaits determineAnalyticsSettings(); replaced direct _onAnalyticsEvent calls with sendAnalyticsEvent() across invalid-usage/help/command-execution/command-not-found flows; removed in-run mutation of _onAnalyticsEvent; updated global options reference to this.onAnalyticsEvent.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI process
  participant Runner as BetterCommandRunner
  participant Analytics as OnAnalyticsEvent (nullable)

  rect rgb(230,245,255)
    CLI->>Runner: instantiate(onAnalyticsEvent?)
    Runner-->>Analytics: store final _onAnalyticsEvent
    Runner->>Runner: set _analyticsEnabled from constructor
  end

  rect rgb(245,255,230)
    CLI->>Runner: run(args)
    Runner->>Runner: await determineAnalyticsSettings()
    alt analyticsEnabled == true
      Runner->>Analytics: sendAnalyticsEvent("run_started")
    else analyticsEnabled == false
      Note right of Runner: analytics suppressed
    end
    Runner->>Runner: dispatch & execute command
    alt help / invalid / not-found / error
      Runner->>Analytics: sendAnalyticsEvent("<event>")  %% emitted only if enabled
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Extra attention areas:
    • Ensure determineAnalyticsSettings() is always awaited before any analytics emission.
    • Verify all previous _onAnalyticsEvent sites were replaced and nullability handled.
    • Confirm analyticsEnabled() semantics (may change after run() starts) are documented and acceptable.

Suggested reviewers

  • Isakdl

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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat(cli_tools): Make the analytics behavior customizable" directly and clearly aligns with the main changes in the changeset. The PR objectives confirm this is a backwards-compatible change that opens up analytics configuration and sending behavior to be overridden by subclasses, and the file changes demonstrate this intent through new public methods like determineAnalyticsSettings() (which can be overridden) and sendAnalyticsEvent(), along with new getters for controlling analytics behavior. The title is concise, specific enough for teammates to understand the primary change when scanning history, and avoids vague or generic phrasing.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f94b7f and 4cff50f.

📒 Files selected for processing (1)
  • packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart (10 hunks)

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

@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

🧹 Nitpick comments (1)
packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart (1)

210-218: Consider adding error handling for analytics callback failures.

If onAnalyticsEvent throws an exception, it will propagate from sendAnalyticsEvent(). This is particularly problematic at line 322 and 337 where it's called from an unawaited future—unhandled exceptions there can cause issues in Dart. Since analytics failures shouldn't disrupt the main flow, consider wrapping the callback invocation in a try-catch.

Apply this diff to add defensive error handling:

 void sendAnalyticsEvent(final String event) {
   if (analyticsEnabled()) {
-    onAnalyticsEvent?.call(event);
+    try {
+      onAnalyticsEvent?.call(event);
+    } catch (_) {
+      // Silently ignore analytics errors to prevent disrupting the main flow
+    }
   }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1614922 and 2f94b7f.

📒 Files selected for processing (1)
  • packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart (10 hunks)
🔇 Additional comments (7)
packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart (7)

69-70: LGTM: Clean initialization of analytics state.

The addition of _analyticsEnabled and making _onAnalyticsEvent final provides clear separation between the callback and the enabled state, allowing for proper customization.

Also applies to: 161-161


220-242: LGTM: Well-designed extension point.

This method provides a clean customization point for subclasses to implement custom analytics logic (e.g., user consent prompts). The default implementation correctly checks both the callback presence and the configuration flag.


254-276: LGTM: Proper sequencing of analytics initialization.

The placement of determineAnalyticsSettings() after configuration resolution but before command execution ensures analytics state is correctly established. The centralized error handling with sendAnalyticsEvent() is clean.


278-288: LGTM: Consistent analytics flow.

The migration to sendAnalyticsEvent() ensures all analytics go through the centralized, customizable path.


308-351: LGTM: Clean centralization of analytics emission.

The refactoring successfully centralizes all analytics through sendAnalyticsEvent(), making the behavior consistently customizable. The asynchronous analytics sending pattern is appropriate for avoiding impact on the main execution path.


172-172: Good use of the public API.

Using the public onAnalyticsEvent getter instead of the private field maintains consistency with the new public interface design.


202-205: LGTM: Clear documentation of state change behavior.

The comment appropriately warns about the mutable nature of the analytics state, which is important for users of this API to understand.

Copy link

@Isakdl Isakdl left a comment

Choose a reason for hiding this comment

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

LGTM

@christerswahn christerswahn merged commit a540919 into main Oct 28, 2025
9 of 10 checks passed
@christerswahn christerswahn deleted the ces-dev branch October 28, 2025 13:00
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.

3 participants