fix: Report a distinct User-Agent for the async client - #516
Merged
Conversation
The async client shipped reusing the sync 'PythonClient/<version>' User-Agent, so LaunchDarkly could not tell async traffic apart from sync. Since sync and async ship in one package, the User-Agent token is the distinguishing signal. Add an ASYNC_USER_AGENT token 'PythonAsyncClient' and thread it through the async request paths (AsyncSSEFactory streaming headers, and the async feature requester, FDv2 polling, and event processor request headers) by parameterizing the shared _base_headers / _headers helpers. Sync behavior is unchanged. Register the new token in .sdk_metadata.json under the existing python-server-sdk entry, since async has no independent package. Implements SDK-2658. The analytics/event name 'python-server-sdk-async' already ships; billing confirmed it does not key off the User-Agent.
jsonbailey
marked this pull request as ready for review
September 3, 2026 14:31
jsonbailey
added a commit
that referenced
this pull request
Sep 3, 2026
keelerm84
approved these changes
Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
The async client (
AsyncLDClient) shipped reusing the synchronousPythonClient/<version>User-Agent, so LaunchDarkly cannot distinguish async traffic from sync. Because sync and async ship in the same package, the User-Agent token is the signal that tells them apart.This adds a distinct async token
PythonAsyncClientand threads it through every async request path.Changes
impl/http.py: addSYNC_USER_AGENT/ASYNC_USER_AGENTconstants;_base_headers(config, user_agent=SYNC_USER_AGENT).impl/util.py:_headers(config, user_agent=SYNC_USER_AGENT)passes the token through.ASYNC_USER_AGENT:impl/aio/transport.py—AsyncSSEFactorystreaming headersimpl/datasource/async_feature_requester.pyimpl/datasourcev2/async_polling.pyimpl/events/async_event_processor.py.sdk_metadata.json: register the token on the existingpython-server-sdkentry →userAgents: ["PythonClient", "PythonAsyncClient"].Sync behavior is unchanged (the default token is still
PythonClient).Design note
SDK-2658 originally proposed a separate
python-server-sdk-asyncsdk-meta registry entry. We chose to keep a single entry and add the async token to itsuserAgentsarray instead, because async has no independent package and is not a separately-tracked feature.The analytics/event SDK name
python-server-sdk-asyncalready ships (async_client.py); billing confirmed it does not key off the User-Agent, so this change is safe and additive.Tests
New
testing/impl/test_user_agent.pylocks the exact wire tokens for both sync and async via_base_headers/_headers.mypy/isort/pycodestyleclean; touched-component suites pass.Implements SDK-2658.
Note
Overview
Async
AsyncLDClienttraffic previously used the samePythonClient/<version>User-Agent as the sync client, so LaunchDarkly could not tell them apart in one package. This PR introducesPythonAsyncClientand wires it through shared header helpers while keeping sync defaults unchanged.SYNC_USER_AGENT/ASYNC_USER_AGENTare defined inimpl/http.py;_base_headersand_headerstake an optionaluser_agent(defaultPythonClient). Async paths passASYNC_USER_AGENT: SSE inimpl/aio/transport.py, FDv1 polling inasync_feature_requester.py, FDv2 polling inasync_polling.py, and event posts inasync_event_processor.py..sdk_metadata.jsonaddsPythonAsyncClientto the existingpython-server-sdkuserAgentslist.testing/impl/test_user_agent.pyasserts the exact wire User-Agent strings for sync and async.Reviewed by Cursor Bugbot for commit 32498ce. Bugbot is set up for automated code reviews on this repo. Configure here.