Skip to content

fix(typespec-ts): simplify SDK User-Agent telemetry prefix#4817

Open
lirenhe wants to merge 6 commits into
mainfrom
js-useragent-update
Open

fix(typespec-ts): simplify SDK User-Agent telemetry prefix#4817
lirenhe wants to merge 6 commits into
mainfrom
js-useragent-update

Conversation

@lirenhe

@lirenhe lirenhe commented Jul 6, 2026

Copy link
Copy Markdown
Member

Fixes #4774

Simplify the generated SDK User-Agent telemetry prefix to follow the Azure Core telemetry policy.

Problem

Generated modular clients emit a stacked User-Agent such as:

azsdk-js-client azsdk-js-api azsdk-js-ai-projects/2.0.0-beta.4 core-rest-pipeline/1.22.2 Node/22.14.0 (...)

The azsdk-js-client and azsdk-js-api tokens were added in autorest.typescript#2616 to distinguish the classic-client / modular-API / REST layers. They are not real packages, carry no /version, and do not match the policy format azsdk-<lang>-<package>/<version> — confusing downstream service teams (#4774).

Change

  • client-helpers.ts buildUserAgentOptions now builds the prefix from azsdk-js-<package>/<version> only (plus any caller-supplied application id); dropped the static token and the .includes("api") gate. Returns no override when package name/version is unavailable.
  • build-classical-client.ts forwards options untouched, so the application id still flows down and is prepended exactly once.

Resulting User-Agent:

[<application_id> ]azsdk-js-<package>/<version> core-rest-pipeline/x Node/y (...)

Validation

  • pnpm build clean; modular unit suite passing.
  • New test/modular-unit/userAgent.test.ts covers the azsdk-js-<pkg>/<version> output, application-id forwarding, and the no-package fallback.
  • Updated 10 modular-unit scenario snapshots.

Note

The @azure/ai-projects team already ships a scripts/post-emitter.mjs that strips these tokens as a workaround; this emitter fix makes such workarounds redundant.

Follow the Azure Core telemetry policy by removing the legacy internal
layering tokens `azsdk-js-client` and `azsdk-js-api` from the generated
User-Agent. The prefix is now `[<application_id> ]azsdk-js-<package>/<version>`.
Any caller-supplied application id is still forwarded and prepended.

Fixes #4774

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

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @azure-tools/typespec-ts
Show changes

@azure-tools/typespec-ts - fix ✏️

Simplify the generated SDK User-Agent telemetry prefix to follow the Azure Core telemetry policy. The legacy internal layering tokens azsdk-js-client and azsdk-js-api are no longer emitted, so the user agent is now [<application_id> ]azsdk-js-<package>/<version> <platform_info>. Any caller-supplied application id is still forwarded and prepended.

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

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

@pkg-pr-new

pkg-pr-new Bot commented Jul 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-ts@4817

commit: 90de4a1

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

⚡ Benchmark Results

⚠️ 8 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
loader 🟡 300.6ms 🟡 323.3ms +7.6% 🔴
linter 🟡 212.2ms 🟡 222.9ms +5.0% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 26.1ms 🔴 28.0ms +7.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 27.3ms 🔴 29.0ms +6.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 32.8ms 🔴 34.9ms +6.4% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 32.2ms 🔴 34.0ms +5.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 19.2ms 🔴 20.8ms +8.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 29.3ms 🔴 31.4ms +7.1% 🔴
Full details – comparing 0444615 vs baseline rolling-baseline-364b924-870cafc (rolling baseline (20 main runs))
Metric Baseline Current Change
total 🔴 998.2ms 🔴 1.05s +5.0%
loader 🟡 300.6ms 🟡 323.3ms +7.6% 🔴
resolver 🟢 40.0ms 🟢 40.2ms +0.5%
checker 🟡 360.0ms 🟡 374.3ms +4.0%
validation 🟢 85.0ms 🟢 86.7ms +2.1%
 ↳ validation/@azure-tools/typespec-azure-core 🟡 12.4ms 🟡 13.2ms +6.2%
 ↳ validation/@typespec/http 🟡 15.3ms 🟡 16.0ms +4.4%
 ↳ validation/@typespec/rest 🟢 1.6ms 🟢 1.6ms +1.2%
 ↳ validation/@typespec/versioning 🔴 51.5ms 🔴 51.8ms +0.6%
 ↳ validation/compiler 🟢 3.8ms 🟢 3.9ms +1.6%
linter 🟡 212.2ms 🟡 222.9ms +5.0% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.1ms 🟢 0.1ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.6ms 🟢 0.6ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 8.2ms 🟢 8.6ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 1.4ms 🟢 1.5ms +1.2%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.2ms 🟢 0.2ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 1.9ms 🟢 2.0ms +3.1%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 1.4ms 🟢 1.4ms +3.2%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.4ms 🟢 0.4ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.5ms 🟢 0.5ms +6.6%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.8ms 🟢 0.8ms +2.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.7ms 🟢 0.7ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 1.0ms 🟢 1.0ms +0.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.2ms 🟢 0.2ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.3ms 🟢 0.3ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.2ms 🟢 0.2ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.8ms 🟢 0.8ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.8ms 🟢 0.8ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 26.1ms 🔴 28.0ms +7.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 2.0ms 🟢 2.1ms +5.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.2ms 🟢 0.2ms +7.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.4ms 🟢 0.4ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 1.9ms 🟢 2.0ms +4.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 2.3ms 🟢 2.3ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 3.1ms 🟢 3.2ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 27.3ms 🔴 29.0ms +6.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 32.8ms 🔴 34.9ms +6.4% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.1ms 🟢 0.1ms +8.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 7.5ms 🟢 8.0ms +7.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.4ms 🟢 0.4ms +5.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.1ms 🟢 0.1ms +6.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.3ms 🟢 0.4ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.8ms 🟢 0.8ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.4ms 🟢 0.4ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.5ms 🟢 0.5ms +1.8%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.1ms 🟢 0.1ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 32.2ms 🔴 34.0ms +5.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.7ms 🟢 0.7ms +6.4%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.5ms 🟢 0.5ms +5.2%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 7.4ms 🟢 8.0ms +6.9%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.3ms 🟢 0.3ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🔴 21.7ms 🔴 22.3ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.3ms 🟢 0.3ms +6.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟡 12.0ms 🟡 12.6ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.2ms 🟢 0.2ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 5.5ms 🟢 4.5ms -17.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟡 17.0ms 🟡 17.7ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.6ms 🟢 0.6ms +2.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 1.4ms 🟢 1.4ms -1.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.2ms 🟢 0.2ms -4.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.4ms 🟢 0.4ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.4ms 🟢 0.4ms +3.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.1ms 🟢 0.1ms -3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.2ms 🟢 0.2ms -2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.3ms 🟢 0.3ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.2ms 🟢 0.2ms +0.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.5ms 🟢 0.5ms +5.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.1ms 🟢 0.1ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.5ms 🟢 0.5ms -0.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 8.8ms 🟢 8.9ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.8ms 🟢 0.8ms -1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.4ms 🟢 0.4ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.4ms 🟢 0.4ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.2ms 🟢 0.2ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.4ms 🟢 0.4ms +0.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.1ms 🟢 0.1ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 19.2ms 🔴 20.8ms +8.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.1ms 🟢 0.1ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 1.0ms 🟢 1.0ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.3ms 🟢 0.3ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.3ms 🟢 0.3ms -2.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.4ms 🟢 0.5ms +5.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 29.3ms 🔴 31.4ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.4ms 🟢 0.4ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.4ms 🟢 0.4ms +1.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 5.4ms 🟢 5.2ms -3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.7ms 🟢 0.7ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.3ms 🟢 0.3ms -1.7%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 2.3ms 🟢 2.3ms +3.0%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 1.6ms 🟢 1.7ms +2.8%
emit 🔴 5.98s 🔴 6.19s +3.6%
 ↳ emit/@Azure-Tools 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@azure-tools/typespec-autorest 🟢 123.9ms 🟢 127.6ms +3.0%
 ↳ emit/@azure-tools/typespec-python 🔴 2.23s 🔴 2.31s +3.7%
 ↳ emit/@typespec 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@typespec/http-client-js 🔴 564.9ms 🔴 583.8ms +3.3%
 ↳ emit/@typespec/openapi3 🟢 106.4ms 🟢 111.1ms +4.4%
 ↳ emit/@typespec/openapi3/compute 🟢 92.4ms 🟢 96.6ms +4.6%
 ↳ emit/@typespec/openapi3/write 🟢 13.8ms 🟢 14.3ms +3.5%

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

lirenhe and others added 3 commits July 6, 2026 11:18
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The updated http-specs (core) added a model operation to the query
parameters queryExpansion/explode group, introducing the ExpandParameters
model. Regenerate the routes modular integration baseline accordingly.

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

dargilco commented Jul 6, 2026

Copy link
Copy Markdown
Member

Thank you @lirenhe for doing this work! Looking forward to see this PR completed. FYI @glharper @bobogogo1990

Comment thread packages/typespec-ts/src/modular/helpers/client-helpers.ts Outdated

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

Overall the code looks good to me, and I left a small comment. I'm not sure whether azsdk-js-api and azsdk-js-client were added in Azure/autorest.typescript#2616 because we wanted to track traffic from the API layer and client layer separately. I may need @qiaozha to help confirm if this change impacts anything else.

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

lirenhe commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@qiaozha @xirzec, could you help to review this PR? thanks

@qiaozha

qiaozha commented Jul 8, 2026

Copy link
Copy Markdown
Member

@dargilco could you explain why you need this userAgent change? Otherwise, I don't think this change makes sense. Because it has nothing to do with the RLC but the modular's own subpath export concept And currently Classical Client layer/API layer are still exposed in the Modular client, and people who have special bundle size requirement can still use API layer only, they might want to filter out their traffic from other users who uses classical client within their organization. /cc @xirzec

@dargilco

dargilco commented Jul 8, 2026

Copy link
Copy Markdown
Member

@qiaozha the description at the top of this GitHub issue explains is very well. I expect User Agent format to be simple and follow Azure SDK guidelines and be similar to other languages, so our many telemetry queries do not need to continue special casing JS.

@bobogogo1990 @glharper FYI

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

I'm fine with these changes to align with UA across languages. Since we have less complexity in our emit now (with the deprecation of RLC) this feels less valuable than it was originally.

As @qiaozha has pointed out, we are losing the ability to see if requests are made by the client class or the api methods directly, but I can't say that we have been looking closely at this data and making decisions with it today.

Anecdotally we've had signal that the api methods are useful for those concerned with bundle size, and I'm fine with that being sufficient to justify continuing to support them without needing to validate using non-standard telemetry.

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

Labels

emitter:typescript Issues for @azure-tools/typespec-ts emitter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[typespec-ts] SDK User-Agent prefixes feel confusing / outdated

5 participants