Skip to content

[x-telemetry] Skip runtime resolution when telemetry is disabled#22078

Merged
aemartos merged 5 commits into
mui:masterfrom
aemartos:aemartos/sto-113-telemetry-skip-fetch-when-disabled
Apr 14, 2026
Merged

[x-telemetry] Skip runtime resolution when telemetry is disabled#22078
aemartos merged 5 commits into
mui:masterfrom
aemartos:aemartos/sto-113-telemetry-skip-fetch-when-disabled

Conversation

@aemartos

Copy link
Copy Markdown
Member

Fixes #22070

Summary

  • Check shouldSendTelemetry before calling getTelemetryContext() in sender.ts, so disabled telemetry doesn't trigger fetch('/package.json')
  • Add tests verifying no fetch is made when telemetry is disabled (via settings or CI)

Context

When telemetry was disabled via muiXTelemetrySettings.disableTelemetry(), env var, or CI environment, a fetch('/package.json') request was still being made on every telemetry event. This caused issues in test environments that monitor unhandled requests.

The root cause: sender.ts called getTelemetryContext() (which resolves runtimePackageNameHash via fetch('/package.json')) before checking whether telemetry should be sent.

Fix

Reorder the checks in sendMuiXTelemetryEvent:

  1. Load the base context (no runtime resolution, no fetch)
  2. Check shouldSendTelemetry with the base context, early exit if disabled
  3. Only then call getTelemetryContext() to resolve runtime values

The base context already has everything shouldSendTelemetry needs (isCI is set at postinstall time), so no additional work is required for the eligibility check.

@aemartos aemartos self-assigned this Apr 14, 2026
@aemartos aemartos requested review from LukasTy and hasdfa and removed request for hasdfa April 14, 2026 07:55
@aemartos aemartos added type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. scope: x-telemetry Changes related to the @mui/x-telemetry. labels Apr 14, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Apr 14, 2026

Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)

Details of bundle changes

Deploy preview

https://deploy-preview-22078--material-ui-x.netlify.app/


Check out the code infra dashboard for more information about this PR.

@LukasTy LukasTy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. 👌
The 2nd and 3rd Claude observations could be worth checking.

Claude Opus 4.6 review

Summary

The fix is correct and well-motivated. The core change in sender.ts reorders the logic so the eligibility check happens before the expensive getTelemetryContext() call (which triggers fetch('/package.json')).

Correctness Analysis

The key question is: does shouldSendTelemetry() work correctly with the base context (before runtime resolution)?

Looking at what shouldSendTelemetry actually checks:

  1. typeof window === 'undefined' — no context needed
  2. getTelemetryEnvConfigValue('IS_COLLECTING') — no context needed (this is where disableTelemetry() sets the flag via settings.ts)
  3. telemetryContext.traits.isCI — set at postinstall time by ci-info, never modified by getTelemetryContext()

And getTelemetryContext() only adds: sessionId, anonymousId, runtimePackageNameHash, projectId, fingerprint — none of which are used by shouldSendTelemetry.

Additionally, since telemetryContext from ../context is a singleton (the same object getTelemetryContext() mutates and returns), baseTelemetryContext and the resolved context are literally the same reference. So the check is guaranteed to produce the same result either way.

Things that look good

  • The payload still uses the fully resolved context (with runtimePackageNameHash, fingerprint, etc.) — only the eligibility check was moved earlier
  • The new beforeEach resets for runtimePackageNameHash and runtimePackageNameHashResolved prevent test pollution from the new tests that set these to null/false
  • Both disabling paths are tested (programmatic disableTelemetry() and CI environment)

Minor observations (non-blocking)

  1. Dynamic vs static import — The new await import('../context') follows the existing pattern of dynamic imports in sendMuiXTelemetryEvent. However, ../context is an extremely lightweight module (just a plain object, no side effects), and other lightweight modules like getTelemetryEnvConfigValue and fetchWithRetry are already imported statically at the top of the file. A static import telemetryContext from '../context' would be simpler and avoid the async overhead on every call. Not critical since it's consistent with the get-context import pattern, but worth considering.

  2. Type import inconsistencyTelemetryContextType is still imported from './get-context' (line 1), while the value is now imported from '../context'. Both resolve to the same type (since get-context re-exports it from ../context), so no bug, but importing both from '../context' would be cleaner.

  3. Pre-existing test cleanup gap — The existing test "should not send telemetry when opted out via settings" (line 89) calls disableTelemetry() but never cleans up. It only works because the next test happens to call enableTelemetry(). The PR's new test correctly calls enableTelemetry() at the end, which is good. Worth noting afterEach doesn't reset the telemetry settings — fragile test ordering is a pre-existing issue, not introduced here.

Verdict

Approve — the fix is correct, the tests cover the important cases, and the change is minimal and focused. The minor observations above are non-blocking style preferences.

@LukasTy LukasTy changed the title [telemetry] skip runtime resolution when telemetry is disabled [telemetry] Skip runtime resolution when telemetry is disabled Apr 14, 2026
@aemartos

Copy link
Copy Markdown
Member Author

@LukasTy suggestions addressed!

@aemartos aemartos merged commit 6ed367e into mui:master Apr 14, 2026
21 checks passed
@aemartos aemartos deleted the aemartos/sto-113-telemetry-skip-fetch-when-disabled branch April 14, 2026 10:39
arminmeh pushed a commit to arminmeh/mui-x that referenced this pull request Apr 29, 2026
@oliviertassinari oliviertassinari changed the title [telemetry] Skip runtime resolution when telemetry is disabled [x-telemetry] Skip runtime resolution when telemetry is disabled Jun 8, 2026
@oliviertassinari oliviertassinari added type: bug It doesn't behave as expected. and removed type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. labels Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: x-telemetry Changes related to the @mui/x-telemetry. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[x-telemetry] v9 Even when telemetry is disabled, a HTTP request to "package.json" is made

3 participants