Skip to content

opentelemetry() incorrectly checks ProxyTracer instance to detect SDK init #70

@heiwen

Description

@heiwen

What version of Elysia is running?

1.4.27

What platform is your computer?

No response

What steps can reproduce the bug?

opentelemetry() currently decides whether it should call new NodeSDK(...).start() by checking:

let tracer = trace.getTracer(serviceName)

if (tracer instanceof ProxyTracer) {
  const sdk = new NodeSDK({
    ...options,
    serviceName,
    instrumentations
  })

  sdk.start()
  tracer = trace.getTracer(serviceName)
}

Checking the tracer instance type is the wrong signal for that.

The OpenTelemetry API already exposes the provider via trace.getTracerProvider(), and the proxy provider exposes getDelegate(). That is a more reliable place to detect whether the provider is still delegating to NoopTracerProvider.

Expected behavior

opentelemetry() should only call NodeSDK.start() when the global tracer provider is still the default proxy/noop setup.

If a real tracer provider is already registered, it should skip SDK initialization.

Actual behavior

The current instanceof ProxyTracer check produces false negatives because even after initialisation the tracer is usually still a ProxyTracer.

Suggested fix

Replace the tracer-instance check with a provider-level check.

Proposed implementation

const hasRegisteredTracerProvider = () => {
  const provider = trace.getTracerProvider() as {
    getDelegate?: () => { constructor?: { name?: string } } | undefined
  }

  if (typeof provider.getDelegate !== 'function') return true

  return provider.getDelegate()?.constructor?.name !== 'NoopTracerProvider'
}

export const opentelemetry = ({
  serviceName = 'Elysia',
  instrumentations,
  contextManager,
  checkIfShouldTrace,
  ...options
}: ElysiaOpenTelemetryOptions = {}) => {
  let tracer = trace.getTracer(serviceName)

  if (!hasRegisteredTracerProvider()) {
    const sdk = new NodeSDK({
      ...options,
      serviceName,
      instrumentations
    })

    sdk.start()
    tracer = trace.getTracer(serviceName)
  }

  // existing logic continues...
}

Why this is better

Matches the actual thing we care about: whether the global provider is still noop/proxy-backed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions