Skip to content

Add application identity to USERAGENT payload (V2) - #4632

Open
cheenamalhotra wants to merge 19 commits into
mainfrom
dev/cheena/refactored-pancake
Open

Add application identity to USERAGENT payload (V2)#4632
cheenamalhotra wants to merge 19 commits into
mainfrom
dev/cheena/refactored-pancake

Conversation

@cheenamalhotra

@cheenamalhotra cheenamalhotra commented Sep 2, 2026

Copy link
Copy Markdown
Member

Fixes #3201

Implements USERAGENT payload version 2 with controlled application identifiers and driver-owned feature flags.

Summary

  • Application Id identifies middleware without allowing arbitrary user-agent text.
  • Driver Properties is a 64-bit driver-owned flag field. Bit 0 reports connection pool V2.
  • Both fields are always emitted as unpadded uppercase hexadecimal.

API

[CLSCompliant(false)]
public enum RegisteredApplication : ushort
{
    Unknown = 0,
    EntityFrameworkCore = 1,
    SemanticKernel = 2,
    ManagementStudio = 3,
    SqlManagementObjects = 4,
    DataTierApplicationFramework = 5,
    SqlToolsService = 6,
    AspNetCoreDistributedSqlServerCache = 7,
    EntityFramework = 8,
    AzureFunctionsSqlExtension = 9,
    OrleansAdoNet = 10,
    DurableTaskSqlServer = 11,
    SqlPackage = 12,
    DataApiBuilder = 13
}

public class SqlConnection
{
    public RegisteredApplication RegisteredApplication { get; set; }
}
Range Use
0x0001-0x7FFF Microsoft-defined large-scale apps
0x8000-0xBFFF Small-scale use
0xC000-0xFFFF Public/developer use

Set RegisteredApplication before Open or OpenAsync. Assigning it while the connection is opening or open throws InvalidOperationException. Unregistered values can use the appropriate range through an enum cast.

Payload

2|MS-MDS|{Driver Version}|{Arch}|{OS Type}|{OS Info}|{Runtime Info}|{App Id}|{Driver Properties}

Example:

2|MS-MDS|7.0.0|X64|Windows|Microsoft Windows 10.0.26100|.NET 9.0.4|1|1

With no application set, Application Id is 0.

Behavior

  • Application identity is client-supplied telemetry and must not be used for authorization or other security decisions.
  • Application identity is not part of the pool key. A pooled physical connection reports the application that created it; background Min Pool Size connections report Unknown.
  • Cloned connections preserve RegisteredApplication.
  • This replaces the earlier unshipped SqlClientAgent and RegisterSqlClientAgent design.

Tests

  • USERAGENT formatting, limits, caching, and 64-bit flags
  • Registered and developer-range application identifiers
  • Clone, connecting/open state, and pooled-attribution behavior
  • LOGIN7 payloads across sync and async open paths, with and without USERAGENT acknowledgment

Checklist

  • Tests added or updated
  • Public API changes documented
  • Verified user_agent field is set correctly in Azure SQL DB telemetry.
  • No breaking changes introduced

Adds an optional agent identifier to the USERAGENT login feature extension
so known middleware (EF Core, SSMS, DacFx, ...) can be told apart from
direct SqlClient use.

- New public `SqlClientAgent` enum and
  `SqlConnection.RegisterSqlClientAgent(SqlClientAgent)`.
- Registration is process-wide and allowed once, so an application cannot
  overwrite or spoof an agent set by a library.
- Can also be set from App.config via a `SqlClientAgent` section.
- Payload format bumped to version 2; the agent id is appended as an
  optional 8th part only when registered.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI balanced review requested due to automatic review settings September 2, 2026 19:20
@cheenamalhotra
cheenamalhotra requested a review from a team as a code owner September 2, 2026 19:20
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Sep 2, 2026
@cheenamalhotra cheenamalhotra added this to the 7.1.0 milestone Sep 2, 2026
@cheenamalhotra cheenamalhotra added the Public API 🆕 Issues/PRs that introduce new APIs to the driver. label Sep 2, 2026

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 LOGIN7 length race, enum validation, test isolation, and documentation issues remain unresolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds process-wide middleware identification to the USERAGENT login payload.

Changes:

  • Adds SqlClientAgent registration and configuration APIs.
  • Extends USERAGENT v2 with an optional agent ID.
  • Adds tests, documentation, and samples.
