Add PET version, build ID, and commit SHA to telemetry#1574
Merged
Conversation
Stamp every PET telemetry event with the running binary's identity so we can correlate user-reported issues and performance regressions back to a specific PET commit. - Adds a fire-and-forget `info` JSON-RPC call once per PET process start and caches the response (petVersion, buildId, commitSha) for the process's lifetime. - Spreads those three fields into PET_REFRESH, PET_RESOLVE, and PET_PROCESS_RESTART telemetry events. - Pairs with PET PRs microsoft/python-environment-tools#470 and microsoft#473 which added the `info` request and the commit SHA field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cedde48 to
65787ad
Compare
eleanorjboyd
approved these changes
Jun 10, 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.
Context
PET (Python Environment Tools) is the Rust JSON-RPC service this extension uses to discover Python environments. PET ships independently of the extension and is bundled as a binary inside the VSIX, so the PET version a user is running can drift from the extension version. When we see a performance regression or a failure in PET telemetry today, we have no way to map it back to the exact PET source code the user is running — we know
pet --version(already telemetered viaPET.VERSION) but a single PET version line can correspond to many commits across multiple builds.This PR closes that gap by stamping every PET telemetry event with the binary's
petVersion,petBuildId, andpetCommitSha, sourced directly from the running PET process via a newinfoJSON-RPC request. We can thensummarize by petCommitShain Kusto and join straight to git log to find the offending change.Related PRs
PET side (both merged):
infoJSON-RPC request returningpetVersionand optionalbuildIdinforesponse for telemetry regression tracking python-environment-tools#473 — extends theinforesponse with optionalcommitShabaked in from CI env vars (PET_COMMIT_SHA/BUILD_SOURCEVERSION/GITHUB_SHA)Supersedes / replaces:
petVersion+petBuildIdand accidentally corrupted the enum docstring forPET_RESOLVE/MIGRATION_SYSTEM_ENV_MANAGER. Please close.What this PR does
NativePetInfointerface matching PET'sinforesponse shape (petVersion: string,buildId?: string,commitSha?: string).infoRPC per PET process start inkickoffInfoFetch(connection), called immediately afterconnection.listen()insidestart(). The call is fire-and-forget with a 2 s timeout —start()does not await it, so discovery is never blocked. The response is cached inthis.petInfofor the lifetime of that PET process.this.petInfois reset toundefinedon everystart()(initial spawn + every crash-recovery restart).connection !== this.connectionchecks in both.thenand.catch, so a late reply from a previous PET process can't clobber the cache of a newer one after a restart.getPetInfoProperties()into the six existing PET telemetry call sites (success + error paths ofPET_RESOLVE,PET_REFRESH,PET_PROCESS_RESTART). The helper always returns concrete strings, defaulting each field to'unknown', so Kusto group-bys work without null handling.PET_RESOLVE,PET_REFRESH,PET_PROCESS_RESTART. All classified asSystemMetaData/PerformanceAndHealth.Files changed
src/managers/common/nativePythonFinder.tsINFO_TIMEOUT_MSconstant,NativePetInfointerface,petInfofield,kickoffInfoFetch+getPetInfoPropertieshelpers, kickoff wiring instart(), payload spread at six telemetry sitessrc/common/telemetry/constants.tspetVersion/petBuildId/petCommitShaproperties onPET_RESOLVE,PET_REFRESH,PET_PROCESS_RESTART(GDPR blocks + TS types)Compatibility with older PET binaries
The extension currently ships PET as a bundled binary (downloaded by the Azure pipelines from PET CI artifacts). Until the PET release branch picks up #470 / #473, the bundled binary won't have the
infohandler. In that case:-1(Failed to find handler for request info)sendRequestWithTimeoutrejects →.catchswallows →petInfostaysundefined'unknown'[pet] Failed to find handler for method: infoline surfaces from PET's stderr into the Python Environments output channelDiscovery, refresh, resolve, and restart all continue to work normally. No crash, no functional regression — just
'unknown'values in telemetry until PET catches up.Crash attribution semantics
A subtle but important detail of where the spread is placed: the crashing PET's commit hash is captured in
PET_REFRESH/PET_RESOLVEerror events because we callsendTelemetryEvent(..., ...this.getPetInfoProperties())before killing the process and resetting the cache. So when a user reports "PET crashed during refresh", we can identify which exact commit was running.The
PET_PROCESS_RESTARTsuccess event itself reports'unknown'for the new PET (itsinforeply usually hasn't landed in the few ms betweenstart()and the telemetry call), but the new binary's identity surfaces on the very next refresh/resolve.Performance impact
kickoffInfoFetchreturnsvoidsynchronously; the response runs on the microtask queue and never blocks refresh/resolveValidation
npm run lint✅npx tsc -p . --noEmit✅npm run compile-tests✅npm run unittest— 1141 passing, 2 pending (unchanged from baseline) ✅npm run compile(webpack production bundle) ✅Manual testing
To get non-
'unknown'values locally, build PET from main and drop the binary intopython-env-tools/bin/:Then F5 → open the Python Environments view → run
Python Environments: Refresh Environments. Set the Python Environments output channel to Debug level to see the[pet] info: { petVersion, buildId, commitSha }line confirming the cache was populated.