Skip to content

feat: advertise qdrant-dotnet in the User-Agent - #124

Merged
Anush008 merged 2 commits into
mainfrom
feat/user-agent
Jun 17, 2026
Merged

feat: advertise qdrant-dotnet in the User-Agent#124
Anush008 merged 2 commits into
mainfrom
feat/user-agent

Conversation

@qdrant-cloud-bot

Copy link
Copy Markdown
Contributor

Summary

The .NET SDK currently sets no Qdrant-branded User-Agent. The only token on the wire is the one Grpc.Net.Client injects, e.g.:

grpc-dotnet/2.71.0 (.NET 8.0.4; CLR 8.0.4; net8.0; linux; x64)

Because of that, server-side tooling cannot attribute traffic to the .NET client. Concretely, the Qdrant Cloud auth sidecars expose a client_requests_total{client,version} metric resolved from the User-Agent, and .NET requests land in the other bucket instead of dotnet.

This PR makes the SDK advertise a qdrant-dotnet/<version> token.

Approach

Grpc.Net.Client does not allow replacing the User-Agent via gRPC metadata (it only appends), so the token is added at the HTTP layer with a small DelegatingHandler (UserAgentHandler) wired into QdrantChannel.ForAddress. The resulting header looks like:

grpc-dotnet/2.71.0 (...) qdrant-dotnet/1.18.0
  • Version is resolved from the assembly informational version (stamped by MinVer at build time), with build metadata (+<sha>) stripped.
  • The handler adds rather than clears, so the gRPC/runtime information is preserved, and it de-dupes so a re-sent request doesn't accumulate duplicate tokens.
  • Wired for net6.0/netstandard2.0. On .NET Framework (net462), where the channel's HTTP handler must be configured manually (WinHttpHandler, per the README), the original behavior is preserved to avoid disturbing the finicky HTTP/2 setup.

Tests

Added UserAgentHandlerTests (pure unit tests, no Qdrant server needed):

  • adds the qdrant-dotnet/<version> token
  • preserves an existing grpc-dotnet token
  • does not duplicate the token when a request is re-sent (retry)

Notes

  • Could not compile locally (no .NET SDK in this environment); relying on CI (net8.0 test run + net462/net6.0/netstandard2.0 build) to validate.

Made with Cursor

The SDK previously set no Qdrant-branded User-Agent, so the only token on the
wire was the gRPC library's own "grpc-dotnet/<version>". Server-side tooling
(e.g. the Qdrant Cloud auth sidecars' client metrics) therefore could not
attribute traffic to the .NET client.

Grpc.Net.Client does not allow replacing the User-Agent through gRPC metadata,
so a DelegatingHandler now adds a "qdrant-dotnet/<version>" token at the HTTP
layer. The version is resolved from the assembly informational version (stamped
by MinVer). The handler is wired into QdrantChannel.ForAddress for net6.0 and
netstandard2.0; on .NET Framework, where the channel handler must be configured
manually, the original behavior is preserved.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Robert-Stam
Robert-Stam requested a review from Anush008 June 17, 2026 07:09
@Robert-Stam Robert-Stam self-assigned this Jun 17, 2026

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

Pushed some simplification.

LGTM!

@Anush008
Anush008 merged commit 6f23091 into main Jun 17, 2026
6 checks passed
@Anush008
Anush008 deleted the feat/user-agent branch June 17, 2026 10:37
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.

3 participants