Skip to content

Race-condition of GlobalOpenTelemetry initialization with AutoConfiguredOpenTelemetrySdkBuilder #7354

Open
@JonasKunz

Description

@JonasKunz

After upgrading our distro to the latest upstream version, one of our E2E tests suddenly started failing.
To me it looks like #7255 unfortunately introduced (or rather surfaced) a race-condition:

The agent uses the AutoConfiguredOpenTelemetrySdkBuilder directly to register the GlobalOpenTelemetry instance in OpenTelemetryInstaller. Therefore, it does not hold the mutex from GlobalOpenTelemetry while building the SDK.

In our E2E test we define a metrics-exporter with a very low export interval (e.g. 10ms). In this case it can happen that this exporter attempts to run before AutoConfiguredOpenTelemetrySdkBuilder has finished installing the GlobalOpenTelemetry instance. Due to #7255, this will result in the exporter calling GlobalOpenTelemetry.get(), effectively triggering a nested, wrong autoconfiguration.

I don't think this is a critical bug, because such low export intervals are likely to be used only in tests. Nonetheless I think we should fix the underlying issue. One approach would be to make AutoConfiguredOpenTelemetrySdkBuilder.build() hold the mutex from GlobalOpenTelemetry while building the SDK, if the builder was configured to install the SDK globally.

