-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(webapp): deployment lifecycle telemetry events #4778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
myftija
merged 13 commits into
main
from
feature/tri-13477-deployment-lifecycle-telemetry
Aug 26, 2026
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
486ec62
feat(webapp): deployment lifecycle telemetry events per build path
myftija 8244227
chore: format recordDeploymentLifecycle.server.ts
myftija cb09bb1
fix: bound the notIn status filter in failDeployment
myftija 6919caa
fix: return the post-update row from failDeployment
myftija 4038e6f
refactor: fold attribute docs into the telemetry constants, neverthro…
myftija 9cd1c6c
chore: trim inline comments to one-liners
myftija fc0d5fd
refactor: rename the terminal telemetry event to deployment.finished
myftija 1af895a
refactor: rename the local_bundle build path value to native_local_bu…
myftija d30575c
refactor: use andTee/orTee for cancel-path side effects
myftija bf0ee66
refactor: carry the full deployment row through the cancel chain inst…
myftija cedd846
fix: only accept version-shaped x-trigger-cli-version values
myftija b515933
fix(cli): send the CLI version header on all API requests
myftija 104bcc9
chore: relax the CLI version header length cap to 128
myftija File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "trigger.dev": patch | ||
| --- | ||
|
|
||
| Send the CLI version header on all API requests so deployments are attributable to a CLI version |
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| import { BuildServerMetadata } from "@trigger.dev/core/v3"; | ||
|
|
||
| /** | ||
| * Attribute names for the `deployment.finished` and `deployment.initialized` | ||
| * telemetry events (emitted by services/recordDeploymentFinished.server.ts). | ||
| * This module is the single owner of these names — external queries, | ||
| * dashboards, and monitors reference them, so treat renames as breaking. | ||
| * | ||
| * Query gotchas: dedup with `arg_max(_time, *) by deployment.id` (job retries | ||
| * can double-emit); the span's `_time` is the deployment's createdAt, so a | ||
| * TIMED_OUT event lands backdated by up to the full deploy timeout — monitor | ||
| * windows must exceed it; phase durations are omitted (not zero) when a | ||
| * boundary timestamp is missing, and `total_ms` excludes local-bundle's | ||
| * pre-init client work (esbuild + upload) until the CLI reports timings. | ||
| */ | ||
| export const DeploymentTelemetryAttributes = { | ||
| ORG_ID: "$trigger.org.id", | ||
| PROJECT_ID: "$trigger.project.id", | ||
| // Project external ref ("proj_…") | ||
| PROJECT_REF: "$trigger.project.ref", | ||
| ENV_ID: "$trigger.env.id", | ||
| // PRODUCTION / STAGING / PREVIEW / DEVELOPMENT | ||
| ENV_TYPE: "$trigger.env.type", | ||
| // Deployment friendly id — the dedup key | ||
| DEPLOYMENT_ID: "deployment.id", | ||
| VERSION: "deployment.version", | ||
| // finished: terminal status; initialized: initial status (PENDING/BUILDING) | ||
| STATUS: "deployment.status", | ||
| // status === DEPLOYED; CANCELED is excluded from failure rates | ||
| SUCCESS: "deployment.success", | ||
| // depot / native / native_local_bundle (see deriveBuildPath) | ||
| BUILD_PATH: "deployment.build_path", | ||
| // V1 / MANAGED (run engine) | ||
| WORKER_TYPE: "deployment.worker_type", | ||
| RUNTIME: "deployment.runtime", | ||
| // Set at indexing; null for pre-index failures | ||
| RUNTIME_VERSION: "deployment.runtime_version", | ||
| // From x-trigger-cli-version at init; null for pre-column history | ||
| CLI_VERSION: "deployment.cli_version", | ||
| TRIGGERED_VIA: "deployment.triggered_via", | ||
| COMMIT_SHA: "deployment.commit_sha", | ||
| // error.* only on FAILED/TIMED_OUT; CANCELED uses canceled_reason | ||
| ERROR_NAME: "deployment.error.name", | ||
| ERROR_MESSAGE: "deployment.error.message", | ||
| CANCELED_REASON: "deployment.canceled_reason", | ||
| // createdAt → terminal (also the span's own duration) | ||
| DURATION_TOTAL_MS: "deployment.duration.total_ms", | ||
| // createdAt → startedAt; ≈0 when created directly in BUILDING (depot) | ||
| DURATION_QUEUE_MS: "deployment.duration.queue_ms", | ||
| // startedAt → installedAt; build-server paths only (depot never sets it) | ||
| DURATION_INSTALL_MS: "deployment.duration.install_ms", | ||
| // (installedAt ?? startedAt) → builtAt | ||
| DURATION_BUILDING_MS: "deployment.duration.building_ms", | ||
| // builtAt → terminal; for depot dominated by the server-side registry push | ||
| DURATION_DEPLOYING_MS: "deployment.duration.deploying_ms", | ||
| } as const; | ||
|
|
||
| export type DeploymentBuildPath = "native_local_bundle" | "native" | "depot"; | ||
|
|
||
| /** | ||
| * Everything that is not a native-build-server deployment falls into the depot | ||
| * bucket, including rare `--local-build` deploys (their flag is not persisted). | ||
| * `externalBuildData` is NOT a usable depot signal: init writes a placeholder | ||
| * for every path. | ||
| */ | ||
| export function deriveBuildPath(buildServerMetadata: unknown): DeploymentBuildPath { | ||
| const metadata = BuildServerMetadata.safeParse(buildServerMetadata); | ||
|
|
||
| if (metadata.success && metadata.data.isNativeBuild) { | ||
| return metadata.data.fromBundle ? "native_local_bundle" : "native"; | ||
| } | ||
|
|
||
| return "depot"; | ||
| } | ||
|
|
||
| export type DeploymentTimestamps = { | ||
| createdAt: Date; | ||
| startedAt?: Date | null; | ||
| installedAt?: Date | null; | ||
| builtAt?: Date | null; | ||
| }; | ||
|
|
||
| export type DeploymentDurations = { | ||
| totalMs: number; | ||
| queueMs?: number; | ||
| installMs?: number; | ||
| buildingMs?: number; | ||
| deployingMs?: number; | ||
| }; | ||
|
|
||
| /** | ||
| * Timestamp chains are path-shaped (e.g. depot never sets installedAt), so | ||
| * each phase is derived only when both of its boundary timestamps exist and | ||
| * are ordered. | ||
| */ | ||
| export function deriveDeploymentDurations( | ||
| timestamps: DeploymentTimestamps, | ||
| terminalAt: Date | ||
| ): DeploymentDurations { | ||
| const { createdAt, startedAt, installedAt, builtAt } = timestamps; | ||
| const buildingFrom = installedAt ?? startedAt; | ||
|
|
||
| return { | ||
| totalMs: Math.max(terminalAt.getTime() - createdAt.getTime(), 0), | ||
| queueMs: msBetween(createdAt, startedAt), | ||
| installMs: msBetween(startedAt, installedAt), | ||
| buildingMs: msBetween(buildingFrom, builtAt), | ||
| deployingMs: msBetween(builtAt, terminalAt), | ||
| }; | ||
| } | ||
|
|
||
| function msBetween(from?: Date | null, to?: Date | null): number | undefined { | ||
| if (!from || !to) return undefined; | ||
| const ms = to.getTime() - from.getTime(); | ||
| return ms >= 0 ? ms : undefined; | ||
| } |
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
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.