Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions references/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ Temporal ships and supports a growing set of integrations with third-party frame
| LangSmith tracing (`temporalio.contrib.langsmith`) | Python | Experimental Temporal Plugin that propagates LangSmith trace context across Worker boundaries; lets `@traceable` run inside Workflows and Activities | `references/python/integrations/langsmith.md` | `references/python/ai-patterns.md`, `references/core/ai-patterns.md` |
| LangGraph (`temporalio.contrib.langgraph`, Pre-release) | Python | Runs LangGraph Graph-API and Functional-API code as Temporal Workflows - nodes/tasks can execute as either in-workflow or as Activities | `references/python/integrations/langgraph.md` | `references/python/ai-patterns.md`, `references/core/ai-patterns.md` |
| Google ADK (`temporalio[google-adk]`) | Python | Durable Google ADK agents: model calls run through `TemporalModel`-wrapped Activities, tools via `activity_tool`, MCP toolsets via `TemporalMcpToolSet` | `references/python/integrations/google-adk.md` | `references/python/ai-patterns.md`, `references/core/ai-patterns.md` |
| OpenTelemetry (`@temporalio/interceptors-opentelemetry`) | TypeScript | Distributed tracing for Temporal apps with OpenTelemetry | `references/typescript/integrations/opentelemetry.md` | `references/typescript/observability.md`, `references/typescript/standalone-activities.md` |
77 changes: 77 additions & 0 deletions references/typescript/integrations/opentelemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Temporal OpenTelemetry Integration (TypeScript)

## Overview

`@temporalio/interceptors-opentelemetry` wires OpenTelemetry tracing into Temporal through the `OpenTelemetryPlugin`. It traces Workflow Executions, Child Workflows, Activity invocations, and Client `start`/`signal` calls, propagating W3C TraceContext + Baggage across all of them.

Workflow-side spans are emitted out of the Workflow isolate through an injected Sink that hands serialized spans to a host-side `SpanProcessor`.

For non-OTel observability (metrics, runtime logger, sinks) read `references/typescript/observability.md`.

> [!NOTE]
> This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

## Install the plugin

Install `@temporalio/interceptors-opentelemetry` plus the OpenTelemetry peer packages you use — typically `@opentelemetry/api`, `@opentelemetry/sdk-trace-base`, and `@opentelemetry/resources` (plus an exporter package such as `@opentelemetry/exporter-trace-otlp-grpc` when you ship spans to a collector).

## `OpenTelemetryPlugin`

Construct one `OpenTelemetryPlugin` and pass it to the Client, `bundleWorkflowCode`, and `Worker.create`. It must reach `bundleWorkflowCode` so the Workflow-side interceptors are included in the bundle. Lifecycle spans (workflow / activity / client) are then created automatically.

```ts
import { Resource } from '@opentelemetry/resources';
import { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { NativeConnection, Worker, bundleWorkflowCode } from '@temporalio/worker';
import { OpenTelemetryPlugin } from '@temporalio/interceptors-opentelemetry';

const resource = new Resource({ 'service.name': 'orders-worker' });
const spanProcessor = new SimpleSpanProcessor(new ConsoleSpanExporter()); // swap in your own exporter

const provider = new BasicTracerProvider({ resource });
provider.addSpanProcessor(spanProcessor);
provider.register();

// `resource` and `spanProcessor` are required; pass an optional `tracer` to override
// the tracer used by the Client/Activity interceptors.
const plugin = new OpenTelemetryPlugin({ resource, spanProcessor });

const bundle = await bundleWorkflowCode({
workflowsPath: require.resolve('./workflows'),
plugins: [plugin],
});

const connection = await NativeConnection.connect();
const worker = await Worker.create({
connection,
taskQueue: 'orders',
workflowBundle: bundle,
activities: { /* ... */ },
plugins: [plugin],
});
await worker.run();
```

Pass the same plugin to the Client so client-side `start` and `signal` calls are traced:

```ts
import { Client, Connection } from '@temporalio/client';

const client = new Client({
connection: await Connection.connect(),
plugins: [plugin],
});
```

The SDK uses the global OpenTelemetry propagator (default: W3C TraceContext + Baggage). To use a non-default propagator (e.g. Jaeger), call `propagation.setGlobalPropagator(...)` at the top level of your Workflow code BEFORE the Worker bundles it.

## Common mistakes

- **Passing only `resource` or only `spanProcessor`.** Both are required; `new OpenTelemetryPlugin()` with no argument throws.
- **Passing the plugin to `Worker.create` but not `bundleWorkflowCode`.** Workflow-side interceptors must be in the bundle.
- **Installing `@temporalio/opentelemetry`.** The package is `@temporalio/interceptors-opentelemetry`.
- **Expecting a non-default propagator (e.g. Jaeger) to work without setting the global propagator before `bundleWorkflowCode` runs.**

## Resources

- SDK metrics / observability reference: `references/typescript/observability.md`
52 changes: 51 additions & 1 deletion references/typescript/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## Overview

The TypeScript SDK provides replay-aware logging, metrics, and integrations for production observability.
The TypeScript SDK provides replay-aware logging, metrics, and distributed tracing (OpenTelemetry) for production observability.

These pillars are complementary: **logging** (below) captures discrete events, **metrics** capture aggregate worker health, **tracing** stitches a single request across Client/Workflow/Activity boundaries, and **Search Attributes** make executions queryable.

## Replay-Aware Logging

Expand Down Expand Up @@ -100,6 +102,53 @@ Runtime.install({
});
```

## Distributed Tracing (OpenTelemetry)

> [!NOTE]
> This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

OpenTelemetry is the supported way to add distributed tracing to Temporal applications. The `OpenTelemetryPlugin` (from `@temporalio/interceptors-opentelemetry`) traces Workflow Executions, Child Workflows, Activity invocations, and Client `start`/`signal` calls, propagating W3C TraceContext + Baggage across all of them. Workflow-side spans are exported out of the Workflow isolate through an injected Sink.

Construct one plugin instance and pass it to the Client, to `bundleWorkflowCode`, and to `Worker.create` (the Workflow-side interceptors must be in the bundle):

```typescript
import { Resource } from '@opentelemetry/resources';
import { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { Client, Connection } from '@temporalio/client';
import { NativeConnection, Worker, bundleWorkflowCode } from '@temporalio/worker';
import { OpenTelemetryPlugin } from '@temporalio/interceptors-opentelemetry';

const resource = new Resource({ 'service.name': 'my-worker' });
const spanProcessor = new SimpleSpanProcessor(new ConsoleSpanExporter()); // swap in your own exporter

const provider = new BasicTracerProvider({ resource });
provider.addSpanProcessor(spanProcessor);
provider.register();

const plugin = new OpenTelemetryPlugin({ resource, spanProcessor });

// In your worker process:
const bundle = await bundleWorkflowCode({
workflowsPath: require.resolve('./workflows'),
plugins: [plugin],
});
const worker = await Worker.create({
connection: await NativeConnection.connect(),
taskQueue: 'my-task-queue',
workflowBundle: bundle,
plugins: [plugin],
});
await worker.run();

// In your client process, pass the same plugin:
const client = new Client({
connection: await Connection.connect(),
plugins: [plugin],
});
```

For the full setup and options, see `references/typescript/integrations/opentelemetry.md`.

## Search Attributes (Visibility)

See the Search Attributes section of `references/typescript/data-handling.md`
Expand All @@ -111,3 +160,4 @@ See the Search Attributes section of `references/typescript/data-handling.md`
3. Configure Winston or similar for production log aggregation
4. Monitor Prometheus metrics for worker health
5. Use Event History for debugging workflow issues
6. Use the `OpenTelemetryPlugin` for distributed tracing across Client/Workflow/Activity boundaries.