Error logs
    2025-05-19 10:58:05,256 [main] INFO  io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder - Error encountered during autoconfiguration. Closing partially configured components.
  2025-05-19 10:58:05,260 [PeriodicMetricReader-1] ERROR io.opentelemetry.exporter.internal.http.HttpExporter - Failed to export metrics. The request could not be executed. Full error message: executor rejected
  java.io.InterruptedIOException: executor rejected
  	at okhttp3.internal.connection.RealCall$AsyncCall.executeOn(RealCall.kt:501) ~[agent.jar:1.4.2-SNAPSHOT]
  	at okhttp3.Dispatcher.promoteAndExecute(Dispatcher.kt:184) ~[agent.jar:1.4.2-SNAPSHOT]
  	at okhttp3.Dispatcher.enqueue$okhttp(Dispatcher.kt:125) ~[agent.jar:1.4.2-SNAPSHOT]
  	at okhttp3.internal.connection.RealCall.enqueue(RealCall.kt:164) ~[agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.exporter.sender.okhttp.internal.OkHttpHttpSender.lambda$send$2(OkHttpHttpSender.java:139) ~[agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context.lambda$wrap$1(Context.java:241) ~[?:1.4.2-SNAPSHOT]
  	at io.opentelemetry.javaagent.shaded.io.opentelemetry.api.internal.InstrumentationUtil.suppressInstrumentation(InstrumentationUtil.java:28) ~[?:1.4.2-SNAPSHOT]
  	at io.opentelemetry.exporter.sender.okhttp.internal.OkHttpHttpSender.send(OkHttpHttpSender.java:135) ~[agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.exporter.internal.http.HttpExporter.export(HttpExporter.java:63) ~[agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler.export(MetricReusableDataMarshaler.java:48) [agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter.export(OtlpHttpMetricExporter.java:113) [agent.jar:1.4.2-SNAPSHOT]
  	at co.elastic.otel.dynamicconfig.BlockableMetricExporter.export(BlockableMetricExporter.java:70) [agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.doRun(PeriodicMetricReader.java:167) [agent.jar:1.4.2-SNAPSHOT]
  	at io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.run(PeriodicMetricReader.java:153) [agent.jar:1.4.2-SNAPSHOT]
  	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
  	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) [?:?]
  	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [?:?]
  	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
  	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
  	at java.base/java.lang.Thread.run(Thread.java:840) [?:?]
  Caused by: java.util.concurrent.RejectedExecutionException: Task okhttp3.internal.connection.RealCall$AsyncCall@2429452d rejected from java.util.concurrent.ThreadPoolExecutor@3bfc0e36[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
  	at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2065) ~[?:?]
  	at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:833) ~[?:?]
  	at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1365) ~[?:?]
  	at okhttp3.internal.connection.RealCall$AsyncCall.executeOn(RealCall.kt:498) ~[agent.jar:1.4.2-SNAPSHOT]
  	... 19 more
  2025-05-19 10:58:05,268 [main] INFO  io.opentelemetry.exporter.internal.http.HttpExporter - Calling shutdown() multiple times.
  2025-05-19 10:58:05,269 [main] INFO  io.opentelemetry.exporter.internal.http.HttpExporter - Calling shutdown() multiple times.
  10:58:05.272 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException: Unexpected configuration error
  10:58:05.272 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder.build(AutoConfiguredOpenTelemetrySdkBuilder.java:489)
  10:58:05.272 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.tooling.OpenTelemetryInstaller.installOpenTelemetrySdk(OpenTelemetryInstaller.java:29)
  2025-05-19 10:58:05,270 [main] INFO  io.opentelemetry.exporter.internal.http.HttpExporter - Calling shutdown() multiple times.
  2025-05-19 10:58:05,271 [main] INFO  io.opentelemetry.exporter.internal.http.HttpExporter - Calling shutdown() multiple times.
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.tooling.AgentInstaller.installBytebuddyAgent(AgentInstaller.java:160)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.tooling.AgentInstaller.installBytebuddyAgent(AgentInstaller.java:110)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.tooling.AgentStarterImpl.start(AgentStarterImpl.java:101)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.bootstrap.AgentInitializer$2.run(AgentInitializer.java:66)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.bootstrap.AgentInitializer$2.run(AgentInitializer.java:60)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.bootstrap.AgentInitializer.execute(AgentInitializer.java:82)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.bootstrap.AgentInitializer.initialize(AgentInitializer.java:59)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.OpenTelemetryAgent.startAgent(OpenTelemetryAgent.java:59)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.OpenTelemetryAgent.premain(OpenTelemetryAgent.java:46)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at co.elastic.otel.agent.ElasticAgent.premain(ElasticAgent.java:39)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:503)
  10:58:05.273 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: Caused by: java.lang.IllegalStateException: GlobalOpenTelemetry.set has already been called. GlobalOpenTelemetry.set must be called only once before any calls to GlobalOpenTelemetry.get. If you are using the OpenTelemetrySdk, use OpenTelemetrySdkBuilder.buildAndRegisterGlobal instead. Previous invocation set to cause of this exception.
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.shaded.io.opentelemetry.api.GlobalOpenTelemetry.set(GlobalOpenTelemetry.java:107)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder.maybeSetAsGlobal(AutoConfiguredOpenTelemetrySdkBuilder.java:580)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder.build(AutoConfiguredOpenTelemetrySdkBuilder.java:470)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	... 17 more
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: Caused by: java.lang.Throwable
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.shaded.io.opentelemetry.api.GlobalOpenTelemetry.set(GlobalOpenTelemetry.java:115)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.shaded.io.opentelemetry.api.GlobalOpenTelemetry.get(GlobalOpenTelemetry.java:85)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.javaagent.shaded.io.opentelemetry.api.GlobalOpenTelemetry.getMeterProvider(GlobalOpenTelemetry.java:174)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.internal.ExporterMetrics.meter(ExporterMetrics.java:90)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.internal.ExporterMetrics.seen(ExporterMetrics.java:74)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.internal.ExporterMetrics.addSeen(ExporterMetrics.java:58)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.internal.http.HttpExporter.export(HttpExporter.java:59)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler.export(MetricReusableDataMarshaler.java:48)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter.export(OtlpHttpMetricExporter.java:113)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at co.elastic.otel.dynamicconfig.BlockableMetricExporter.export(BlockableMetricExporter.java:70)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.doRun(PeriodicMetricReader.java:167)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at io.opentelemetry.sdk.metrics.export.PeriodicMetricReader$Scheduled.run(PeriodicMetricReader.java:153)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
  10:58:05.274 [docker-java-stream-2559052] INFO  c.e.j.smoketest.UserAgentHeaderTest - STDERR: 	at java.base/java.lang.Thread.run(Thread.java:840)

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