Sitelet https://github.com/triggerdotdev/trigger.dev/pull/4778
Skip to content

feat(webapp): deployment lifecycle telemetry events - #4778

Open
myftija wants to merge 8 commits into
mainfrom
feature/tri-13477-deployment-lifecycle-telemetry
Open

feat(webapp): deployment lifecycle telemetry events#4778
myftija wants to merge 8 commits into
mainfrom
feature/tri-13477-deployment-lifecycle-telemetry

Conversation

@myftija

@myftija myftija commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Deployments currently leave little analytical trace. This PR makes every deployment emit two analytics events to enable useful queries. It also enables comparing deployments across build paths, CLI versions, runtimes, and orgs.

Where the events come from

 trigger deploy
      │
      ▼
  initialize ─────────────────────────────▶ ✨ deployment.initialized
      │ createdAt
      ▼
   PENDING      waiting for a build slot        ┐
      │ startedAt                               │ queue time
      ▼                                         ┘
  INSTALLING    build server installs deps      ┐
      │ installedAt      (native paths only)    │ install time
      ▼                                         ┘
   BUILDING     the image is built              ┐
      │ builtAt                                 │ building time
      ▼                                         ┘
  DEPLOYING     indexing + registry push        ┐
      │ deployedAt / failedAt / canceledAt      │ deploying time
      ▼                                         ┘
  DEPLOYED · FAILED · TIMED_OUT · CANCELED
      │
      └───────────────────────────────────▶ ✨ deployment.finished

deployment.finished fires exactly once, whichever way the deployment ends, and is backdated to cover the deployment's real lifetime. Not every path visits every state (Depot deploys skip PENDING/INSTALLING, for example) — a phase duration is simply omitted when its state was never entered.

What each event carries

  • Which path built it: depot, native, or native_local_bundle
  • How it ended: status, plus an error class and message when it failed
  • How long each phase took: queue, install, building, deploying, and total — derived from the timestamps above
  • Who and with what: org, project, environment, runtime, CLI version, and how the deploy was triggered (CLI, GitHub, Vercel)

With that, one query gives failure rate per build path, duration percentiles per phase, adoption per CLI version, or a per-org health table.

Fixes that ride along

  • The old deployment.outcome span was silently dropped ~95% of the time (it was subject to trace sampling). The new events opt out of sampling explicitly, so every deployment is counted.
  • The fail/timeout/finalize transitions were racy: a late timeout could overwrite a successful deployment. They now use guarded writes, so exactly one caller wins the terminal transition — and exactly one event is emitted.
  • Canceled deployments previously recorded nothing; they do now.
  • The deployment's CLI version is now stored at initialization (new nullable column), so even deploys that fail early are attributable to a CLI release.
  • Telemetry is flushed on shutdown (the last batch used to be lost on every webapp deploy), and an optional second exporter can mirror just these events into a dedicated dataset.

Replaces the deployment.outcome span with a wide deployment.lifecycle
event emitted once per terminal transition (DEPLOYED/FAILED/TIMED_OUT/
CANCELED), backdated createdAt-to-terminal, carrying build path (depot/
native/local_bundle), per-phase durations derived from the persisted
timestamp chain, error class, org/project/env, runtime, CLI version and
trigger source as attributes. A zero-duration deployment.initialized
event at creation provides the funnel denominator for stuck-deployment
detection.

Events are emitted on ROOT_CONTEXT with the forceRecording attribute:
the previous span was started under the ambient request context, where
the parent-based sampler drops ~95% of traffic before the force-record
check runs. SEMINTATTRS_FORCE_RECORDING is now exported for this.

The fail, timeout and finalize transitions now use guarded updateMany
writes so exactly one caller commits a terminal status and emits the
event; this also stops a late timeout from overwriting DEPLOYED. The
cancel path now emits too (it previously recorded nothing).

Also: cliVersion is stamped onto WorkerDeployment at initialization from
the x-trigger-cli-version header (previously only available post-index
via BackgroundWorker, i.e. null for pre-index failures); an optional
second OTLP exporter (INTERNAL_OTEL_DEPLOYMENT_EVENT_EXPORTER_URL)
mirrors deployment.* spans into a dedicated dataset; the tracer provider
is flushed on SIGTERM/SIGINT so shutdowns stop dropping the last batch.
@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 1af895a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4fbff98b-4359-45aa-b2bf-b98d672c266d

📥 Commits

Reviewing files that changed from the base of the PR and between 4038e6f and 9cd1c6c.

📒 Files selected for processing (10)
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/v3/deploymentTelemetry.ts
  • apps/webapp/app/v3/services/deployment.server.ts
  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/finalizeDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
  • apps/webapp/app/v3/services/timeoutDeployment.server.ts
  • apps/webapp/app/v3/tracer.server.ts
  • internal-packages/database/prisma/migrations/20260825120000_add_worker_deployment_cli_version/migration.sql
  • internal-packages/database/prisma/schema.prisma
