Add app_id and org_id to metrics payloads - #5130
Merged
Merged
Conversation
Send the internal numeric app and org IDs alongside the existing name/slug fields in the deploy, launch, and command-stats telemetry payloads, so they can flow through to Snowflake for analytics. Fields are omitempty so older flyctl behavior is unchanged for the receiver. - Deploy: populated from the flaps.App returned during deployToMachines. - Launch: populated from the app created in createApp, threaded through launchState since app creation happens in a different function than where the metrics payload is built. - Command stats: added context plumbing (WithAppID/WithOrgID) and wired RecordCommandFinish to read from it, but nothing currently populates it — RequireAppName only resolves the app name, not the numeric ID, and command context is captured once early via RecordCommandContext, so populating this needs a GetApp call threaded through the preparer chain. Left for a follow-up PR. Requires a companion flyctl-metrics PR to persist these fields; until then the receiver silently ignores them (json.Decoder without DisallowUnknownFields). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5 tasks
clouvet
added a commit
that referenced
this pull request
Aug 28, 2026
The command stats payload gained app_id/org_id fields in #5130, but nothing ever populated them. Populate them from the scope our tokens already carry, which costs no API call and needs no app lookup. Tokens hold one macaroon per org the user belongs to, so an org is only reported when every permission macaroon agrees on one. Single-org tokens -- CI and deploy tokens, and users in a single org -- therefore report an org, while a token spanning several reports none rather than guessing. Apps are only reported by tokens narrowed to exactly one app, so app_id stays empty far more often than org_id. Both fields are omitempty, so an invocation we can't attribute sends what it sends today. Deriving this from the tokens rather than from a fetched app is what makes it worth doing: only 5 of the 39 app-scoped command packages ever call GetApp, and those overlap with deploy and launch, which already report both IDs on their own payloads. The remaining 34 -- status, logs, ssh, scale, machine, volumes and friends -- only ever deal in an app name, and command stats is the sole event covering them. Also replaces the WithAppID/WithOrgID context helpers from #5130. They could never have worked: RecordCommandFinish reads a package-global context that startMetrics snapshots before any app is resolved, and a context derived later is a different value the global never sees. A package-level setter matches how IsUsingGPU is already reported. Co-authored-by: Sprite <noreply@sprites.dev> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
Summary
app_idandorg_id(internal numeric IDs) alongside the existing app name / org slug fields on the deploy, launch, and command-stats telemetry payloads, so they can flow through to Snowflake for analytics.omitempty, so older flyctl builds and any code path that doesn't populate them send the same payload as today.json.Decoderand noDisallowUnknownFields.Deploy payload
DeployStatusPayload.AppID/OrgIDare populated indeployToMachines()from the*flaps.Appalready fetched for the deploy (app.InternalNumericID,app.Organization.InternalNumericID).Launch payload
LaunchStatusPayload.AppID/OrgIDare populated from the app created inlaunchState.createApp(). Since app creation happens in a different function than where the metrics payload is built incmd.go, the IDs are stashed onlaunchState(appID/orgID) at creation time and copied ontostatusright afterstate.Launch(ctx)returns. If--no-createis used (no app creation), these stay empty as before.Command stats payload
Added
metrics.WithAppID/WithOrgIDcontext helpers and wiredRecordCommandFinishto readAppID/OrgIDfrom context. However, nothing currently calls the setters:command.RequireAppNameonly resolves the app name (no network call), andmetrics.RecordCommandContextcaptures the context once, early, before app resolution would happen. Populating this properly needs aGetAppcall threaded through the preparer chain (a real behavior/perf change beyond the scope here), so it's left for a follow-up PR. The plumbing is in place for that follow-up.Test plan
go build ./...go vet ./...