Skip to content

Commit 5541c8d

Browse files
feat(opentelemetry): add otel v2 package
1 parent bb01203 commit 5541c8d

38 files changed

Lines changed: 5486 additions & 1 deletion
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# `@temporalio/interceptors-opentelemetry-v2`
2+
3+
[![NPM](https://img.shields.io/npm/v/@temporalio/interceptors-opentelemetry-v2?style=for-the-badge)](https://www.npmjs.com/package/@temporalio/interceptors-opentelemetry-v2)
4+
5+
[Temporal](https://temporal.io)'s [TypeScript SDK](https://docs.temporal.io/typescript/introduction) interceptors for tracing Workflow and Activity executions with [OpenTelemetry](https://opentelemetry.io/) v2.
6+
7+
This package targets OpenTelemetry JS SDK v2. For OpenTelemetry JS SDK v1, use [`@temporalio/interceptors-opentelemetry`](https://www.npmjs.com/package/@temporalio/interceptors-opentelemetry).
8+
9+
- [Interceptors docs](https://docs.temporal.io/typescript/interceptors)
10+
- [OpenTelemetry Interceptor example setup](https://github.com/temporalio/samples-typescript/tree/main/interceptors-opentelemetry)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"name": "@temporalio/interceptors-opentelemetry-v2",
3+
"version": "1.15.0",
4+
"description": "Temporal.io SDK interceptors bundle for tracing with opentelemetry v2",
5+
"main": "lib/index.js",
6+
"types": "./lib/index.d.ts",
7+
"scripts": {
8+
"build": "tsc --build",
9+
"test": "ava ./lib/__tests__/test-*.js"
10+
},
11+
"keywords": [
12+
"temporal",
13+
"workflow",
14+
"interceptors",
15+
"opentelemetry"
16+
],
17+
"author": "Temporal Technologies Inc. <sdk@temporal.io>",
18+
"license": "MIT",
19+
"dependencies": {
20+
"@opentelemetry/api": "^1.9.0",
21+
"@opentelemetry/core": "^2.2.0",
22+
"@opentelemetry/resources": "^2.2.0",
23+
"@opentelemetry/sdk-trace-base": "^2.2.0",
24+
"@temporalio/plugin": "workspace:*"
25+
},
26+
"devDependencies": {
27+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.208.0",
28+
"@opentelemetry/sdk-node": "^0.208.0",
29+
"@opentelemetry/semantic-conventions": "^1.38.0",
30+
"@temporalio/activity": "workspace:*",
31+
"@temporalio/client": "workspace:*",
32+
"@temporalio/common": "workspace:*",
33+
"@temporalio/proto": "workspace:*",
34+
"@temporalio/test-helpers": "workspace:*",
35+
"@temporalio/testing": "workspace:*",
36+
"@temporalio/worker": "workspace:*",
37+
"@temporalio/workflow": "workspace:*",
38+
"ava": "^5.3.1",
39+
"uuid": "^11.1.0"
40+
},
41+
"peerDependencies": {
42+
"@temporalio/common": "workspace:*",
43+
"@temporalio/workflow": "workspace:*"
44+
},
45+
"peerDependenciesMeta": {
46+
"@temporalio/workflow": {
47+
"optional": true
48+
}
49+
},
50+
"bugs": {
51+
"url": "https://github.com/temporalio/sdk-typescript/issues"
52+
},
53+
"repository": {
54+
"type": "git",
55+
"url": "git+https://github.com/temporalio/sdk-typescript.git",
56+
"directory": "packages/interceptors-opentelemetry-v2"
57+
},
58+
"homepage": "https://github.com/temporalio/sdk-typescript/tree/main/packages/interceptors-opentelemetry-v2",
59+
"publishConfig": {
60+
"access": "public"
61+
},
62+
"engines": {
63+
"node": ">= 20.0.0"
64+
},
65+
"files": [
66+
"src",
67+
"lib",
68+
"!src/__tests__",
69+
"!lib/__tests__"
70+
],
71+
"ava": {
72+
"timeout": "120s",
73+
"concurrency": 1,
74+
"workerThreads": false
75+
}
76+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { WorkflowHandle } from '@temporalio/client';
2+
import { QueryDefinition } from '@temporalio/common';
3+
import { Context } from '@temporalio/activity';
4+
5+
function getSchedulingWorkflowHandle(): WorkflowHandle {
6+
const { info, client } = Context.current();
7+
const { workflowExecution } = info;
8+
return client.workflow.getHandle(workflowExecution.workflowId, workflowExecution.runId);
9+
}
10+
11+
export async function signalSchedulingWorkflow(signalName: string): Promise<void> {
12+
const handle = getSchedulingWorkflowHandle();
13+
await handle.signal(signalName);
14+
}
15+
16+
export async function queryOwnWf<R, A extends any[]>(queryDef: QueryDefinition<R, A>, ...args: A): Promise<R> {
17+
const handle = getSchedulingWorkflowHandle();
18+
return await handle.query(queryDef, ...args);
19+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { activityInfo, Context } from '@temporalio/activity';
2+
import { ApplicationFailure, ApplicationFailureCategory, CancelledFailure } from '@temporalio/common';
3+
4+
export { queryOwnWf, signalSchedulingWorkflow } from './helpers';
5+
6+
export async function echo(message?: string): Promise<string> {
7+
return message ?? 'echo';
8+
}
9+
10+
export async function fakeProgress(sleepIntervalMs = 1000, numIters = 100): Promise<void> {
11+
await signalSchedulingWorkflow('activityStarted');
12+
try {
13+
for (let progress = 1; progress <= numIters; ++progress) {
14+
await Context.current().sleep(sleepIntervalMs);
15+
Context.current().heartbeat(progress);
16+
}
17+
} catch (err) {
18+
if (!(err instanceof CancelledFailure)) {
19+
throw err;
20+
}
21+
throw err;
22+
}
23+
}
24+
25+
async function signalSchedulingWorkflow(signalName: string): Promise<void> {
26+
const { info, client } = Context.current();
27+
const { workflowExecution } = info;
28+
const handle = client.workflow.getHandle(workflowExecution.workflowId, workflowExecution.runId);
29+
await handle.signal(signalName);
30+
}
31+
32+
export async function throwMaybeBenign(): Promise<void> {
33+
if (activityInfo().attempt === 1) {
34+
throw ApplicationFailure.create({ message: 'not benign' });
35+
}
36+
if (activityInfo().attempt === 2) {
37+
throw ApplicationFailure.create({ message: 'benign', category: ApplicationFailureCategory.BENIGN });
38+
}
39+
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
{
2+
"events": [
3+
{
4+
"eventId": "1",
5+
"eventTime": "2025-10-17T12:56:44.200769Z",
6+
"eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED",
7+
"taskId": "1049716",
8+
"workflowExecutionStartedEventAttributes": {
9+
"workflowType": {
10+
"name": "signalStartOtel"
11+
},
12+
"taskQueue": {
13+
"name": "test-otel-inbound",
14+
"kind": "TASK_QUEUE_KIND_NORMAL"
15+
},
16+
"input": {},
17+
"workflowTaskTimeout": "10s",
18+
"originalExecutionRunId": "10b7e171-0ee7-4775-ad6d-f5df09aa4160",
19+
"identity": "82936@mac.lan",
20+
"firstExecutionRunId": "10b7e171-0ee7-4775-ad6d-f5df09aa4160",
21+
"attempt": 1,
22+
"firstWorkflowTaskBackoff": "0s",
23+
"header": {
24+
"fields": {}
25+
},
26+
"workflowId": "f61035b7-9fa3-4120-ac03-98763ccd469a"
27+
}
28+
},
29+
{
30+
"eventId": "2",
31+
"eventTime": "2025-10-17T12:56:44.200815Z",
32+
"eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED",
33+
"taskId": "1049717",
34+
"workflowExecutionSignaledEventAttributes": {
35+
"signalName": "startSignal",
36+
"input": {},
37+
"identity": "82936@mac.lan",
38+
"header": {
39+
"fields": {}
40+
}
41+
}
42+
},
43+
{
44+
"eventId": "3",
45+
"eventTime": "2025-10-17T12:56:44.200819Z",
46+
"eventType": "EVENT_TYPE_WORKFLOW_TASK_SCHEDULED",
47+
"taskId": "1049718",
48+
"workflowTaskScheduledEventAttributes": {
49+
"taskQueue": {
50+
"name": "test-otel-inbound",
51+
"kind": "TASK_QUEUE_KIND_NORMAL"
52+
},
53+
"startToCloseTimeout": "10s",
54+
"attempt": 1
55+
}
56+
},
57+
{
58+
"eventId": "4",
59+
"eventTime": "2025-10-17T12:56:44.201794Z",
60+
"eventType": "EVENT_TYPE_WORKFLOW_TASK_STARTED",
61+
"taskId": "1049722",
62+
"workflowTaskStartedEventAttributes": {
63+
"scheduledEventId": "3",
64+
"identity": "82936@mac.lan",
65+
"requestId": "488319d7-d425-44eb-b5ce-362f8462be1f",
66+
"historySizeBytes": "327",
67+
"workerVersion": {
68+
"buildId": "@temporalio/worker@1.13.1+6b92c11c4f907379345c3513a5f749c90d752cfd0a3bf888bf0be04350bb0d2e"
69+
}
70+
}
71+
},
72+
{
73+
"eventId": "5",
74+
"eventTime": "2025-10-17T12:56:44.229959Z",
75+
"eventType": "EVENT_TYPE_WORKFLOW_TASK_COMPLETED",
76+
"taskId": "1049726",
77+
"workflowTaskCompletedEventAttributes": {
78+
"scheduledEventId": "3",
79+
"startedEventId": "4",
80+
"identity": "82936@mac.lan",
81+
"workerVersion": {
82+
"buildId": "@temporalio/worker@1.13.1+6b92c11c4f907379345c3513a5f749c90d752cfd0a3bf888bf0be04350bb0d2e"
83+
},
84+
"sdkMetadata": {
85+
"coreUsedFlags": [1, 3, 2],
86+
"langUsedFlags": [2],
87+
"sdkName": "temporal-typescript",
88+
"sdkVersion": "1.11.3"
89+
},
90+
"meteringMetadata": {}
91+
}
92+
},
93+
{
94+
"eventId": "6",
95+
"eventTime": "2025-10-17T12:56:44.229985Z",
96+
"eventType": "EVENT_TYPE_MARKER_RECORDED",
97+
"taskId": "1049727",
98+
"markerRecordedEventAttributes": {
99+
"details": {
100+
"data": {
101+
"payloads": [
102+
{
103+
"metadata": {
104+
"encoding": "anNvbi9wbGFpbg=="
105+
},
106+
"data": "eyJzZXEiOjEsImF0dGVtcHQiOjEsImFjdGl2aXR5X2lkIjoiMSIsImFjdGl2aXR5X3R5cGUiOiJhIiwiY29tcGxldGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjAyMzY4NjY3fSwiYmFja29mZiI6bnVsbCwib3JpZ2luYWxfc2NoZWR1bGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjI0MTE2MDAwfX0="
107+
}
108+
]
109+
},
110+
"result": {
111+
"payloads": [
112+
{
113+
"metadata": {
114+
"encoding": "anNvbi9wbGFpbg=="
115+
},
116+
"data": "ImEi"
117+
}
118+
]
119+
}
120+
},
121+
"markerName": "core_local_activity",
122+
"workflowTaskCompletedEventId": "5"
123+
}
124+
},
125+
{
126+
"eventId": "7",
127+
"eventTime": "2025-10-17T12:56:44.229986Z",
128+
"eventType": "EVENT_TYPE_MARKER_RECORDED",
129+
"taskId": "1049728",
130+
"markerRecordedEventAttributes": {
131+
"details": {
132+
"result": {
133+
"payloads": [
134+
{
135+
"metadata": {
136+
"encoding": "anNvbi9wbGFpbg=="
137+
},
138+
"data": "ImIi"
139+
}
140+
]
141+
},
142+
"data": {
143+
"payloads": [
144+
{
145+
"metadata": {
146+
"encoding": "anNvbi9wbGFpbg=="
147+
},
148+
"data": "eyJzZXEiOjIsImF0dGVtcHQiOjEsImFjdGl2aXR5X2lkIjoiMiIsImFjdGl2aXR5X3R5cGUiOiJiIiwiY29tcGxldGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjAyNjc1OTE3fSwiYmFja29mZiI6bnVsbCwib3JpZ2luYWxfc2NoZWR1bGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjI3MzQ4MDAwfX0="
149+
}
150+
]
151+
}
152+
},
153+
"markerName": "core_local_activity",
154+
"workflowTaskCompletedEventId": "5"
155+
}
156+
},
157+
{
158+
"eventId": "8",
159+
"eventTime": "2025-10-17T12:56:44.230034Z",
160+
"eventType": "EVENT_TYPE_MARKER_RECORDED",
161+
"taskId": "1049729",
162+
"markerRecordedEventAttributes": {
163+
"details": {
164+
"data": {
165+
"payloads": [
166+
{
167+
"metadata": {
168+
"encoding": "anNvbi9wbGFpbg=="
169+
},
170+
"data": "eyJzZXEiOjMsImF0dGVtcHQiOjEsImFjdGl2aXR5X2lkIjoiMyIsImFjdGl2aXR5X3R5cGUiOiJjIiwiY29tcGxldGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjAyNzI0ODM0fSwiYmFja29mZiI6bnVsbCwib3JpZ2luYWxfc2NoZWR1bGVfdGltZSI6eyJzZWNvbmRzIjoxNzYwNzA1ODA0LCJuYW5vcyI6MjI3MzU2MDAwfX0="
171+
}
172+
]
173+
},
174+
"result": {
175+
"payloads": [
176+
{
177+
"metadata": {
178+
"encoding": "anNvbi9wbGFpbg=="
179+
},
180+
"data": "ImMi"
181+
}
182+
]
183+
}
184+
},
185+
"markerName": "core_local_activity",
186+
"workflowTaskCompletedEventId": "5"
187+
}
188+
},
189+
{
190+
"eventId": "9",
191+
"eventTime": "2025-10-17T12:56:44.230036Z",
192+
"eventType": "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED",
193+
"taskId": "1049730",
194+
"workflowExecutionCompletedEventAttributes": {
195+
"result": {
196+
"payloads": [
197+
{
198+
"metadata": {
199+
"encoding": "anNvbi9wbGFpbg=="
200+
},
201+
"data": "ImFiYyI="
202+
}
203+
]
204+
},
205+
"workflowTaskCompletedEventId": "5"
206+
}
207+
}
208+
]
209+
}

0 commit comments

Comments
 (0)