diff --git a/api/incubator/README.md b/api/incubator/README.md
index 84e10a2a78b..ccd4678df43 100644
--- a/api/incubator/README.md
+++ b/api/incubator/README.md
@@ -14,6 +14,7 @@ See [EventApiUsageTest](./src/test/java/io/opentelemetry/api/incubator/events/Ev
Features:
+* Check if logger is enabled before emitting logs to avoid uneccessary computation
* Set AnyValue log record body with arbitrarily complex data
See [ExtendedLogsBridgeApiUsageTest](./src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java).
@@ -30,6 +31,7 @@ See [ExtendedMetricsApiUsageTest](./src/test/java/io/opentelemetry/api/incubator
Features:
+* Check if instrument is enabled before recording measurements to avoid uneccessary computation
* Simplified injection / extraction of context
See [ExtendedContextPropagatorsUsageTest](./src/test/java/io/opentelemetry/api/incubator/propagation/ExtendedContextPropagatorsUsageTest.java).
@@ -38,6 +40,7 @@ See [ExtendedContextPropagatorsUsageTest](./src/test/java/io/opentelemetry/api/i
Features:
+* Check if tracer is enabled before starting spans to avoid uneccessary computation
* Utility methods to reduce boilerplace using span API, including extracting context, and wrapping runnables / callables with spans
See [ExtendedTraceApiUsageTest](./src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java).
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
new file mode 100644
index 00000000000..db5e2a3b029
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.logs;
+
+import io.opentelemetry.api.logs.Logger;
+
+/** Extended {@link Logger} with experimental APIs. */
+public interface ExtendedLogger extends Logger {
+
+ /**
+ * Returns {@code true} if the logger is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #logRecordBuilder()}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleCounter.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleCounter.java
new file mode 100644
index 00000000000..4345661ebe5
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleCounter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleCounter;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link DoubleCounter} with experimental APIs. */
+public interface ExtendedDoubleCounter extends DoubleCounter {
+
+ /**
+ * Returns {@code true} if the counter is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #add(double)}, {@link #add(double, Attributes)}, or {@link #add(double,
+ * Attributes, Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleGauge.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleGauge.java
new file mode 100644
index 00000000000..d9a56f7a391
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleGauge.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleGauge;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link DoubleGauge} with experimental APIs. */
+public interface ExtendedDoubleGauge extends DoubleGauge {
+
+ /**
+ * Returns {@code true} if the gauge is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #set(double)}, {@link #set(double, Attributes)}, or {@link #set(double,
+ * Attributes, Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleHistogram.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleHistogram.java
new file mode 100644
index 00000000000..0a481afef2b
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleHistogram.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleHistogram;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link DoubleHistogram} with experimental APIs. */
+public interface ExtendedDoubleHistogram extends DoubleHistogram {
+
+ /**
+ * Returns {@code true} if the histogram is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #record(double)}, {@link #record(double, Attributes)}, or {@link #record(double,
+ * Attributes, Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleUpDownCounter.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleUpDownCounter.java
new file mode 100644
index 00000000000..6dbb91f1d6f
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleUpDownCounter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleUpDownCounter;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link DoubleUpDownCounter} with experimental APIs. */
+public interface ExtendedDoubleUpDownCounter extends DoubleUpDownCounter {
+
+ /**
+ * Returns {@code true} if the up down counter is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #add(double)}, {@link #add(double, Attributes)}, or {@link #add(double,
+ * Attributes, Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongCounter.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongCounter.java
new file mode 100644
index 00000000000..0ff67a38fb9
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongCounter.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.DoubleCounter;
+import io.opentelemetry.api.metrics.LongCounter;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link DoubleCounter} with experimental APIs. */
+public interface ExtendedLongCounter extends LongCounter {
+
+ /**
+ * Returns {@code true} if the counter is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #add(long)}, {@link #add(long, Attributes)}, or {@link #add(long, Attributes,
+ * Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongGauge.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongGauge.java
new file mode 100644
index 00000000000..7a660d0e007
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongGauge.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.LongGauge;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link LongGauge} with experimental APIs. */
+public interface ExtendedLongGauge extends LongGauge {
+
+ /**
+ * Returns {@code true} if the gauge is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #set(long)}, {@link #set(long, Attributes)}, or {@link #set(long, Attributes,
+ * Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongHistogram.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongHistogram.java
new file mode 100644
index 00000000000..d1cd303fb7d
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongHistogram.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.LongHistogram;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link LongHistogram} with experimental APIs. */
+public interface ExtendedLongHistogram extends LongHistogram {
+
+ /**
+ * Returns {@code true} if the histogram is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #record(long)}, {@link #record(long, Attributes)}, or {@link #record(long,
+ * Attributes, Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongUpDownCounter.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongUpDownCounter.java
new file mode 100644
index 00000000000..7327ed43842
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongUpDownCounter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.metrics;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.LongUpDownCounter;
+import io.opentelemetry.context.Context;
+
+/** Extended {@link LongUpDownCounter} with experimental APIs. */
+public interface ExtendedLongUpDownCounter extends LongUpDownCounter {
+
+ /**
+ * Returns {@code true} if the up down counter is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #add(long)}, {@link #add(long, Attributes)}, or {@link #add(long, Attributes,
+ * Context)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedTracer.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedTracer.java
new file mode 100644
index 00000000000..cb2cae27c24
--- /dev/null
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedTracer.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.api.incubator.trace;
+
+import io.opentelemetry.api.trace.Tracer;
+
+/** Extended {@link Tracer} with experimental APIs. */
+public interface ExtendedTracer extends Tracer {
+
+ /**
+ * Returns {@code true} if the tracer is enabled.
+ *
+ *
This allows callers to avoid unnecessary compute when nothing is consuming the data. Because
+ * the response is subject to change over the application, callers should call this before each
+ * call to {@link #spanBuilder(String)}.
+ */
+ default boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
index 7a1f82e64d0..7a3d7c82e17 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
@@ -5,21 +5,82 @@
package io.opentelemetry.api.incubator.logs;
+import static io.opentelemetry.sdk.internal.ScopeConfiguratorBuilder.nameEquals;
+import static io.opentelemetry.sdk.logs.internal.LoggerConfig.disabled;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import com.google.common.collect.ImmutableMap;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
+import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
import io.opentelemetry.sdk.logs.internal.AnyValueBody;
+import io.opentelemetry.sdk.logs.internal.SdkLoggerProviderUtil;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
+import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
/** Demonstrating usage of extended Logs Bridge API. */
class ExtendedLogsBridgeApiUsageTest {
+ @Test
+ void loggerEnabled() {
+ // Setup SdkLoggerProvider
+ InMemoryLogRecordExporter exporter = InMemoryLogRecordExporter.create();
+ SdkLoggerProviderBuilder loggerProviderBuilder =
+ SdkLoggerProvider.builder()
+ // Default resource used for demonstration purposes
+ .setResource(Resource.getDefault())
+ // In-memory exporter used for demonstration purposes
+ .addLogRecordProcessor(SimpleLogRecordProcessor.create(exporter));
+ // Disable loggerB
+ SdkLoggerProviderUtil.addLoggerConfiguratorCondition(
+ loggerProviderBuilder, nameEquals("loggerB"), disabled());
+ SdkLoggerProvider loggerProvider = loggerProviderBuilder.build();
+
+ // Create loggerA and loggerB
+ ExtendedLogger loggerA = (ExtendedLogger) loggerProvider.get("loggerA");
+ ExtendedLogger loggerB = (ExtendedLogger) loggerProvider.get("loggerB");
+
+ // Check if logger is enabled before emitting log and avoid unnecessary computation
+ if (loggerA.isEnabled()) {
+ loggerA
+ .logRecordBuilder()
+ .setBody("hello world!")
+ .setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
+ .emit();
+ }
+ if (loggerB.isEnabled()) {
+ loggerB
+ .logRecordBuilder()
+ .setBody("hello world!")
+ .setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
+ .emit();
+ }
+
+ // loggerA is enabled, loggerB is disabled
+ assertThat(loggerA.isEnabled()).isTrue();
+ assertThat(loggerB.isEnabled()).isFalse();
+
+ // Collected data only consists of logs from loggerA. Note, loggerB's logs would be
+ // omitted from the results even if logs were emitted. The check if enabled simply avoids
+ // unnecessary computation.
+ assertThat(exporter.getFinishedLogRecordItems())
+ .allSatisfy(
+ logRecordData ->
+ assertThat(logRecordData.getInstrumentationScopeInfo().getName())
+ .isEqualTo("loggerA"));
+ }
+
+ private static final Random random = new Random();
+
+ private static String flipCoin() {
+ return random.nextBoolean() ? "heads" : "tails";
+ }
+
@Test
void extendedLogRecordBuilderUsage() {
// Setup SdkLoggerProvider
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedMetricsApiUsageTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedMetricsApiUsageTest.java
index 5ae6297a2c7..09cda254e18 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedMetricsApiUsageTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedMetricsApiUsageTest.java
@@ -5,6 +5,8 @@
package io.opentelemetry.api.incubator.metrics;
+import static io.opentelemetry.sdk.internal.ScopeConfiguratorBuilder.nameEquals;
+import static io.opentelemetry.sdk.metrics.internal.MeterConfig.disabled;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import com.google.common.collect.ImmutableList;
@@ -15,14 +17,68 @@
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
+import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.View;
+import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
+import java.util.Random;
import org.junit.jupiter.api.Test;
/** Demonstrating usage of extended Metrics API. */
class ExtendedMetricsApiUsageTest {
+ @Test
+ void meterEnabled() {
+ // Setup SdkMeterProvider
+ InMemoryMetricReader reader = InMemoryMetricReader.create();
+ SdkMeterProviderBuilder meterProviderBuilder =
+ SdkMeterProvider.builder()
+ // Default resource used for demonstration purposes
+ .setResource(Resource.getDefault())
+ // In-memory reader used for demonstration purposes
+ .registerMetricReader(reader);
+ // Disable meterB
+ SdkMeterProviderUtil.addMeterConfiguratorCondition(
+ meterProviderBuilder, nameEquals("meterB"), disabled());
+ SdkMeterProvider meterProvider = meterProviderBuilder.build();
+
+ // Create meterA and meterB, and corresponding instruments
+ Meter meterA = meterProvider.get("meterA");
+ Meter meterB = meterProvider.get("meterB");
+ ExtendedDoubleHistogram histogramA =
+ (ExtendedDoubleHistogram) meterA.histogramBuilder("histogramA").build();
+ ExtendedDoubleHistogram histogramB =
+ (ExtendedDoubleHistogram) meterB.histogramBuilder("histogramB").build();
+
+ // Check if instrument is enabled before recording measurement and avoid unnecessary computation
+ if (histogramA.isEnabled()) {
+ histogramA.record(1.0, Attributes.builder().put("result", flipCoin()).build());
+ }
+ if (histogramB.isEnabled()) {
+ histogramA.record(1.0, Attributes.builder().put("result", flipCoin()).build());
+ }
+
+ // histogramA is enabled since meterA is enabled, histogramB is disabled since meterB is
+ // disabled
+ assertThat(histogramA.isEnabled()).isTrue();
+ assertThat(histogramB.isEnabled()).isFalse();
+
+ // Collected data only consists of metrics from meterA. Note, meterB's histogramB would be
+ // omitted from the results even if values were recorded. The check if enabled simply avoids
+ // unnecessary computation.
+ assertThat(reader.collectAllMetrics())
+ .allSatisfy(
+ metric ->
+ assertThat(metric.getInstrumentationScopeInfo().getName()).isEqualTo("meterA"));
+ }
+
+ private static final Random random = new Random();
+
+ private static String flipCoin() {
+ return random.nextBoolean() ? "heads" : "tails";
+ }
+
@Test
void attributesAdvice() {
// Setup SdkMeterProvider
diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java
index 3922cba7f8b..40bf10454de 100644
--- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java
+++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java
@@ -5,9 +5,12 @@
package io.opentelemetry.api.incubator.trace;
+import static io.opentelemetry.sdk.internal.ScopeConfiguratorBuilder.nameEquals;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
+import static io.opentelemetry.sdk.trace.internal.TracerConfig.disabled;
import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.TraceFlags;
@@ -21,16 +24,73 @@
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
+import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.data.StatusData;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
+import io.opentelemetry.sdk.trace.internal.SdkTracerProviderUtil;
import java.util.HashMap;
import java.util.Map;
+import java.util.Random;
import java.util.function.BiConsumer;
import org.junit.jupiter.api.Test;
/** Demonstrating usage of extended Trace API. */
class ExtendedTraceApiUsageTest {
+ @Test
+ void tracerEnabled() {
+ // Setup SdkTracerProvider
+ InMemorySpanExporter exporter = InMemorySpanExporter.create();
+ SdkTracerProviderBuilder tracerProviderBuilder =
+ SdkTracerProvider.builder()
+ // Default resource used for demonstration purposes
+ .setResource(Resource.getDefault())
+ // In-memory exporter used for demonstration purposes
+ .addSpanProcessor(SimpleSpanProcessor.create(exporter));
+ // Disable tracerB
+ SdkTracerProviderUtil.addTracerConfiguratorCondition(
+ tracerProviderBuilder, nameEquals("tracerB"), disabled());
+ SdkTracerProvider tracerProvider = tracerProviderBuilder.build();
+
+ // Create tracerA and tracerB
+ ExtendedTracer tracerA = (ExtendedTracer) tracerProvider.get("tracerA");
+ ExtendedTracer tracerB = (ExtendedTracer) tracerProvider.get("tracerB");
+
+ // Check if tracer is enabled before recording span and avoid unnecessary computation
+ if (tracerA.isEnabled()) {
+ tracerA
+ .spanBuilder("span name")
+ .startSpan()
+ .setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
+ .end();
+ }
+ if (tracerB.isEnabled()) {
+ tracerB
+ .spanBuilder("span name")
+ .startSpan()
+ .setAllAttributes(Attributes.builder().put("result", flipCoin()).build())
+ .end();
+ }
+
+ // tracerA is enabled, tracerB is disabled
+ assertThat(tracerA.isEnabled()).isTrue();
+ assertThat(tracerB.isEnabled()).isFalse();
+
+ // Collected data only consists of spans from tracerA. Note, tracerB's spans would be
+ // omitted from the results even if spans were recorded. The check if enabled simply avoids
+ // unnecessary computation.
+ assertThat(exporter.getFinishedSpanItems())
+ .allSatisfy(
+ spanData ->
+ assertThat(spanData.getInstrumentationScopeInfo().getName()).isEqualTo("tracerA"));
+ }
+
+ private static final Random random = new Random();
+
+ private static String flipCoin() {
+ return random.nextBoolean() ? "heads" : "tails";
+ }
+
/** Demonstrates {@link ExtendedSpanBuilder#setParentFrom(ContextPropagators, Map)}. */
@Test
void setParentFrom() {
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogger.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogger.java
index 74bad693bfa..72fb9f0b356 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogger.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogger.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.api.incubator.logs.ExtendedLogger;
import io.opentelemetry.api.logs.LogRecordBuilder;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.logs.LoggerProvider;
@@ -12,13 +13,13 @@
import io.opentelemetry.sdk.logs.internal.LoggerConfig;
/** SDK implementation of {@link Logger}. */
-final class SdkLogger implements Logger {
+final class SdkLogger implements ExtendedLogger {
private static final Logger NOOP_LOGGER = LoggerProvider.noop().get("noop");
private final LoggerSharedState loggerSharedState;
private final InstrumentationScopeInfo instrumentationScopeInfo;
- private final LoggerConfig loggerConfig;
+ private final boolean loggerEnabled;
SdkLogger(
LoggerSharedState loggerSharedState,
@@ -26,12 +27,12 @@ final class SdkLogger implements Logger {
LoggerConfig loggerConfig) {
this.loggerSharedState = loggerSharedState;
this.instrumentationScopeInfo = instrumentationScopeInfo;
- this.loggerConfig = loggerConfig;
+ this.loggerEnabled = loggerConfig.isEnabled();
}
@Override
public LogRecordBuilder logRecordBuilder() {
- if (loggerConfig.isEnabled()) {
+ if (loggerEnabled) {
return new SdkLogRecordBuilder(loggerSharedState, instrumentationScopeInfo);
}
return NOOP_LOGGER.logRecordBuilder();
@@ -41,4 +42,9 @@ public LogRecordBuilder logRecordBuilder() {
InstrumentationScopeInfo getInstrumentationScopeInfo() {
return instrumentationScopeInfo;
}
+
+ @Override
+ public boolean isEnabled() {
+ return loggerEnabled;
+ }
}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LoggerConfigTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LoggerConfigTest.java
index 371098267eb..f94b97388b4 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LoggerConfigTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LoggerConfigTest.java
@@ -11,6 +11,7 @@
import static io.opentelemetry.sdk.logs.internal.LoggerConfig.enabled;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
+import io.opentelemetry.api.incubator.logs.ExtendedLogger;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.ScopeConfigurator;
@@ -59,6 +60,10 @@ void disableScopes() {
assertThat(logsByScope.get(InstrumentationScopeInfo.create("loggerB"))).isNull();
assertThat(logsByScope.get(InstrumentationScopeInfo.create("loggerC"))).hasSize(1);
});
+ // loggerA and loggerC are enabled, loggerB is disabled.
+ assertThat(((ExtendedLogger) loggerA).isEnabled()).isTrue();
+ assertThat(((ExtendedLogger) loggerB).isEnabled()).isFalse();
+ assertThat(((ExtendedLogger) loggerC).isEnabled()).isTrue();
}
@ParameterizedTest
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/InstrumentBuilder.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/InstrumentBuilder.java
index f1da522e15b..afed0778796 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/InstrumentBuilder.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/InstrumentBuilder.java
@@ -17,7 +17,6 @@
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
import java.util.Collections;
import java.util.List;
-import java.util.function.BiFunction;
import java.util.function.Consumer;
/** Helper to make implementing builders easier. */
@@ -65,12 +64,21 @@ T swapBuilder(SwapBuilder swapper) {
meterProviderSharedState, meterSharedState, name, description, unit, adviceBuilder);
}
+ @FunctionalInterface
+ interface SynchronousInstrumentConstructor {
+
+ I createInstrument(
+ InstrumentDescriptor instrumentDescriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage);
+ }
+
I buildSynchronousInstrument(
- BiFunction instrumentFactory) {
+ SynchronousInstrumentConstructor instrumentFactory) {
InstrumentDescriptor descriptor = newDescriptor();
WriteableMetricStorage storage =
meterSharedState.registerSynchronousMetricStorage(descriptor, meterProviderSharedState);
- return instrumentFactory.apply(descriptor, storage);
+ return instrumentFactory.createInstrument(descriptor, meterSharedState, storage);
}
SdkObservableInstrument buildDoubleAsynchronousInstrument(
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java
index d7aa5f47cad..5e4eb4a7ef5 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java
@@ -7,8 +7,8 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleCounter;
import io.opentelemetry.api.incubator.metrics.ExtendedDoubleCounterBuilder;
-import io.opentelemetry.api.metrics.DoubleCounter;
import io.opentelemetry.api.metrics.DoubleCounterBuilder;
import io.opentelemetry.api.metrics.ObservableDoubleCounter;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
@@ -24,14 +24,19 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-final class SdkDoubleCounter extends AbstractInstrument implements DoubleCounter {
+final class SdkDoubleCounter extends AbstractInstrument implements ExtendedDoubleCounter {
private static final Logger logger = Logger.getLogger(SdkDoubleCounter.class.getName());
private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger);
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkDoubleCounter(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkDoubleCounter(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -58,6 +63,11 @@ public void add(double increment) {
add(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkDoubleCounterBuilder implements ExtendedDoubleCounterBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java
index 1c834b18e10..8cc9d468257 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java
@@ -7,8 +7,8 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGauge;
import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder;
-import io.opentelemetry.api.metrics.DoubleGauge;
import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
import io.opentelemetry.api.metrics.LongGaugeBuilder;
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
@@ -21,12 +21,17 @@
import java.util.List;
import java.util.function.Consumer;
-final class SdkDoubleGauge extends AbstractInstrument implements DoubleGauge {
+final class SdkDoubleGauge extends AbstractInstrument implements ExtendedDoubleGauge {
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkDoubleGauge(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkDoubleGauge(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -45,6 +50,11 @@ public void set(double increment) {
set(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkDoubleGaugeBuilder implements ExtendedDoubleGaugeBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleHistogram.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleHistogram.java
index 15dd7d2f8c7..4861a631ab7 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleHistogram.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleHistogram.java
@@ -7,8 +7,8 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogram;
import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder;
-import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.context.Context;
@@ -23,14 +23,19 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-final class SdkDoubleHistogram extends AbstractInstrument implements DoubleHistogram {
+final class SdkDoubleHistogram extends AbstractInstrument implements ExtendedDoubleHistogram {
private static final Logger logger = Logger.getLogger(SdkDoubleHistogram.class.getName());
private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger);
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkDoubleHistogram(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkDoubleHistogram(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -57,6 +62,11 @@ public void record(double value) {
record(value, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkDoubleHistogramBuilder implements ExtendedDoubleHistogramBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleUpDownCounter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleUpDownCounter.java
index 57188aa6a23..da6316d6b77 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleUpDownCounter.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleUpDownCounter.java
@@ -7,6 +7,7 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleUpDownCounter;
import io.opentelemetry.api.incubator.metrics.ExtendedDoubleUpDownCounterBuilder;
import io.opentelemetry.api.metrics.DoubleUpDownCounter;
import io.opentelemetry.api.metrics.DoubleUpDownCounterBuilder;
@@ -21,12 +22,18 @@
import java.util.List;
import java.util.function.Consumer;
-final class SdkDoubleUpDownCounter extends AbstractInstrument implements DoubleUpDownCounter {
+final class SdkDoubleUpDownCounter extends AbstractInstrument
+ implements ExtendedDoubleUpDownCounter {
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkDoubleUpDownCounter(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkDoubleUpDownCounter(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -45,6 +52,11 @@ public void add(double increment) {
add(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkDoubleUpDownCounterBuilder implements ExtendedDoubleUpDownCounterBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongCounter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongCounter.java
index 3847bf716f3..91b52fee7fd 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongCounter.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongCounter.java
@@ -7,9 +7,9 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongCounter;
import io.opentelemetry.api.incubator.metrics.ExtendedLongCounterBuilder;
import io.opentelemetry.api.metrics.DoubleCounterBuilder;
-import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.LongCounterBuilder;
import io.opentelemetry.api.metrics.ObservableLongCounter;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
@@ -24,15 +24,20 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-final class SdkLongCounter extends AbstractInstrument implements LongCounter {
+final class SdkLongCounter extends AbstractInstrument implements ExtendedLongCounter {
private static final Logger logger = Logger.getLogger(SdkLongCounter.class.getName());
private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger);
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkLongCounter(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkLongCounter(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -59,6 +64,11 @@ public void add(long increment) {
add(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkLongCounterBuilder implements ExtendedLongCounterBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongGauge.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongGauge.java
index ad7db428bdf..62ab826df87 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongGauge.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongGauge.java
@@ -7,8 +7,8 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongGauge;
import io.opentelemetry.api.incubator.metrics.ExtendedLongGaugeBuilder;
-import io.opentelemetry.api.metrics.LongGauge;
import io.opentelemetry.api.metrics.LongGaugeBuilder;
import io.opentelemetry.api.metrics.ObservableLongGauge;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
@@ -21,12 +21,17 @@
import java.util.List;
import java.util.function.Consumer;
-final class SdkLongGauge extends AbstractInstrument implements LongGauge {
+final class SdkLongGauge extends AbstractInstrument implements ExtendedLongGauge {
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkLongGauge(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkLongGauge(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -45,6 +50,11 @@ public void set(long increment) {
set(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkLongGaugeBuilder implements ExtendedLongGaugeBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongHistogram.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongHistogram.java
index b2975886565..ef8ee31e707 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongHistogram.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongHistogram.java
@@ -7,8 +7,8 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongHistogram;
import io.opentelemetry.api.incubator.metrics.ExtendedLongHistogramBuilder;
-import io.opentelemetry.api.metrics.LongHistogram;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.internal.ThrottlingLogger;
@@ -24,14 +24,19 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;
-final class SdkLongHistogram extends AbstractInstrument implements LongHistogram {
+final class SdkLongHistogram extends AbstractInstrument implements ExtendedLongHistogram {
private static final Logger logger = Logger.getLogger(SdkLongHistogram.class.getName());
private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger);
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkLongHistogram(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkLongHistogram(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -58,6 +63,11 @@ public void record(long value) {
record(value, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkLongHistogramBuilder implements ExtendedLongHistogramBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongUpDownCounter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongUpDownCounter.java
index 4530f3b8405..a74ac786d1a 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongUpDownCounter.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkLongUpDownCounter.java
@@ -7,6 +7,7 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounter;
import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounterBuilder;
import io.opentelemetry.api.metrics.DoubleUpDownCounterBuilder;
import io.opentelemetry.api.metrics.LongUpDownCounter;
@@ -21,12 +22,17 @@
import java.util.List;
import java.util.function.Consumer;
-final class SdkLongUpDownCounter extends AbstractInstrument implements LongUpDownCounter {
+final class SdkLongUpDownCounter extends AbstractInstrument implements ExtendedLongUpDownCounter {
+ private final MeterSharedState meterSharedState;
private final WriteableMetricStorage storage;
- private SdkLongUpDownCounter(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
+ private SdkLongUpDownCounter(
+ InstrumentDescriptor descriptor,
+ MeterSharedState meterSharedState,
+ WriteableMetricStorage storage) {
super(descriptor);
+ this.meterSharedState = meterSharedState;
this.storage = storage;
}
@@ -45,6 +51,11 @@ public void add(long increment) {
add(increment, Attributes.empty());
}
+ @Override
+ public boolean isEnabled() {
+ return meterSharedState.isMeterEnabled() && storage.isEnabled();
+ }
+
static final class SdkLongUpDownCounterBuilder implements ExtendedLongUpDownCounterBuilder {
private final InstrumentBuilder builder;
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java
index bb76fe6701a..da57ef3506c 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java
@@ -56,7 +56,6 @@ final class SdkMeter implements Meter {
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final MeterProviderSharedState meterProviderSharedState;
private final MeterSharedState meterSharedState;
- private final MeterConfig meterConfig;
SdkMeter(
MeterProviderSharedState meterProviderSharedState,
@@ -65,8 +64,8 @@ final class SdkMeter implements Meter {
MeterConfig meterConfig) {
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.meterProviderSharedState = meterProviderSharedState;
- this.meterSharedState = MeterSharedState.create(instrumentationScopeInfo, registeredReaders);
- this.meterConfig = meterConfig;
+ this.meterSharedState =
+ MeterSharedState.create(instrumentationScopeInfo, registeredReaders, meterConfig);
}
// Visible for testing
@@ -86,14 +85,14 @@ void resetForTest() {
@Override
public LongCounterBuilder counterBuilder(String name) {
- return meterConfig.isEnabled() && checkValidInstrumentName(name)
+ return checkValidInstrumentName(name)
? new SdkLongCounter.SdkLongCounterBuilder(meterProviderSharedState, meterSharedState, name)
: NOOP_METER.counterBuilder(NOOP_INSTRUMENT_NAME);
}
@Override
public LongUpDownCounterBuilder upDownCounterBuilder(String name) {
- return meterConfig.isEnabled() && checkValidInstrumentName(name)
+ return checkValidInstrumentName(name)
? new SdkLongUpDownCounter.SdkLongUpDownCounterBuilder(
meterProviderSharedState, meterSharedState, name)
: NOOP_METER.upDownCounterBuilder(NOOP_INSTRUMENT_NAME);
@@ -101,7 +100,7 @@ public LongUpDownCounterBuilder upDownCounterBuilder(String name) {
@Override
public DoubleHistogramBuilder histogramBuilder(String name) {
- return meterConfig.isEnabled() && checkValidInstrumentName(name)
+ return checkValidInstrumentName(name)
? new SdkDoubleHistogram.SdkDoubleHistogramBuilder(
meterProviderSharedState, meterSharedState, name)
: NOOP_METER.histogramBuilder(NOOP_INSTRUMENT_NAME);
@@ -109,7 +108,7 @@ public DoubleHistogramBuilder histogramBuilder(String name) {
@Override
public DoubleGaugeBuilder gaugeBuilder(String name) {
- return meterConfig.isEnabled() && checkValidInstrumentName(name)
+ return checkValidInstrumentName(name)
? new SdkDoubleGauge.SdkDoubleGaugeBuilder(meterProviderSharedState, meterSharedState, name)
: NOOP_METER.gaugeBuilder(NOOP_INSTRUMENT_NAME);
}
@@ -119,9 +118,6 @@ public BatchCallback batchCallback(
Runnable callback,
ObservableMeasurement observableMeasurement,
ObservableMeasurement... additionalMeasurements) {
- if (!meterConfig.isEnabled()) {
- return NOOP_METER.batchCallback(callback, observableMeasurement, additionalMeasurements);
- }
Set measurements = new HashSet<>();
measurements.add(observableMeasurement);
Collections.addAll(measurements, additionalMeasurements);
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java
index 191223bfeac..c0deda9d068 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java
@@ -131,6 +131,11 @@ public void recordDouble(double value, Attributes attributes, Context context) {
}
}
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
/**
* Obtain the AggregatorHolder for recording measurements, re-reading the volatile
* this.aggregatorHolder until we access one where recordsInProgress is even. Collect sets
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/EmptyMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/EmptyMetricStorage.java
index d076178d193..faaa7087c76 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/EmptyMetricStorage.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/EmptyMetricStorage.java
@@ -39,4 +39,9 @@ public void recordLong(long value, Attributes attributes, Context context) {}
@Override
public void recordDouble(double value, Attributes attributes, Context context) {}
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
}
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterSharedState.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterSharedState.java
index 64ecefd5385..30a3a838c45 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterSharedState.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterSharedState.java
@@ -11,11 +11,13 @@
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.data.MetricData;
+import io.opentelemetry.sdk.metrics.internal.MeterConfig;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.export.RegisteredReader;
import io.opentelemetry.sdk.metrics.internal.view.RegisteredView;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -36,20 +38,25 @@ public class MeterSharedState {
private final List callbackRegistrations = new ArrayList<>();
private final Map readerStorageRegistries;
-
private final InstrumentationScopeInfo instrumentationScopeInfo;
+ private final boolean meterEnabled;
private MeterSharedState(
- InstrumentationScopeInfo instrumentationScopeInfo, List registeredReaders) {
+ InstrumentationScopeInfo instrumentationScopeInfo,
+ List registeredReaders,
+ MeterConfig meterConfig) {
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.readerStorageRegistries =
registeredReaders.stream()
.collect(toMap(Function.identity(), unused -> new MetricStorageRegistry()));
+ this.meterEnabled = meterConfig.isEnabled();
}
public static MeterSharedState create(
- InstrumentationScopeInfo instrumentationScopeInfo, List registeredReaders) {
- return new MeterSharedState(instrumentationScopeInfo, registeredReaders);
+ InstrumentationScopeInfo instrumentationScopeInfo,
+ List registeredReaders,
+ MeterConfig meterConfig) {
+ return new MeterSharedState(instrumentationScopeInfo, registeredReaders, meterConfig);
}
/**
@@ -81,11 +88,20 @@ public InstrumentationScopeInfo getInstrumentationScopeInfo() {
return instrumentationScopeInfo;
}
+ /** Returns {@code true} if the {@link MeterConfig#enabled()} of the meter is {@code true}. */
+ public boolean isMeterEnabled() {
+ return meterEnabled;
+ }
+
/** Collects all metrics. */
public List collectAll(
RegisteredReader registeredReader,
MeterProviderSharedState meterProviderSharedState,
long epochNanos) {
+ // Short circuit collection process if meter is disabled
+ if (!meterEnabled) {
+ return Collections.emptyList();
+ }
List currentRegisteredCallbacks;
synchronized (callbackLock) {
currentRegisteredCallbacks = new ArrayList<>(callbackRegistrations);
@@ -113,7 +129,7 @@ public List collectAll(
result.add(current);
}
}
- return result;
+ return Collections.unmodifiableList(result);
}
}
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MultiWritableMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MultiWritableMetricStorage.java
index 59632a9cc4a..700fee4c3fb 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MultiWritableMetricStorage.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MultiWritableMetricStorage.java
@@ -29,4 +29,14 @@ public void recordDouble(double value, Attributes attributes, Context context) {
storage.recordDouble(value, attributes, context);
}
}
+
+ @Override
+ public boolean isEnabled() {
+ for (WriteableMetricStorage storage : storages) {
+ if (storage.isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/WriteableMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/WriteableMetricStorage.java
index 77e2dd510b8..7191a63f1e0 100644
--- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/WriteableMetricStorage.java
+++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/WriteableMetricStorage.java
@@ -22,4 +22,10 @@ public interface WriteableMetricStorage {
/** Records a measurement. */
void recordDouble(double value, Attributes attributes, Context context);
+
+ /**
+ * Returns {@code true} if the storage is actively recording measurements, and {@code false}
+ * otherwise (i.e. noop / empty metric storage is installed).
+ */
+ boolean isEnabled();
}
diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/InstrumentBuilderTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/InstrumentBuilderTest.java
index a351c95d0e6..c6ef1957428 100644
--- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/InstrumentBuilderTest.java
+++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/InstrumentBuilderTest.java
@@ -8,6 +8,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import io.opentelemetry.sdk.metrics.internal.MeterConfig;
import io.opentelemetry.sdk.metrics.internal.descriptor.Advice;
import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
@@ -24,7 +25,7 @@ class InstrumentBuilderTest {
TestClock.create(), Resource.getDefault(), ExemplarFilter.alwaysOff(), 0);
static final InstrumentationScopeInfo SCOPE = InstrumentationScopeInfo.create("scope-name");
public static final MeterSharedState METER_SHARED_STATE =
- MeterSharedState.create(SCOPE, Collections.emptyList());
+ MeterSharedState.create(SCOPE, Collections.emptyList(), MeterConfig.defaultConfig());
@Test
void stringRepresentation() {
diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/MeterConfigTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/MeterConfigTest.java
index 3b78f2abd0d..aaaeaf5f85d 100644
--- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/MeterConfigTest.java
+++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/MeterConfigTest.java
@@ -11,7 +11,16 @@
import static io.opentelemetry.sdk.metrics.internal.MeterConfig.disabled;
import static io.opentelemetry.sdk.metrics.internal.MeterConfig.enabled;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
+import static java.util.stream.Collectors.groupingBy;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleCounter;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGauge;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogram;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleUpDownCounter;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongCounter;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongGauge;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongHistogram;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.ScopeConfigurator;
@@ -20,7 +29,7 @@
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -37,50 +46,136 @@ void disableScopes() {
// Disable meterB. Since meters are enabled by default, meterA and meterC are enabled.
.addMeterConfiguratorCondition(nameEquals("meterB"), disabled())
.registerMetricReader(reader)
+ // Register drop aggregation for all instruments of meterD. Instruments are disabled if
+ // their relevant MeterConfig is disabled, or if there are no resolved views which
+ // consume the measurements.
+ .registerView(
+ InstrumentSelector.builder().setMeterName("meterD").build(),
+ View.builder().setAggregation(Aggregation.drop()).build())
.build();
Meter meterA = meterProvider.get("meterA");
Meter meterB = meterProvider.get("meterB");
Meter meterC = meterProvider.get("meterC");
+ Meter meterD = meterProvider.get("meterD");
+ AtomicLong meterAInvocations = new AtomicLong();
+ AtomicLong meterBInvocations = new AtomicLong();
+ AtomicLong meterCInvocations = new AtomicLong();
+ AtomicLong meterDInvocations = new AtomicLong();
- meterA.counterBuilder("counterA").build().add(1);
- meterA.counterBuilder("asyncCounterA").buildWithCallback(observable -> observable.record(1));
- meterA.upDownCounterBuilder("upDownCounterA").build().add(1);
- meterA
- .upDownCounterBuilder("asyncUpDownCounterA")
- .buildWithCallback(observable -> observable.record(1));
- meterA.histogramBuilder("histogramA").build().record(1.0);
- meterA.gaugeBuilder("gaugeA").buildWithCallback(observable -> observable.record(1.0));
-
- meterB.counterBuilder("counterB").build().add(1);
- meterB.counterBuilder("asyncCounterB").buildWithCallback(observable -> observable.record(1));
- meterB.upDownCounterBuilder("upDownCounterB").build().add(1);
- meterB
- .upDownCounterBuilder("asyncUpDownCounterB")
- .buildWithCallback(observable -> observable.record(1));
- meterB.histogramBuilder("histogramB").build().record(1.0);
- meterB.gaugeBuilder("gaugeB").buildWithCallback(observable -> observable.record(1.0));
-
- meterC.counterBuilder("counterC").build().add(1);
- meterC.counterBuilder("asyncCounterC").buildWithCallback(observable -> observable.record(1));
- meterC.upDownCounterBuilder("upDownCounterC").build().add(1);
- meterC
- .upDownCounterBuilder("asyncUpDownCounterC")
- .buildWithCallback(observable -> observable.record(1));
- meterC.histogramBuilder("histogramC").build().record(1.0);
- meterC.gaugeBuilder("gaugeC").buildWithCallback(observable -> observable.record(1.0));
+ // Record measurements to each instrument type
+ recordToMeterInstruments(meterA, meterAInvocations);
+ recordToMeterInstruments(meterB, meterBInvocations);
+ recordToMeterInstruments(meterC, meterCInvocations);
+ recordToMeterInstruments(meterD, meterDInvocations);
// Only metrics from meterA and meterC should be seen
assertThat(reader.collectAllMetrics())
.satisfies(
metrics -> {
Map> metricsByScope =
- metrics.stream()
- .collect(Collectors.groupingBy(MetricData::getInstrumentationScopeInfo));
- assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterA"))).hasSize(6);
+ metrics.stream().collect(groupingBy(MetricData::getInstrumentationScopeInfo));
+ assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterA"))).hasSize(14);
assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterB"))).isNull();
- assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterC"))).hasSize(6);
+ assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterC"))).hasSize(14);
+ assertThat(metricsByScope.get(InstrumentationScopeInfo.create("meterD"))).isNull();
+ });
+ // Only async callbacks from meterA and meterC should be invoked
+ assertThat(meterAInvocations.get()).isPositive();
+ assertThat(meterBInvocations.get()).isZero();
+ assertThat(meterCInvocations.get()).isPositive();
+ assertThat(meterDInvocations.get()).isZero();
+ // Instruments from meterA and meterC are enabled, meterC is not enabled
+ assertMeterInstrumentsEnabled(meterA, /* expectedEnabled= */ true);
+ assertMeterInstrumentsEnabled(meterB, /* expectedEnabled= */ false);
+ assertMeterInstrumentsEnabled(meterC, /* expectedEnabled= */ true);
+ assertMeterInstrumentsEnabled(meterD, /* expectedEnabled= */ false);
+ }
+
+ private static void recordToMeterInstruments(Meter meter, AtomicLong asyncInvocationsCount) {
+ meter.counterBuilder("longCounter").build().add(1);
+ meter.counterBuilder("doubleCounter").ofDoubles().build().add(1);
+ meter
+ .counterBuilder("asyncLongCounter")
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1);
+ });
+ meter
+ .counterBuilder("asyncDoubleCounter")
+ .ofDoubles()
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1);
});
+ meter.upDownCounterBuilder("longUpDownCounter").build().add(1);
+ meter.upDownCounterBuilder("doubleUpDownCounter").ofDoubles().build().add(1);
+ meter
+ .upDownCounterBuilder("asyncLongUpDownCounter")
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1);
+ });
+ meter
+ .upDownCounterBuilder("asyncDoubleUpDownCounter")
+ .ofDoubles()
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1);
+ });
+ meter.histogramBuilder("doubleHistogram").build().record(1.0);
+ meter.histogramBuilder("longHistogram").ofLongs().build().record(1);
+ meter.gaugeBuilder("doubleGauge").build().set(1);
+ meter.gaugeBuilder("longGauge").ofLongs().build().set(1);
+ meter
+ .gaugeBuilder("asyncDoubleGauge")
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1.0);
+ });
+ meter
+ .gaugeBuilder("asyncLongGauge")
+ .ofLongs()
+ .buildWithCallback(
+ observable -> {
+ asyncInvocationsCount.incrementAndGet();
+ observable.record(1);
+ });
+ }
+
+ private static void assertMeterInstrumentsEnabled(Meter meter, boolean expectedEnabled) {
+ assertThat(
+ ((ExtendedDoubleCounter) meter.counterBuilder("doubleCounter").ofDoubles().build())
+ .isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(((ExtendedLongCounter) meter.counterBuilder("longCounter").build()).isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(
+ ((ExtendedDoubleUpDownCounter)
+ meter.upDownCounterBuilder("doubleUpDownCounter").ofDoubles().build())
+ .isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(
+ ((ExtendedLongUpDownCounter) meter.upDownCounterBuilder("longUpDownCounter").build())
+ .isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(
+ ((ExtendedDoubleHistogram) meter.histogramBuilder("doubleHistogram").build())
+ .isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(
+ ((ExtendedLongHistogram) meter.histogramBuilder("longHistogram").ofLongs().build())
+ .isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(((ExtendedDoubleGauge) meter.gaugeBuilder("doubleGauge").build()).isEnabled())
+ .isEqualTo(expectedEnabled);
+ assertThat(((ExtendedLongGauge) meter.gaugeBuilder("longGauge").ofLongs().build()).isEnabled())
+ .isEqualTo(expectedEnabled);
}
@ParameterizedTest
diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableInstrumentTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableInstrumentTest.java
index a2b9e60a60f..03e52331dc7 100644
--- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableInstrumentTest.java
+++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableInstrumentTest.java
@@ -13,6 +13,7 @@
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import io.opentelemetry.sdk.metrics.internal.MeterConfig;
import io.opentelemetry.sdk.metrics.internal.descriptor.Advice;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.CallbackRegistration;
@@ -36,7 +37,11 @@ class SdkObservableInstrumentTest {
@BeforeEach
void setup() {
meterSharedState =
- spy(MeterSharedState.create(InstrumentationScopeInfo.empty(), Collections.emptyList()));
+ spy(
+ MeterSharedState.create(
+ InstrumentationScopeInfo.empty(),
+ Collections.emptyList(),
+ MeterConfig.defaultConfig()));
callbackRegistration =
CallbackRegistration.create(
Collections.singletonList(
diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/MetricStorageRegistryTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/MetricStorageRegistryTest.java
index 8b664ad5d3e..99a26106a78 100644
--- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/MetricStorageRegistryTest.java
+++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/MetricStorageRegistryTest.java
@@ -114,5 +114,10 @@ public void recordLong(long value, Attributes attributes, Context context) {}
@Override
public void recordDouble(double value, Attributes attributes, Context context) {}
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
}
}
diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracer.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracer.java
index a0b2704fc72..cd8c7ca2471 100644
--- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracer.java
+++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracer.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.trace;
+import io.opentelemetry.api.incubator.trace.ExtendedTracer;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerProvider;
@@ -12,13 +13,13 @@
import io.opentelemetry.sdk.trace.internal.TracerConfig;
/** {@link SdkTracer} is SDK implementation of {@link Tracer}. */
-final class SdkTracer implements Tracer {
+final class SdkTracer implements ExtendedTracer {
static final String FALLBACK_SPAN_NAME = "";
private static final Tracer NOOP_TRACER = TracerProvider.noop().get("noop");
private final TracerSharedState sharedState;
private final InstrumentationScopeInfo instrumentationScopeInfo;
- private final TracerConfig tracerConfig;
+ private final boolean tracerEnabled;
SdkTracer(
TracerSharedState sharedState,
@@ -26,12 +27,12 @@ final class SdkTracer implements Tracer {
TracerConfig tracerConfig) {
this.sharedState = sharedState;
this.instrumentationScopeInfo = instrumentationScopeInfo;
- this.tracerConfig = tracerConfig;
+ this.tracerEnabled = tracerConfig.isEnabled();
}
@Override
public SpanBuilder spanBuilder(String spanName) {
- if (!tracerConfig.isEnabled()) {
+ if (!tracerEnabled) {
return NOOP_TRACER.spanBuilder(spanName);
}
if (spanName == null || spanName.trim().isEmpty()) {
@@ -49,4 +50,9 @@ public SpanBuilder spanBuilder(String spanName) {
InstrumentationScopeInfo getInstrumentationScopeInfo() {
return instrumentationScopeInfo;
}
+
+ @Override
+ public boolean isEnabled() {
+ return tracerEnabled;
+ }
}
diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/TracerConfigTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/TracerConfigTest.java
index 4df99b4c999..4421185aeea 100644
--- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/TracerConfigTest.java
+++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/TracerConfigTest.java
@@ -13,6 +13,7 @@
import static io.opentelemetry.sdk.trace.internal.TracerConfig.enabled;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.trace.ExtendedTracer;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanId;
import io.opentelemetry.api.trace.Tracer;
@@ -90,6 +91,10 @@ void disableScopes() throws InterruptedException {
.hasSpanId(grandchild.getSpanContext().getSpanId())
.hasParentSpanId(parent.getSpanContext().getSpanId())
.hasAttributes(Attributes.builder().put("c", "1").build()));
+ // tracerA and tracerC are enabled, tracerB is disabled.
+ assertThat(((ExtendedTracer) tracerA).isEnabled()).isTrue();
+ assertThat(((ExtendedTracer) tracerB).isEnabled()).isFalse();
+ assertThat(((ExtendedTracer) tracerA).isEnabled()).isTrue();
}
@ParameterizedTest