💤 Files with no reviewable changes (1)
  • internal-packages/database/prisma/migrations/20260825120000_add_worker_deployment_cli_version/migration.sql
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/finalizeDeployment.server.ts
  • apps/webapp/app/v3/services/deployment.server.ts
  • apps/webapp/app/v3/deploymentTelemetry.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
  • apps/webapp/app/v3/tracer.server.ts
  • apps/webapp/app/v3/services/timeoutDeployment.server.ts
  • internal-packages/database/prisma/schema.prisma

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (31)
  • GitHub Check: report
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (24, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (23, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (22, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 24)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: 🛡️ E2E Auth Tests (full)

Walkthrough

Adds deployment lifecycle telemetry for initialization, success, failure, cancellation, and timeout events. Adds build-path and duration derivation helpers with tests. Persists the CLI version from the request header on deployments. Guards terminal database transitions against concurrent updates. Adds an optional OTLP exporter for deployment.* spans with header parsing and shutdown flushing.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 12 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description explains the telemetry changes and related fixes in detail, but it does not follow the repository template. It omits the issue reference, checklist, Testing section with test steps, Ch… Add the required template sections. Include the issue reference, completed checklist, specific testing steps, a short changelog entry, and screenshots or an explicit indication that screenshots are not applicable.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: deployment lifecycle telemetry events. It is concise and specific.
Full details: Docstring Coverage

Explanation

Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 12 files. (2 skipped: 2 unsupported.)

Full details: Description check

Explanation

The description explains the telemetry changes and related fixes in detail, but it does not follow the repository template. It omits the issue reference, checklist, Testing section with test steps, Changelog section, and Screenshots section.

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/tri-13477-deployment-lifecycle-telemetry

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/webapp/app/v3/services/failDeployment.server.ts (1)

49-60: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Refresh the deployment before recording its lifecycle.

failedDeployment uses the row loaded before updateMany. A concurrent phase update can change startedAt, installedAt, builtAt, or buildServerMetadata, so recordDeploymentLifecycle may record stale values.

When updatedCount === 1, reload the row with findFirst and guard a missing result. Use the refreshed row for the lifecycle record. The event log uses only shortCode and does not require this reload.

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b8a1cfb5-79a0-4d98-882b-9659465a6c46

📥 Commits

Reviewing files that changed from the base of the PR and between 486ec62 and cb09bb1.

📒 Files selected for processing (2)
  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.

📜 Review details
⏰ Context from checks skipped due to timeout. (35)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (21, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (16, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (13, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (24, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (23, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (15, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (22, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (19, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (20, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (17, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (18, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (14, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 24)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 24)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (1, 2)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp (2, 2)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: obsmap / 🧪 Unit Tests: Observability Map
  • GitHub Check: fk-cascade-guard / fk-cascade-guard
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: runops-guard / runops-guard
  • GitHub Check: code-quality / code-quality
  • GitHub Check: report
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: 🛡️ E2E Auth Tests (full)
🧰 Additional context used
📓 Path-based instructions (10)
New code must target Run Engine V2 through the singleton in `app/v3/runEngine.server.ts`; do not reintroduce V1 execution paths. V1 branches may only reject or finalize gracefully with a clean 4xx.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Never use `request.signal` to detect client disconnects. Use `getRequestAbortSignal()` from `app/services/httpAsyncStorage.server.ts`, which is wired to Express response close events.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
For dashboard changes, visually verify the running Remix app with Chrome DevTools MCP, using snapshots, screenshots, interaction, and console-message checks as appropriate.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
**Prefer static imports over dynamic imports.** Only use dynamic `import()` when:

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Add crumbs as you write code — not just when debugging. Mark lines with

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Use zod for validation in packages/core and apps/webapp

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Access environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env`

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Use function declarations instead of default exports

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
Use types over interfaces for TypeScript

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

Files:

  • apps/webapp/app/v3/services/failDeployment.server.ts
  • apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts
🔇 Additional comments (2)
apps/webapp/app/v3/services/failDeployment.server.ts (1)

44-89: Add crumbs markers to this transition path.

The guarded update and lifecycle emission have no // @Crumbs marker or `#region `@crumbs block. This repeats the existing missing-crumbs finding for neighboring telemetry code.

As per coding guidelines, add crumbs as you write code with // @Crumbs or `#region `@crumbs, then remove them with agentcrumbs strip before merge.

Source: Coding guidelines

apps/webapp/app/v3/services/recordDeploymentLifecycle.server.ts (1)

69-71: 🎯 Functional Correctness

No change needed for TIMED_OUT terminal time. timeoutDeployment.server.ts assigns and persists failedAt before passing timedOutDeployment to recordDeploymentLifecycle, so terminalAt resolves to failedAt.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

coderabbitai[bot]

This comment was marked as resolved.

…w cancel emission

Replaces the standalone DEPLOYMENT_TELEMETRY_ATTRIBUTES.md with short
comments on the DeploymentTelemetryAttributes keys, and chains the
canceled-lifecycle emission through the cancel ResultAsync pipeline
instead of a fire-and-forget promise.
coderabbitai[bot]

This comment was marked as resolved.

@myftija myftija changed the title feat(webapp): deployment lifecycle telemetry events per build path feat(webapp): deployment lifecycle telemetry events Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants