chore: enforce -Error suffix on sendTelemetryError event names#1941
chore: enforce -Error suffix on sendTelemetryError event names#1941
-Error suffix on sendTelemetryError event names#1941Conversation
Adds two `no-restricted-syntax` rules to `.eslintrc.json` that flag any
`sendTelemetryError` call whose first argument is a string literal —
or a `TelemetryEvents[...]` enum lookup — that does not end in `Error`.
Dynamic first args (variables, computed expressions, template literals)
are deliberately left unchecked because their runtime value can't be
validated statically.
Why: ~30 of ~33 existing call sites already follow the convention
(`compileNodePythonError`, `extensionActivationError`,
`registerDBTProjectError`, ...). The convention makes App Insights
queries trivially distinguishable between event-name patterns
(`endsWith("Error")` vs other), and was reinforced by mdesmet's review
on #1940 (renamed `unhandledRejection` → `catchAllError`). Without a
lint rule, the next non-conforming call lands at review time rather
than dev time.
Renames the four pre-existing violations so the rule lands green:
- `formatDbtModelApplyDiffFailed` → `formatDbtModelApplyDiffError`
- `columnLevelLineageRequestTimeout` → `columnLevelLineageRequestTimeoutError`
- `TelemetryEvents["QueryHistory/Cleared"]` → `TelemetryEvents["QueryHistory/ClearError"]`
- `"unhandlederror"` (test fixture) → `"unhandledRejectionError"`
App Insights impact: dashboards or saved queries keying off the
old event names need to be updated. None of the four event names show
up in production cluster reports above the noise floor; the rename
will cause a brief gap rather than a silent loss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
WalkthroughEnforces a telemetry naming convention requiring error event names to end with "Error": adds ESLint rules, adds ChangesTelemetry Naming Convention Enforcement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Bundle Size Reportdarwin-arm64: 74.2 MB
linux-x64: 75.9 MB
win32-x64: 76.8 MB
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.eslintrc.json:
- Around line 28-29: Update the ESLint rule selector that targets
sendTelemetryError usages so it explicitly matches the first argument access on
TelemetryEvents; replace the current selector string (which uses the child
combinator and MemberExpression) with one that constrains to
CallExpression[callee.property.name='sendTelemetryError'] >
MemberExpression[object.name='TelemetryEvents'] that is specifically at
arguments.0 (i.e., use a path like
CallExpression[callee.property.name='sendTelemetryError'] >
:matches(MemberExpression)[arguments.0.type] or an equivalent AST selector that
targets arguments.0) so only the first parameter is validated; keep references
to sendTelemetryError and TelemetryEvents to locate the rule in .eslintrc.json
and ensure the message remains unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 34456460-6320-4588-9547-7f88fdb8c82d
📒 Files selected for processing (6)
.eslintrc.jsonsrc/document_formatting_edit_provider/dbtDocumentFormattingEditProvider.tssrc/services/dbtLineageService.tssrc/telemetry/events.tssrc/test/suite/telemetryService.test.tssrc/webview_provider/queryResultPanel.ts
Address @coderabbitai review on PR #1941. Previous form used a `>` combinator which matches any direct `MemberExpression` child of the `CallExpression` whose `object.name='TelemetryEvents'`. In practice this only matches the first argument (since the second arg is the error object, not a TelemetryEvents lookup), but the explicit `[arguments.0.object.name=...][arguments.0.property.value!=...]` form is tighter and removes any chance of false positives if a caller ever passes `TelemetryEvents[...]` in a later position. Verified by temporarily reverting the `QueryHistory/ClearError` rename and confirming the new selector still fires. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ Tests — All Passed |
Summary
Adds an ESLint rule that fails on
sendTelemetryErrorcalls whose first argument is a string literal — or aTelemetryEvents[...]enum lookup — that doesn't end inError. Renames the four pre-existing violations so the rule lands green.Follow-up to #1940, where @mdesmet's review surfaced
unhandledRejection→catchAllErrorand the broader naming convention. Without a lint rule, the next non-conforming call gets caught at review time, not dev time.Why this convention
~30 of ~33 existing
sendTelemetryErrorcall sites already follow the-Errorsuffix:It makes App Insights queries trivially distinguishable between error events and event events (
endsWith("Error")vs other), and is whattelemetry/index.ts:37enforces at runtime for the${eventName}Errorwrapper. The lint rule pulls the same constraint up to dev-time for directsendTelemetryErrorcalls.What this PR does
1. Lint rule —
.eslintrc.jsonTwo
no-restricted-syntaxselectors:{ "selector": "CallExpression[callee.property.name='sendTelemetryError'][arguments.0.type='Literal'][arguments.0.value!=/Error$/]", "message": "First argument to sendTelemetryError must be an event name ending in 'Error'..." }, { "selector": "CallExpression[callee.property.name='sendTelemetryError'] > MemberExpression[object.name='TelemetryEvents'][property.value!=/Error$/]", "message": "TelemetryEvents key passed to sendTelemetryError must end in 'Error'..." }The first selector catches inline string literals. The second catches
TelemetryEvents["Foo/NotError"]lookups by inspecting theMemberExpressionproperty's literal value at lint time.Dynamic first args are deliberately not flagged — variables (
name), template literals (`${eventName}Error`),as-cast member access (params.eventName as string), etc. Their runtime value can't be validated statically; the existing rules cover the cases that ARE statically checkable, and the wrapper attelemetry/index.ts:37(${eventName}Error) already enforces the suffix at runtime for indirect callers.2. Renames so the rule lands green
formatDbtModelApplyDiffFailedformatDbtModelApplyDiffErrordbtDocumentFormattingEditProvider.ts:91,104columnLevelLineageRequestTimeoutcolumnLevelLineageRequestTimeoutErrordbtLineageService.ts:487TelemetryEvents["QueryHistory/Cleared"]TelemetryEvents["QueryHistory/ClearError"]events.ts:62,queryResultPanel.ts:415"unhandlederror"(test fixture)"unhandledRejectionError"telemetryService.test.ts:80,86App Insights impact
The rename changes the event name written to App Insights for these four cases. Anyone with saved queries or dashboards keying off the old names needs to update them. None of the four event names appear above the noise floor in current production cluster reports (verified via the Channel-closed triage that motivated #1940), so the rename causes a brief gap rather than a silent loss.
Test plan
npx eslint 'src/**/*.ts'before rename: 4no-restricted-syntaxerrors flagged (the four call sites above)npx eslint 'src/**/*.ts'after rename: 0no-restricted-syntaxerrors. The remaining 7 errors are pre-existing prettier/prettier issues inbigQueryCostEstimate.test.tsandtelemetryService.test.tsconfirmed present onmaster— unrelatedgrep -r 'formatDbtModelApplyDiffFailed\|columnLevelLineageRequestTimeout"\|QueryHistory/Cleared\|"unhandlederror"' src/: 0 matches — all old names replaced🤖 Generated with Claude Code
Summary by CodeRabbit