Skip to content

feat(opentelemetry) add @temporalio/interceptors-opentelemetry-v2#1951

Open
chris-olszewski wants to merge 3 commits intoolszewski/break_up_buildfrom
olszewski/feat_otel_v2
Open

feat(opentelemetry) add @temporalio/interceptors-opentelemetry-v2#1951
chris-olszewski wants to merge 3 commits intoolszewski/break_up_buildfrom
olszewski/feat_otel_v2

Conversation

@chris-olszewski
Copy link
Copy Markdown
Member

@chris-olszewski chris-olszewski commented Feb 26, 2026

What was changed

Add a package to provide interceptors that support OpenTelemetry v2.

First commit is a straight copy of the v1 with package bumps and the necessary changes the came along with those bumps.

Note: Histories created with the @temporalio/interceptors-opentelemetry will not be compatible with @temporalio/interceptors-opentelemetry and vice-versa. The crux of the issue is that OpenTelemetry changed their usage of Math.random(). The random number generator was shared by OpenTelemetry for generating span ids as well as the uuid function which is used for generating child workflow ids. This can cause NDE. To prevent future breakages from changes to Math.random usage, we now provide an IdGenerator to OpenTelemetry that uses its own random number generator. This doesn't offer a huge amount of value as we are still vulnerable to changes to the amount of calls to Math.random outside of id creation, but it does offer protection if the number of ids created changes.

Due to histories already being incompatible, I removed the yield point injections from the interceptors to have a cleaner starting point.

Why?

This was done in a separate package to allow us to support both v1 and v2 without forcing users to upgrade.

Checklist

  1. Closes [Feature Request] Add support for opentelemetry v2 #1658

  2. How was this tested:
    Copied over relevant tests and added an additional test to verify that replaying workflow history that has uuid call doesn't trigger NDE in the future.

  3. Any docs updates needed?

@chris-olszewski chris-olszewski marked this pull request as ready for review March 10, 2026 14:53
@chris-olszewski chris-olszewski requested a review from a team as a code owner March 10, 2026 14:53
@grant0417
Copy link
Copy Markdown

Since you are making a breaking v2 version, could you also align the spanProcessor with how it works in the @opentelemetry/sdk-node package.

The spanProcessor arg is deprecated in favor of spanProcessors which is an array of processors. This would allow using the same arg to both the temporal OpenTelemetryPlugin and NodeSDK.

Example:

const resource = resourceFromAttributes({ [ATTR_SERVICE_NAME]: "temporal-worker" });
const spanProcessors = [new SpanProcessor1(), new SpanProcessor2()];

// exact same args
const sdk = new NodeSDK({ resource, spanProcessors });
const plugin = OpenTelemetryPlugin({ resource, spanProcessors });

clientInterceptors: {
workflow: [new OpenTelemetryWorkflowClientInterceptor(interceptorOptions)],
},
workerInterceptors: {
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.

We need to add nexus interceptors

export * from './worker';
export {
OpenTelemetryWorkflowClientInterceptor,
/** deprecated: Use OpenTelemetryWorkflowClientInterceptor instead */
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.

You can get rid of that legacy thing.

*
* @experimental Plugins is an experimental feature; APIs may change without notice.
*/
export class OpenTelemetryPlugin extends SimplePlugin {
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.

Are we not injecting bundler options?

Btw, we now have a preloadedModules bundler option, which may help reduce the overhead associated with per-workflow loading of the OpenTelemetry library.

* @module
*/
export { inWorkflowContext, proxySinks, workflowInfo, AsyncLocalStorage, ContinueAsNew } from '@temporalio/workflow';
export { alea, type RNG } from '@temporalio/workflow/lib/alea';
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.

Use the new random streams api once it has landed.

@@ -0,0 +1,54 @@
import type { IdGenerator } from '@opentelemetry/sdk-trace-base';
import { alea, type RNG } from './workflow-imports';
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.

Use the new Random Streams API, once it has landed.

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.

3 participants