Skip to content

JS-1597 fix generated-source observability reporting#7215

Draft
francois-mora-sonarsource wants to merge 5 commits into
masterfrom
fix/generated-code-detection-08-generated-source-observability
Draft

JS-1597 fix generated-source observability reporting#7215
francois-mora-sonarsource wants to merge 5 commits into
masterfrom
fix/generated-code-detection-08-generated-source-observability

Conversation

@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

What changed

  • propagated generatedSources telemetry through the gRPC converter and protobuf schema
  • stopped treating generated files omitted from request.files as excluded in observability summaries
  • added regression coverage for protobuf serialization and partial-analysis observability counts

Why

  • gRPC-based analyses were dropping the new generated-source telemetry before downstream consumers could read it
  • partial analyses with an explicit file subset were overstating excluded generated files even when those files were still in scope and simply not requested

Validation

  • npx tsx --tsconfig packages/tsconfig.test.json --test packages/analysis/tests/telemetry.test.ts packages/analysis/tests/jsts/project-metadata/generated-sources.test.ts packages/grpc/tests/analyze-project-convert.test.ts
  • npx tsc -p packages/tsconfig.json --noEmit --pretty false

@hashicorp-vault-sonar-prod
Copy link
Copy Markdown

hashicorp-vault-sonar-prod Bot commented Jun 5, 2026

JS-1597

Comment thread packages/analysis/src/common/filter/filter-path.ts
Comment thread packages/analysis/src/file-stores/generated-sources.ts Outdated
Comment thread packages/analysis/src/file-stores/generated-sources.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Ruling Report

No changes to ruling expected issues in this PR

Comment thread packages/analysis/src/file-stores/generated-sources.ts
Comment thread packages/analysis/src/file-stores/generated-sources.ts
@francois-mora-sonarsource francois-mora-sonarsource force-pushed the fix/generated-code-detection-08-generated-source-observability branch from 2e8326d to b5602a2 Compare June 5, 2026 15:30
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Jun 5, 2026

Code Review ✅ Approved 5 resolved / 5 findings

Updates the observability pipeline to correctly propagate telemetry and fix misreported counts for partially requested files. Resolved redundant branches and logging overhead, with no remaining open findings.

✅ 5 resolved
Quality: Redundant duplicate OUT_OF_SCOPE branches in classifyFilePathInternal

📄 packages/analysis/src/common/filter/filter-path.ts:106-114
In classifyFilePathInternal the final two branches both return { status: 'OUT_OF_SCOPE' }:

if (mainClassification === 'OUT_OF_SCOPE' || testClassification === 'OUT_OF_SCOPE') {
  return { status: 'OUT_OF_SCOPE' };
}
return { status: 'OUT_OF_SCOPE' };

The explicit conditional is dead because the unconditional fallthrough returns the same value. This is harmless functionally but suggests an intended distinction (e.g. NO_MATCH vs OUT_OF_SCOPE) that was collapsed and may confuse future maintainers. Consider removing the conditional, or, if NO_MATCH was meant to be surfaced distinctly to observability, modeling it explicitly.

Quality: Unreachable else branch in buildGeneratedSourceObservability

📄 packages/analysis/src/file-stores/generated-sources.ts:357-371 📄 packages/analysis/src/file-stores/generated-sources.ts:261 📄 packages/analysis/src/file-stores/generated-sources.ts:281-287
In the per-file loop of buildGeneratedSourceObservability, the final else branch (file classified MAIN/TEST, not tagged, and present in requestedFilePaths) counts the file as excluded. This branch is effectively unreachable: familyByFile (taggedFamilyByFile) is derived from filterAnalyzableGeneratedFiles(derivedFamilyByFile, analyzableFiles), which tags every resolved file that is present in analyzableFiles. So any resolved file that is in requestedFilePaths is already tagged and hits the first continue branch. When analyzableFiles is undefined, requestedFilePaths is undefined and every resolved file is tagged as well. The dead branch is harmless but obscures the intended classification logic; consider removing it or adding a clarifying comment about why an in-scope, requested, untagged file is treated as excluded.

Quality: Observability summary logged at INFO on every state refresh

📄 packages/analysis/src/file-stores/generated-sources.ts:262-269 📄 packages/analysis/src/file-stores/generated-sources.ts:444-457
refreshFilteredState calls logGeneratedSourceObservability, which emits an INFO line for the summary plus one INFO line per generated-source family. refreshFilteredState runs on each request-files-key change (from isInitialized) and during postProcess. In long-lived SonarLint sessions where generated-source state is re-derived on filesystem events / repeated analyses, this re-emits the same INFO lines on every refresh, producing log noise for projects that use code generators. Consider logging the summary at DEBUG, or only logging when the computed telemetry actually changes from the previously logged value.

Performance: Dedup key JSON.stringifies full observability each postProcess

📄 packages/analysis/src/file-stores/generated-sources.ts:533-541 📄 packages/analysis/src/file-stores/generated-sources.ts:270
createGeneratedSourceObservabilityLogKey serializes the entire observability object on every postProcess/refreshFilteredState call. Note families[].excludedPaths and families[].outOfScopePaths hold all matching paths (sampling only happens later in formatSamplePaths), so for large projects with many generated outputs this stringifies large arrays purely to compute a dedup key. Since this runs once per refresh (not in a hot per-file loop) the impact is bounded, but a cheaper key (e.g. derived from the telemetry counts plus a hash of path lengths) would avoid the full serialization.

Quality: lastLoggedObservabilityKey not reset on cache clear

📄 packages/analysis/src/file-stores/generated-sources.ts:224-232 📄 packages/analysis/src/file-stores/generated-sources.ts:136-143 📄 packages/analysis/src/file-stores/generated-sources.ts:80 📄 packages/analysis/src/file-stores/generated-sources.ts:270-274
clearDerivedState() resets observabilityTelemetry to empty but does not reset the new lastLoggedObservabilityKey, and neither does clearCache(). After a cache invalidation (config change, relevant fs event), if a re-derivation produces observability identical to the last logged one, the dedup check at L271 will suppress the log even though the derived state was just rebuilt. This is inconsistent with the surrounding reset logic. If suppression across invalidations is intentional, that's fine; otherwise reset the key in clearDerivedState() so a fresh analysis re-logs.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next
Copy link
Copy Markdown

sonarqube-next Bot commented Jun 5, 2026

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