workflow 5.0.0-beta.16 → 5.0.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -103,6 +103,8 @@ const run = await start(myWorkflow, ["arg1", "arg2"], { // [!code highlight]
103
103
 
104
104
  <Callout type="info">
105
105
  The `deploymentId` option is currently a Vercel-specific feature. Other Worlds may implement this option differently to match their own deployment runtimes, and the World spec may rename it from `deploymentId` to `version` in a future SDK version. On Vercel, `"latest"` resolves to the most recent deployment matching your current environment — the same production target for production deployments, or the same git branch for preview deployments.
106
+
107
+ In Worlds without atomic, immutable deployments (such as local development or self-hosted Postgres), there is no notion of multiple deployments to resolve between, so `deploymentId: "latest"` has no effect: the SDK logs a warning and the run targets the current deployment. This means a workflow that opts into `"latest"` on Vercel still runs unchanged in local development.
106
108
  </Callout>
107
109
 
108
110
  <Callout type="warn">
@@ -31,8 +31,8 @@ export default withWorkflow(nextConfig, workflowConfig); // [!code highlight]
31
31
  If a package in `serverExternalPackages` contains workflow code (`"use step"`,
32
32
  `"use workflow"`, or serialization classes), `withWorkflow()` automatically
33
33
  removes it from `serverExternalPackages` for the current build and prints a
34
- warning. This ensures the package still gets transformed by the Workflow
35
- compiler. Remove that package from `serverExternalPackages` in your
34
+ warning. Workflow still compiles the package so its directives are transformed.
35
+ Remove that package from `serverExternalPackages` in your
36
36
  `next.config` to silence the warning.
37
37
  </Callout>
38
38
 
@@ -42,6 +42,19 @@ npx workflow inspect runs --web
42
42
 
43
43
  ![Workflow SDK Web UI](/o11y-ui.png)
44
44
 
45
+ To share a link to a specific run without opening a browser, use the `--url`
46
+ flag. It prints the dashboard deep link to stdout and exits (no browser, no
47
+ local server) — useful for scripts, PR comments, or automation. Add `--json` to
48
+ get `{ "url": "..." }`.
49
+
50
+ ```bash
51
+ # Print the deep-link URL for a run (no browser, no server)
52
+ npx workflow inspect run <run_id> --url
53
+
54
+ # Vercel runs: add the backend (and --env preview for preview deployments)
55
+ npx workflow inspect run <run_id> --backend vercel --url
56
+ ```
57
+
45
58
  ## Backends
46
59
 
47
60
  The Workflow SDK CLI can inspect data from any [World](/docs/deploying). By default, it inspects data in your local development environment. For example, if you are using Next.js to develop workflows locally, the
@@ -67,6 +80,9 @@ When deployed to Vercel, workflow data is [encrypted end-to-end](/docs/how-it-wo
67
80
  ## More Observability Features
68
81
 
69
82
  <Cards>
83
+ <Card href="/docs/observability/tracing" title="Tracing">
84
+ Distributed tracing with OpenTelemetry for workflow runs, steps, and queue deliveries.
85
+ </Card>
70
86
  <Card href="/docs/observability/attributes" title="Attributes">
71
87
  Attach experimental metadata to workflow runs for observability.
72
88
  </Card>
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "title": "Observability",
3
- "pages": ["attributes"]
3
+ "pages": ["tracing", "attributes"]
4
4
  }
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: Tracing
3
+ description: Distributed tracing with OpenTelemetry for workflow runs, steps, and queue deliveries.
4
+ type: guide
5
+ summary: Trace workflow execution end to end with OpenTelemetry.
6
+ prerequisites:
7
+ - /docs/foundations/workflows-and-steps
8
+ related:
9
+ - /docs/observability
10
+ - /docs/observability/attributes
11
+ - /docs/how-it-works/event-sourcing
12
+ ---
13
+
14
+ The Workflow SDK is instrumented with [OpenTelemetry](https://opentelemetry.io) out of the box. It emits spans for workflow starts, every workflow and step invocation, and the HTTP calls it makes to the workflow backend — and it propagates trace context across queue deliveries so a run remains traceable end to end.
15
+
16
+ The SDK only depends on the OpenTelemetry **API**, never on an SDK or exporter. If your application does not register an OpenTelemetry SDK, all tracing code is a silent no-op with no overhead and no behavior change.
17
+
18
+ ## Enabling tracing
19
+
20
+ Register any OpenTelemetry Node SDK in your application. On Vercel with Next.js, the simplest setup is [`@vercel/otel`](https://vercel.com/docs/observability/otel-overview) in `instrumentation.ts`:
21
+
22
+ ```typescript title="instrumentation.ts" lineNumbers
23
+ import { registerOTel } from "@vercel/otel"
24
+
25
+ export function register() {
26
+ registerOTel({ serviceName: "my-app" })
27
+ }
28
+ ```
29
+
30
+ No workflow-specific configuration is required. As soon as a tracer provider and propagator are registered, the SDK's spans, context propagation, and span links activate automatically.
31
+
32
+ ## Spans
33
+
34
+ | Span name | Kind | Emitted when |
35
+ | --- | --- | --- |
36
+ | `workflow.start <name>` | internal | `start()` is called in your application code |
37
+ | `workflow.execute <name>` | consumer (root) | a queue delivery invokes the workflow — replay, orchestration, and inline steps run under it |
38
+ | `step.execute <name>` | internal (inline) / consumer + root (queue-delivered) | a step function executes |
39
+ | `http <method>` | client | the SDK calls the workflow backend (event reads/writes) |
40
+
41
+ `<name>` is the short function name (for example `processOrder`); the full machine name, including the source module, is available in the `workflow.name` / `step.name` attributes.
42
+
43
+ ## Key attributes
44
+
45
+ | Attribute | Description |
46
+ | --- | --- |
47
+ | `workflow.run.id` | The run ID (`wrun_...`). Present on every workflow and step span — the primary key for finding all spans of a run. |
48
+ | `workflow.name` | The workflow function name. |
49
+ | `workflow.trace.mode` | The active trace mode (`linked` or `continuous`). |
50
+ | `workflow.trace.propagated` | Whether the invocation received trace context from the queue message. |
51
+ | `workflow.queue.overhead_ms` | Time between the message being enqueued and the handler starting — queue dwell plus any cold start. |
52
+
53
+ ## Trace shape: one trace per invocation
54
+
55
+ A single workflow run can span hours or days across many separate function invocations: every step completion, `sleep()` wake-up, and retry is a new queue delivery. Stitching all of that into one trace produces giant, slow-loading traces that most tracing backends truncate.
56
+
57
+ Instead, the SDK creates **one bounded trace per invocation**. Each `workflow.execute` (or background `step.execute`) span starts a new trace root and attaches two **span links**:
58
+
59
+ - a link to the **enqueue site** — the span that queued the message which triggered this invocation, and
60
+ - a link to the **run origin** — the trace in which `start()` was originally called.
61
+
62
+ A span link is OpenTelemetry's relationship for "causally related, but in a different trace." It is the standard pattern for asynchronous messaging, where producing and consuming a message can be separated by arbitrary time.
63
+
64
+ ```mermaid
65
+ flowchart LR
66
+ O["start() request trace"]
67
+ A["invocation 1"]
68
+ B["invocation 2"]
69
+ C["invocation 3 ..."]
70
+ A -. "link" .-> O
71
+ B -. "link" .-> O
72
+ C -. "link" .-> O
73
+ B -. "link" .-> A
74
+ C -. "link" .-> B
75
+
76
+ style O fill:#a78bfa,stroke:#8b5cf6,color:#000
77
+ ```
78
+
79
+ Each invocation links back to the trace that enqueued it and to the run origin.
80
+
81
+ To see a whole run, query by attribute rather than by trace ID — for example `workflow.run.id = wrun_...` in your tracing backend — or follow the span links between invocation traces.
82
+
83
+ ## Trace modes
84
+
85
+ The `WORKFLOW_TRACE_MODE` environment variable controls the shape:
86
+
87
+ | Mode | Behavior |
88
+ | --- | --- |
89
+ | `linked` (default) | Each invocation is its own trace root with span links to the enqueue site and the run origin. Traces stay small; sampling is decided per invocation. |
90
+ | `continuous` | The run-origin context becomes the **parent** of every invocation, so the entire run shares one trace ID. |
91
+
92
+ <Callout type="warn">
93
+ This is a behavior change from v4, which always used `continuous`-style tracing. If you have dashboards or queries that assume one trace ID per run, either update them to use `workflow.run.id` and span links, or set `WORKFLOW_TRACE_MODE=continuous` to restore the previous shape. Note that in `linked` mode each invocation root makes its own sampling decision, and the number of root spans increases to one per invocation.
94
+ </Callout>
95
+
96
+ ## Context propagation
97
+
98
+ When tracing is enabled, the SDK propagates [W3C Trace Context](https://www.w3.org/TR/trace-context/) on its outbound calls:
99
+
100
+ - **Backend requests** carry `traceparent`, `tracestate`, and `baggage` headers, so backend spans can join your trace.
101
+ - **Queue messages** carry the run-origin trace context in the message payload, and the queue re-delivers the producer's context to the workflow handler, where it becomes the enqueue-site span link.
102
+ - **Baggage** carries `workflow.run_id` and `workflow.name` entries during workflow execution, allowing downstream services you call from steps to tag their own telemetry with the run ID.
103
+
104
+ <Callout>
105
+ Baggage entries set by your application are propagated as a `baggage` HTTP header on the SDK's backend requests, like any other OpenTelemetry-instrumented HTTP call. Avoid placing sensitive values in baggage.
106
+ </Callout>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workflow",
3
- "version": "5.0.0-beta.16",
3
+ "version": "5.0.0-beta.18",
4
4
  "description": "Workflow SDK - Build durable, resilient, and observable workflows",
5
5
  "main": "dist/typescript-plugin.cjs",
6
6
  "type": "module",
@@ -57,18 +57,18 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "ms": "2.1.3",
60
- "@workflow/astro": "5.0.0-beta.16",
61
- "@workflow/cli": "5.0.0-beta.16",
62
- "@workflow/core": "5.0.0-beta.16",
63
- "@workflow/errors": "5.0.0-beta.7",
60
+ "@workflow/astro": "5.0.0-beta.18",
61
+ "@workflow/cli": "5.0.0-beta.18",
62
+ "@workflow/core": "5.0.0-beta.18",
63
+ "@workflow/errors": "5.0.0-beta.8",
64
64
  "@workflow/typescript-plugin": "5.0.0-beta.4",
65
- "@workflow/utils": "5.0.0-beta.3",
66
- "@workflow/next": "5.0.0-beta.16",
67
- "@workflow/nest": "5.0.0-beta.16",
68
- "@workflow/nitro": "5.0.0-beta.16",
69
- "@workflow/nuxt": "5.0.0-beta.16",
70
- "@workflow/sveltekit": "5.0.0-beta.16",
71
- "@workflow/rollup": "5.0.0-beta.16"
65
+ "@workflow/utils": "5.0.0-beta.4",
66
+ "@workflow/next": "5.0.0-beta.18",
67
+ "@workflow/nest": "5.0.0-beta.18",
68
+ "@workflow/nitro": "5.0.0-beta.18",
69
+ "@workflow/nuxt": "5.0.0-beta.18",
70
+ "@workflow/sveltekit": "5.0.0-beta.18",
71
+ "@workflow/rollup": "5.0.0-beta.18"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/ms": "2.1.0",