Skip to content

Remove DiagnosticSource.Write trim warnings in SqlDiagnosticListener - #4688

Open
charlesroddie wants to merge 1 commit into
dotnet:mainfrom
charlesroddie:trim-diagnostic-listener
Open

charlesroddie wants to merge 1 commit into
dotnet:mainfrom
charlesroddie:trim-diagnostic-listener

Conversation

@charlesroddie

@charlesroddie charlesroddie commented Sep 15, 2026

Copy link
Copy Markdown

Description

Removes the 15 IL2026 warnings in SqlDiagnosticListener, one per DiagnosticSource.Write<T> call.

The [RequiresUnreferencedCode] attribute on Write<T> is in fact untrue! Write<T> does no reflection intrinsically: it passes the payload to subscribers as object. The reason it's there is that subscribers could reflect over the payload. However that is their responsibility, and they will receive their own trim warnings when they do.

So this attribute was always misguided, and so suppressing it is common, e.g. in DiagnosticsHandler in dotnet/runtime and HostingApplicationDiagnostics in ASP.NET Core. Following those examples, all events now go through one private WriteEvent<T> helper with an UnconditionalSuppressMessage on IL2026.

This helper's T has the same PublicProperties annotation as Write<T>. This is pragmatic. This keeps existing consumers working, so this PR doesn't change behaviour under trimming and only corrects trim warnings. Some of these consumers, including the current OpenTelemetry SqlClient implementation, not only require these properties but suppress their own warnings, so removing this annotation would not only stop code from working under NativeAOT, but do so silently.

The claims above were checked in a NativeAOT test app: see details below.

Trim/AOT warnings with -p:IsAotCompatible=true (unique by location and code):

TFM Before After
net8.0 50 35
net9.0 52 37

No public API changes. Independent of #4683 and #4684.

Issues

Part of #1947.

Testing

  • Built net462, net8.0 and net9.0 with -p:IsAotCompatible=true; no warnings remain in SqlDiagnosticListener.cs.
  • DiagnosticTest (21 tests covering connection open and command execution events, sync, async and error paths) passes on net8.0.
  • Transaction commit/rollback events have no automated tests; they use the same helper.
NativeAOT verification of Description claims

A console app (net10.0, PublishAot, win-x64) subscribed to SqlClientDiagnosticListener with a reflecting observer (GetType().GetProperty, once unsuppressed and once with UnconditionalSuppressMessage) and with OpenTelemetry.Instrumentation.SqlClient 1.18.0 plus an in-memory exporter, then ran SELECT 1 and SELECT 1/0 against LocalDB. It was published against main, this PR, and this PR with the PublicProperties annotation removed.

main This PR Annotation removed
SqlDiagnosticListener trim warnings 9 0 0
Payload Command/Connection readable by reflection Yes Yes No
OpenTelemetry spans 2 2 0
OpenTelemetry trim warnings 0 0 0
  • The app's unsuppressed reflection produced IL2075 in all three builds; its suppressed reflection produced none.
  • main shows 9 warnings rather than 15 because the app doesn't use transactions.
  • In all NativeAOT builds the error span lacks db.response.status_code (present under JIT), because SqlException.Number isn't reflectable. This PR doesn't change that.

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings September 15, 2026 11:41
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Sep 15, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The trimming guarantees need a publish-trimmed test covering the preserved nested members.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Centralizes diagnostic event writes to suppress redundant trim warnings while preserving reflected payload members.

Changes:

  • Routes all 15 diagnostic writes through WriteEvent<T>.
  • Adds trimming annotations and nested-member dependencies.
File summaries
File Description
SqlDiagnosticListener.cs Adds the annotated diagnostic-write helper.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI review requested due to automatic review settings September 15, 2026 12:31
@charlesroddie
charlesroddie force-pushed the trim-diagnostic-listener branch from 0760c29 to f621741 Compare September 15, 2026 12:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

A trimmed runtime test is needed to validate that the reflection-dependent members survive linking.

Review details

Suppressed comments (1)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Diagnostics/SqlDiagnosticListener.cs:490

  • The PR's core runtime guarantee is not exercised: an AOT-compatible build only shows that IL2026 is suppressed, while the existing diagnostic tests run untrimmed and cannot prove that these two reflected members survive linking. Please add a trimmed-publish smoke test that subscribes to an error event, reflects SqlException.Number, and resolves/invokes SqlConnection.RetrieveStatistics; otherwise a misplaced or ineffective dependency annotation would pass all current validation but break OpenTelemetry in trimmed applications.
        [DynamicDependency(nameof(SqlException.Number), typeof(SqlException))]
        [DynamicDependency(nameof(SqlConnection.RetrieveStatistics), typeof(SqlConnection))]
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Route the 15 diagnostic events through one WriteEvent helper that
carries the PublicProperties annotation on T required by Write<T> and
suppresses IL2026 once. SqlClient does no reflection when writing
events; subscribers that reflect over payloads are responsible for
their own reflection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 15, 2026 20:50
@charlesroddie
charlesroddie force-pushed the trim-diagnostic-listener branch from f621741 to 9be4c69 Compare September 15, 2026 20:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused refactoring preserves existing event behavior while correctly centralizing trim annotations and suppression.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@charlesroddie
charlesroddie marked this pull request as ready for review September 15, 2026 21:24
@charlesroddie
charlesroddie requested a review from a team as a code owner September 15, 2026 21:24
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To triage

Development

Successfully merging this pull request may close these issues.

4 participants