Skip to content

Commit

Permalink
Prevent NPE when using otel metrics bridge asynchronously to agent start
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasKunz committed Nov 20, 2024
1 parent fe707e0 commit 4ae56e6
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
*/
package co.elastic.apm.agent.embeddedotel;

import co.elastic.apm.agent.tracer.AbstractLifecycleListener;
import co.elastic.apm.agent.embeddedotel.proxy.ProxyMeterProvider;
import co.elastic.apm.agent.sdk.logging.Logger;
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
import co.elastic.apm.agent.tracer.AbstractLifecycleListener;
import co.elastic.apm.agent.tracer.Tracer;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;

Expand Down Expand Up @@ -65,6 +66,10 @@ public ProxyMeterProvider getMeterProvider() {
if (sdkInstance == null) {
startSdk();
}
if (sdkInstance == null) {
logger.warn("Returning NoOp-MeterProvider because OpenTelemetry metrics SDK could not be initialized!");
return new ProxyMeterProvider(MeterProvider.noop());
}
return new ProxyMeterProvider(sdkInstance);
}

Expand All @@ -78,7 +83,11 @@ synchronized void reset() {
}

private synchronized void startSdk() {
if (isShutdown || sdkInstance != null || tracer == null) {
if (isShutdown || sdkInstance != null) {
return;
}
if (tracer == null) {
logger.warn("Cannot initialize OpenTelemetry metrics SDK because tracer has not started yet");
return;
}
logger.debug("Starting embedded OpenTelemetry metrics SDK");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package co.elastic.apm.agent.embeddedotel;

import co.elastic.apm.agent.embeddedotel.proxy.ProxyMeter;
import co.elastic.apm.agent.tracer.Tracer;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class EmbeddedSdkManagerTest {

/**
* The instrumentation of the agent is performed before {@link EmbeddedSdkManager#init(Tracer)} is invoked.
* This means if the agent is started asynchronously, it can happen that {@link EmbeddedSdkManager#getMeterProvider()}
* is invoked before the tracer has been provided.
* This test verifies that in that case no exception occurs and a noop-meter implementation is used.
*/
@Test
public void ensureNoExceptionOnMissingTracer() throws Exception {
ProxyMeter meter = new EmbeddedSdkManager().getMeterProvider().get("foobar");
assertThat(meter.getDelegate()).isInstanceOf(Class.forName("io.opentelemetry.api.metrics.DefaultMeter"));
}
}

0 comments on commit 4ae56e6

Please sign in to comment.