Node.js Notification API: WebSocket reconnect loop causing context propagation loss in OTel spans

We’re hitting a wall with our OpenTelemetry tracing setup for Genesys Cloud Data Actions. The goal is to propagate trace context through WebSocket notification events so we can correlate backend processing with frontend triggers.

The issue starts when the WebSocket connection drops. Our Node.js client attempts to reconnect, but the new connection doesn’t seem to inherit the parent span context correctly. Instead, we get orphaned spans in Jaeger that have no parent.

Here’s the reconnection logic we’ve written:

const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('gc-notifications');

let ws;
let currentSpan;

function connect() {
 const parentSpan = tracer.startSpan('ws.connect');
 currentSpan = parentSpan;
 
 ws = new WebSocket('wss://api.mypurecloud.com/api/v2/notifications');
 
 ws.on('open', () => {
 // Inject context into the subscription payload
 const headers = {};
 trace.propagation.inject(trace.context.active(), headers);
 
 ws.send(JSON.stringify({
 type: 'subscribe',
 resource: 'routing/users',
 headers: headers // Attempting to pass traceparent here
 }));
 });

 ws.on('message', (data) => {
 const span = tracer.startSpan('ws.message.handler', {
 links: [{ context: trace.propagation.extract(trace.context.active(), data.headers) }]
 });
 // Process event
 span.end();
 });

 ws.on('close', (code, reason) => {
 console.log(`Disconnected: ${code}`);
 // Reconnect after delay
 setTimeout(connect, 5000);
 });
}

connect();

The problem is that when connect() is called again after a close event, the tracer.startSpan('ws.connect') creates a new root span because the previous context isn’t being carried over properly. We’ve tried wrapping the reconnect call in tracer.withSpan(currentSpan), but it feels like a hack and doesn’t always stick.

Is there a standard pattern for maintaining trace context across WebSocket reconnections in Node.js? Or are we missing something in how the Genesys Cloud Notification API handles headers during the subscription phase?