File summaries
File Description
src/Microsoft.Data.SqlClient/tests/UnitTests/UserAgentTests.cs Tests payload versioning and agent encoding.
src/Microsoft.Data.SqlClient/tests/UnitTests/SqlClientAgentTests.cs Tests identifiers and configuration parsing.
src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/ConnectionTests.cs Verifies LOGIN7 agent transmission.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlClientAgentConfigurationTests.cs Tests configuration precedence.
src/Microsoft.Data.SqlClient/tests/FunctionalTests/app.config Registers the test agent.
src/Microsoft.Data.SqlClient/src/Resources/Strings.resx Adds registration error messages.
src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs Exposes generated resource accessors.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/UserAgent.cs Builds and caches agent payloads.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs Writes agent payloads into LOGIN7.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs Creates agent-related exceptions.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs Adds the registration API.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientAgent.cs Defines agents and registration logic.
src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs Updates the public API contract.
doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml Documents registration behavior.
doc/samples/SqlConnection_RegisterSqlClientAgent.cs Demonstrates middleware registration.
Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Suppressed comments (1)

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlClientAgentConfigurationTests.cs:20

  • The test intent is written as ordinary comments, but test methods require XML <summary> documentation. Convert this explanation to an XML summary so the new test follows the test documentation contract.
        [ConditionalFact(typeof(TestUtility), nameof(TestUtility.IsNetFramework))]
        public void AppConfigAgent_PreventsProgrammaticRegistration()
  • Files reviewed: 14/15 changed files
  • Comments generated: 4
  • Review effort level: Balanced

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

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs Outdated
Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientAgent.cs Outdated
- Capture the USERAGENT payload once in SendPreLoginHandshake and pass it
  to WriteLoginData, so a concurrent registration cannot make the reserved
  feature length disagree with the bytes written.
- Restrict RegisterSqlClientAgent to declared enum members. Undeclared
  numeric ids remain valid in config, where forward compatibility matters.
- Serialize ConnectionTests via SimulatedServerTestCollection; it now
  mutates process-wide registration.
- Add XML summary to SqlClientAgentConfigurationTests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 2, 2026 19:39

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

Malformed App.config handling needs isolated regression coverage before approval.

Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientAgent.cs:198

  • The new tests validate Parse directly, but none exercises this catch through LoadFromAppConfig. Consequently, the stated guarantee that an invalid or malformed application configuration cannot turn first use into a TypeInitializationException has no regression coverage. Add an isolated-process/AppDomain test with a bad SqlClientAgent section that triggers registration loading and verifies the failure is consumed.

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/UserAgent.cs:39

  • Value is always built with agentId: null, so it never has the optional eighth part; only GetUcs2Bytes can return that transmitted form. Describing the Value property itself with the optional format makes its contract inconsistent with the implementation and the seven-part tests. Clarify that this is the base value and that the encoded login payload may append the agent ID.
    ///     The format is pipe ('|') delimited into 7 parts, plus an optional
    ///     8th part:
    ///
    ///     <code>2|MS-MDS|{Driver Version}|{Arch}|{OS Type}|{OS Info}|{Runtime Info}[|{Agent Id}]</code>

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlClientAgentConfigurationTests.cs:24

  • Convert the preceding ordinary comment into an XML <summary> for this test method. The repository's test documentation rules require behavior-focused XML summaries on every test method.
        [ConditionalFact(typeof(TestUtility), nameof(TestUtility.IsNetFramework))]
        public void AppConfigAgent_PreventsProgrammaticRegistration()
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

- Change SqlClientAgent to int-backed so it needs no CLSCompliant
  attribute, which the notsupported assembly rejects (CS3021). Identifiers
  are still bounded to a positive 16-bit range.
- Extract LoadAgent so the configuration failure paths are testable, and
  cover malformed config, invalid id, wrong section type, missing section,
  and a throwing loader.
- Clarify that UserAgent.Value never carries the agent id; only the login
  payload does.
- Convert the App.config test comment to an XML summary.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 2, 2026 19: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.

🟡 Changes recommended

The public enum’s underlying type and CLS annotations do not match the advertised 16-bit API contract.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientAgent.cs Outdated
- Remove the now-unnecessary CLSCompliant attribute from the
  implementation method.
- Document the 16-bit identifier contract on the enum, since it is no
  longer implied by the underlying type.
- Assert the underlying type is Int32 so the CLS-compliant surface cannot
  regress.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 2, 2026 19:56
@cheenamalhotra cheenamalhotra moved this from To triage to In review in SqlClient Board Sep 2, 2026

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

Public API, configuration, and wire-payload changes require final human review, and two documentation nits remain.

Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Suppressed comments (2)

src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.cs:603

  • The PR's API example still declares SqlClientAgent : ushort, but this public surface (and UnderlyingType_IsInt32) intentionally publishes an Int32-backed enum. Please update the PR description to omit : ushort or use : int, so consumers are not given an API signature that differs from the assembly.
public enum SqlClientAgent

src/Microsoft.Data.SqlClient/tests/UnitTests/UserAgentTests.cs:221

  • Document the bytes parameter and return value for this new test helper. The repository's test documentation rules require XML <param> and <returns> elements for helper methods where applicable.
    /// <summary>
    /// Decode a UCS-2 encoded payload back to its string form.
    /// </summary>
    private static string Decode(ReadOnlyMemory<byte> bytes) =>
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

doc/samples builds against the published Microsoft.Data.SqlClient package,
so it cannot reference an API that has not shipped yet. Move the example
into the XML docs alongside the existing App.config example and drop the
compiled sample file.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 2, 2026 20:12

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

The PR description incorrectly documents SqlClientAgent as having a ushort underlying type.

Review details

Files not reviewed (1)

  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Suppressed comments (1)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientAgent.cs:23

  • The PR's API example still advertises public enum SqlClientAgent : ushort, while this declaration, the reference surface, and the new underlying-type test intentionally publish Int32. Because the enum's underlying type is observable, update the PR description to show public enum SqlClientAgent (or : int) and describe 16 bits as the validated identifier range rather than the underlying type.
public enum SqlClientAgent
  • Files reviewed: 13/14 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@cheenamalhotra

Copy link
Copy Markdown
Member Author

CI failure analysis — none of the 6 failing legs are caused by this change.

sqlclient-pr (4 legs: linux net8/net9, windows net9/net10)
All four fail on the same test, SqlCommandCancelTest.CancelAndDisposePreparedCommand_Tcp, with a server-side error:

Transaction (Process ID nn) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.

The test runs a 6-way cross join over sys.objects, so it takes catalog locks and deadlocks when parallel legs run DDL against the same shared database. Known flaky area — the last two commits to this file are "Address additional flaky tests" (#4305) and "Address flaky DEBUG assertions" (#4085).

PR-SqlClient-Project (2 legs) — both fail before any test runs:

  • MacOSLatest_Sql25 net9_ManagedSNI_3: the Configure SQL Server [macOS] setup task exits 1.
  • Win22_Azure_Sql net9_NativeSNI_3: Build AKV Provider hits MSB4166: Child node "2" exited prematurely / Restore canceled! (agent/MSBuild crash, 4m runtime).

Why this change can't be the cause: it only appends an optional 8th part to the LOGIN7 USERAGENT payload. No manual test references UserAgent/USERAGENT or asserts on the payload format, and none of these failures touch login. The equivalent legs that do exercise this code all pass, including all three Win11_ARM64_Azure_Sql net462 legs which validate the new App.config path on .NET Framework.

Re-running to clear the flakes.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 9, 2026 20:40

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 asynchronous open path lacks required coverage, and a new test helper has incomplete XML documentation.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/Microsoft.Data.SqlClient/tests/UnitTests/UserAgentTests.cs:268

  • Add <param> and <returns> documentation for this new test helper. The repository's test documentation rules require those elements for helpers with parameters and return values.
  • Files reviewed: 16/16 changed files
  • Comments generated: 1
  • Review effort level: Balanced


/// <include file='../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientApp.xml' path='docs/members[@name="SqlClientApp"]/SqlClientApp/*' />
public enum SqlClientApp
[System.CLSCompliantAttribute(false)]

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.

Since this type is opt-in telemetry for existing apps, I don't think the lack of CLS compliance is a problem. Any existing apps relying on CLS compliance will need to take explicit steps to use this enum and the new SqlConnection.SqlClientApp property - I'm fine with that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed. The enum and property remain explicitly non-CLS-compliant.

[InlineData((ushort)0, (ulong)0, "2|A|B|X64|C|D|E|0|0")]
[InlineData((ushort)7, (ulong)1, "2|A|B|X64|C|D|E|7|1")]
[InlineData((ushort)0x00AB, (ulong)0, "2|A|B|X64|C|D|E|AB|0")]
[InlineData(ushort.MaxValue, (ulong)ushort.MaxValue, "2|A|B|X64|C|D|E|FFFF|FFFF")]

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.

ulong.MaxValue ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Updated the theory to use ulong.MaxValue directly in f087c29.

Expose RegisteredApplication, use field-backed storage, cover sync and async login paths, and exercise the full 64-bit driver property range.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 10, 2026 16:23

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 documented pooled and background-creation telemetry behavior lacks automated coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

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

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 10, 2026 16:51

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

The irreversible public API and protocol payload change warrant final human compatibility review.

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

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 10, 2026 17:37

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 documented connecting-state and pooled-attribution behaviors still lack regression coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs:779

  • This null-owner fallback and the deliberate omission from the pool key define the documented pooled-attribution behavior, but no added test exercises either pooled reuse across different application IDs or background Min Pool Size creation. Please cover those paths with a simulated-server/pool test so a future factory or pool change cannot silently attribute a physical connection to the wrong application.
                metrics: Metrics,
                registeredApplication: sqlOwningConnection?.RegisteredApplication ?? RegisteredApplication.Unknown);
  • Files reviewed: 16/16 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs Outdated
@cheenamalhotra cheenamalhotra moved this from Waiting for customer to In review in SqlClient Board Sep 10, 2026
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 10, 2026 17:55

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 property setter can race with Open, causing the reported property value to differ from the identity sent during login.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

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

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: efbed43f-1014-45d7-a9f6-9f04711c281e
Copilot AI review requested due to automatic review settings September 10, 2026 18:05

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

The public API and wire-protocol changes warrant final human compatibility review despite comprehensive coverage.

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

@mdaigle mdaigle 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.

Type naming and payload structure look good to me.

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

Labels

Public API 🆕 Issues/PRs that introduce new APIs to the driver.

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

Feature: New API to capture Client Information for telemetry

7 participants