From f208ba72b7ae333236efd677165834902ffd49f7 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Mon, 11 Oct 2021 19:52:50 +0900 Subject: [PATCH] Update to OTel 1.7 (#4340) * Update to OTel 1.7 * Fix metrics tests --- dependencyManagement/build.gradle.kts | 6 +- .../http/HttpClientMetricsTest.java | 93 +++++---- .../http/HttpServerMetricsTest.java | 179 ++++++++++-------- .../awslambda/v1_0/LambdaUtils.java | 12 +- .../oshi/AbstractMetricsTest.java | 111 ++--------- .../oshi/ProcessMetricsTest.java | 32 ++-- .../oshi/SystemMetricsTest.java | 54 +++--- .../tooling/OpenTelemetryInstaller.java | 14 +- .../exporter/AgentTestingExporterFactory.java | 2 +- .../AgentTestingMetricsCustomizer.java | 24 +++ ...ava => AgentTestingTracingCustomizer.java} | 14 +- 11 files changed, 269 insertions(+), 272 deletions(-) create mode 100644 testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingMetricsCustomizer.java rename testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/{AgentTestingSdkCustomizer.java => AgentTestingTracingCustomizer.java} (56%) diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 364e79b475..8bd6df3a88 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -13,8 +13,8 @@ rootProject.extra["versions"] = dependencyVersions // IMPORTANT when updating otelVersion, make sure that grpcVersion below is >= the grpc version // used by that otel version -val otelVersion = "1.6.0" -val grpcVersion = "1.40.1" +val otelVersion = "1.7.0" +val grpcVersion = "1.41.0" rootProject.extra["otelVersion"] = otelVersion // Need both BOM and -all @@ -107,7 +107,7 @@ val DEPENDENCIES = listOf( "commons-validator:commons-validator:1.7", "info.solidsoft.spock:spock-global-unroll:0.5.1", "io.netty:netty:3.10.6.Final", - "org.assertj:assertj-core:3.19.0", + "org.assertj:assertj-core:3.21.0", "org.awaitility:awaitility:4.1.0", "org.checkerframework:checker-qual:3.14.0", "org.codehaus.groovy:groovy-all:${groovyVersion}", diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetricsTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetricsTest.java index d31bdd9c06..f1c66e9119 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetricsTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetricsTest.java @@ -7,12 +7,14 @@ package io.opentelemetry.instrumentation.api.instrumenter.http; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; import static io.opentelemetry.sdk.testing.assertj.metrics.MetricAssertions.assertThat; +import static org.awaitility.Awaitility.await; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.RequestListener; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.testing.InMemoryMetricReader; import java.util.Collection; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -21,7 +23,9 @@ class HttpClientMetricsTest { @Test void collectsMetrics() { - SdkMeterProvider meterProvider = SdkMeterProvider.builder().build(); + InMemoryMetricReader metricReader = new InMemoryMetricReader(); + SdkMeterProvider meterProvider = + SdkMeterProvider.builder().registerMetricReader(metricReader).build(); RequestListener listener = HttpClientMetrics.get().create(meterProvider.get("test")); @@ -44,49 +48,68 @@ class HttpClientMetricsTest { Context context1 = listener.start(Context.current(), requestAttributes, nanos(100)); - Collection metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).isEmpty(); + // TODO(anuraaga): Remove await from this file after 1.8.0 hopefully fixes + // https://github.com/open-telemetry/opentelemetry-java/issues/3725 + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).isEmpty(); + }); Context context2 = listener.start(Context.current(), requestAttributes, nanos(150)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).isEmpty(); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).isEmpty(); + }); listener.end(context1, responseAttributes, nanos(250)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(1); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.client.duration") - .hasDoubleHistogram() - .points() - .satisfiesExactly( - point -> - assertThat(point) - .hasSum(150 /* millis */) - .attributes() - .containsOnly( - attributeEntry("http.host", "host"), - attributeEntry("http.method", "GET"), - attributeEntry("http.scheme", "https"), - attributeEntry("net.host.name", "localhost"), - attributeEntry("net.host.port", 1234L)))); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(1); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.client.duration") + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .hasSum(150 /* millis */) + .attributes() + .containsOnly( + attributeEntry("http.host", "host"), + attributeEntry("http.method", "GET"), + attributeEntry("http.scheme", "https"), + attributeEntry("net.host.name", "localhost"), + attributeEntry("net.host.port", 1234L)))); + }); listener.end(context2, responseAttributes, nanos(300)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(1); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.client.duration") - .hasDoubleHistogram() - .points() - .satisfiesExactly(point -> assertThat(point).hasSum(300 /* millis */))); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(1); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.client.duration") + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> assertThat(point).hasSum(300 /* millis */))); + }); } private static long nanos(int millis) { diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerMetricsTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerMetricsTest.java index 895ad85fbc..b12d4f5476 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerMetricsTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerMetricsTest.java @@ -7,12 +7,14 @@ package io.opentelemetry.instrumentation.api.instrumenter.http; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; import static io.opentelemetry.sdk.testing.assertj.metrics.MetricAssertions.assertThat; +import static org.awaitility.Awaitility.await; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.RequestListener; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.testing.InMemoryMetricReader; import java.util.Collection; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -21,7 +23,9 @@ class HttpServerMetricsTest { @Test void collectsMetrics() { - SdkMeterProvider meterProvider = SdkMeterProvider.builder().build(); + InMemoryMetricReader metricReader = new InMemoryMetricReader(); + SdkMeterProvider meterProvider = + SdkMeterProvider.builder().registerMetricReader(metricReader).build(); RequestListener listener = HttpServerMetrics.get().create(meterProvider.get("test")); @@ -44,92 +48,111 @@ class HttpServerMetricsTest { Context context1 = listener.start(Context.current(), requestAttributes, nanos(100)); - Collection metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(1); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.active_requests") - .hasDescription( - "The number of concurrent HTTP requests that are currently in-flight") - .hasUnit("requests") - .hasLongSum() - .points() - .satisfiesExactly( - point -> - assertThat(point) - .hasValue(1) - .attributes() - .containsOnly( - attributeEntry("http.host", "host"), - attributeEntry("http.method", "GET"), - attributeEntry("http.scheme", "https")))); + // TODO(anuraaga): Remove await from this file after 1.8.0 hopefully fixes + // https://github.com/open-telemetry/opentelemetry-java/issues/3725 + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(1); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.active_requests") + .hasDescription( + "The number of concurrent HTTP requests that are currently in-flight") + .hasUnit("requests") + .hasLongSum() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .hasValue(1) + .attributes() + .containsOnly( + attributeEntry("http.host", "host"), + attributeEntry("http.method", "GET"), + attributeEntry("http.scheme", "https")))); + }); Context context2 = listener.start(Context.current(), requestAttributes, nanos(150)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(1); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.active_requests") - .hasLongSum() - .points() - .satisfiesExactly(point -> assertThat(point).hasValue(2))); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(1); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.active_requests") + .hasLongSum() + .points() + .satisfiesExactly(point -> assertThat(point).hasValue(2))); + }); listener.end(context1, responseAttributes, nanos(250)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(2); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.active_requests") - .hasLongSum() - .points() - .satisfiesExactly(point -> assertThat(point).hasValue(1))); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.duration") - .hasDoubleHistogram() - .points() - .satisfiesExactly( - point -> - assertThat(point) - .hasSum(150 /* millis */) - .attributes() - .containsOnly( - attributeEntry("http.host", "host"), - attributeEntry("http.method", "GET"), - attributeEntry("http.scheme", "https"), - attributeEntry("net.host.name", "localhost"), - attributeEntry("net.host.port", 1234L)))); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(2); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.active_requests") + .hasLongSum() + .points() + .satisfiesExactly(point -> assertThat(point).hasValue(1))); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.duration") + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> + assertThat(point) + .hasSum(150 /* millis */) + .attributes() + .containsOnly( + attributeEntry("http.host", "host"), + attributeEntry("http.method", "GET"), + attributeEntry("http.scheme", "https"), + attributeEntry("net.host.name", "localhost"), + attributeEntry("net.host.port", 1234L)))); + }); listener.end(context2, responseAttributes, nanos(300)); - metrics = meterProvider.collectAllMetrics(); - assertThat(metrics).hasSize(2); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.active_requests") - .hasLongSum() - .points() - .satisfiesExactly(point -> assertThat(point).hasValue(0))); - assertThat(metrics) - .anySatisfy( - metric -> - assertThat(metric) - .hasName("http.server.duration") - .hasDoubleHistogram() - .points() - .satisfiesExactly(point -> assertThat(point).hasSum(300 /* millis */))); + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); + assertThat(metrics).hasSize(2); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.active_requests") + .hasLongSum() + .points() + .satisfiesExactly(point -> assertThat(point).hasValue(0))); + assertThat(metrics) + .anySatisfy( + metric -> + assertThat(metric) + .hasName("http.server.duration") + .hasDoubleHistogram() + .points() + .satisfiesExactly( + point -> assertThat(point).hasSum(300 /* millis */))); + }); } private static long nanos(int millis) { diff --git a/instrumentation/aws-lambda-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambda/v1_0/LambdaUtils.java b/instrumentation/aws-lambda-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambda/v1_0/LambdaUtils.java index d1b9fe2962..3eeb2630fc 100644 --- a/instrumentation/aws-lambda-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambda/v1_0/LambdaUtils.java +++ b/instrumentation/aws-lambda-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambda/v1_0/LambdaUtils.java @@ -5,9 +5,11 @@ package io.opentelemetry.instrumentation.awslambda.v1_0; +import io.opentelemetry.api.metrics.GlobalMeterProvider; +import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -15,7 +17,13 @@ final class LambdaUtils { static void forceFlush(OpenTelemetrySdk openTelemetrySdk, long flushTimeout, TimeUnit unit) { CompletableResultCode traceFlush = openTelemetrySdk.getSdkTracerProvider().forceFlush(); - CompletableResultCode metricsFlush = IntervalMetricReader.forceFlushGlobal(); + MeterProvider meterProvider = GlobalMeterProvider.get(); + final CompletableResultCode metricsFlush; + if (meterProvider instanceof SdkMeterProvider) { + metricsFlush = ((SdkMeterProvider) meterProvider).forceFlush(); + } else { + metricsFlush = CompletableResultCode.ofSuccess(); + } CompletableResultCode.ofAll(Arrays.asList(traceFlush, metricsFlush)).join(flushTimeout, unit); } diff --git a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/AbstractMetricsTest.java b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/AbstractMetricsTest.java index 63def6ff09..6a2135f2f6 100644 --- a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/AbstractMetricsTest.java +++ b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/AbstractMetricsTest.java @@ -6,112 +6,41 @@ package io.opentelemetry.instrumentation.oshi; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; -import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.data.DoublePointData; -import io.opentelemetry.sdk.metrics.data.DoubleSummaryPointData; -import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; -import io.opentelemetry.sdk.metrics.data.MetricDataType; -import io.opentelemetry.sdk.metrics.data.PointData; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; -import io.opentelemetry.sdk.metrics.export.MetricExporter; -import java.util.ArrayList; +import io.opentelemetry.sdk.metrics.testing.InMemoryMetricReader; +import io.opentelemetry.sdk.testing.assertj.metrics.MetricAssertions; +import io.opentelemetry.sdk.testing.assertj.metrics.MetricDataAssert; import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.Assertions; +import java.util.function.Consumer; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; class AbstractMetricsTest { - TestMetricExporter testMetricExporter; static SdkMeterProvider meterProvider; + static InMemoryMetricReader metricReader; @BeforeAll static void initializeOpenTelemetry() { - meterProvider = SdkMeterProvider.builder().buildAndRegisterGlobal(); + metricReader = new InMemoryMetricReader(); + meterProvider = + SdkMeterProvider.builder().registerMetricReader(metricReader).buildAndRegisterGlobal(); } - @BeforeEach - void beforeEach() { - testMetricExporter = new TestMetricExporter(); - } + protected void waitAndAssertMetrics(Consumer... assertions) { + await() + .untilAsserted( + () -> { + Collection metrics = metricReader.collectAllMetrics(); - IntervalMetricReader createIntervalMetricReader() { - return IntervalMetricReader.builder() - .setExportIntervalMillis(100) - .setMetricExporter(testMetricExporter) - .setMetricProducers(Collections.singletonList(meterProvider)) - .buildAndStart(); - } + assertThat(metrics).isNotEmpty(); - public void verify( - String metricName, String unit, MetricDataType type, boolean checkNonZeroValue) { - List metricDataList = testMetricExporter.metricDataList; - for (MetricData metricData : metricDataList) { - if (metricData.getName().equals(metricName)) { - assertThat(metricData.getDescription()).isNotEmpty(); - assertThat(metricData.getUnit()).isEqualTo(unit); - List points = new ArrayList<>(); - points.addAll(metricData.getDoubleGaugeData().getPoints()); - points.addAll(metricData.getDoubleSumData().getPoints()); - points.addAll(metricData.getDoubleSummaryData().getPoints()); - points.addAll(metricData.getLongGaugeData().getPoints()); - points.addAll(metricData.getLongSumData().getPoints()); - - assertThat(points).isNotEmpty(); - assertThat(metricData.getType()).isEqualTo(type); - if (checkNonZeroValue) { - for (PointData point : points) { - if (point instanceof LongPointData) { - LongPointData longPoint = (LongPointData) point; - assertThat(longPoint.getValue()).isGreaterThan(0); - } else if (point instanceof DoublePointData) { - DoublePointData doublePoint = (DoublePointData) point; - assertThat(doublePoint.getValue()).isGreaterThan(0.0); - } else if (point instanceof DoubleSummaryPointData) { - DoubleSummaryPointData summaryPoint = (DoubleSummaryPointData) point; - assertThat(summaryPoint.getSum()).isGreaterThan(0.0); - } else { - Assertions.fail("unexpected type " + metricData.getType()); - } - } - } - return; - } - } - Assertions.fail("No metric for " + metricName); - } - - static class TestMetricExporter implements MetricExporter { - private final List metricDataList = new CopyOnWriteArrayList<>(); - private final CountDownLatch latch = new CountDownLatch(1); - - @Override - public CompletableResultCode export(Collection collection) { - metricDataList.addAll(collection); - latch.countDown(); - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode flush() { - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode shutdown() { - return CompletableResultCode.ofSuccess(); - } - - public void waitForData() throws InterruptedException { - latch.await(20, TimeUnit.SECONDS); - } + for (Consumer assertion : assertions) { + assertThat(metrics) + .anySatisfy(metric -> assertion.accept(MetricAssertions.assertThat(metric))); + } + }); } } diff --git a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/ProcessMetricsTest.java b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/ProcessMetricsTest.java index 57b6aeeea9..62517d0b9a 100644 --- a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/ProcessMetricsTest.java +++ b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/ProcessMetricsTest.java @@ -5,26 +5,30 @@ package io.opentelemetry.instrumentation.oshi; -import io.opentelemetry.sdk.metrics.data.MetricDataType; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; +import static io.opentelemetry.sdk.testing.assertj.metrics.MetricAssertions.assertThat; + import org.junit.jupiter.api.Test; public class ProcessMetricsTest extends AbstractMetricsTest { @Test - public void test() throws Exception { + public void test() { ProcessMetrics.registerObservers(); - IntervalMetricReader intervalMetricReader = createIntervalMetricReader(); - testMetricExporter.waitForData(); - intervalMetricReader.shutdown(); - - verify( - "runtime.java.memory", "bytes", MetricDataType.LONG_GAUGE, /* checkNonZeroValue= */ true); - verify( - "runtime.java.cpu_time", - "seconds", - MetricDataType.DOUBLE_GAUGE, - /* checkNonZeroValue= */ true); + waitAndAssertMetrics( + metric -> + metric + .hasName("runtime.java.memory") + .hasUnit("bytes") + .hasLongGauge() + .points() + .anySatisfy(point -> assertThat(point.getValue()).isPositive()), + metric -> + metric + .hasName("runtime.java.cpu_time") + .hasUnit("seconds") + .hasDoubleGauge() + .points() + .anySatisfy(point -> assertThat(point.getValue()).isPositive())); } } diff --git a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/SystemMetricsTest.java b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/SystemMetricsTest.java index 9de527c41b..4196aedddc 100644 --- a/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/SystemMetricsTest.java +++ b/instrumentation/oshi/library/src/test/java/io/opentelemetry/instrumentation/oshi/SystemMetricsTest.java @@ -5,44 +5,34 @@ package io.opentelemetry.instrumentation.oshi; -import io.opentelemetry.sdk.metrics.data.MetricDataType; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; +import static io.opentelemetry.sdk.testing.assertj.metrics.MetricAssertions.assertThat; + import org.junit.jupiter.api.Test; public class SystemMetricsTest extends AbstractMetricsTest { @Test - public void test() throws Exception { + public void test() { SystemMetrics.registerObservers(); - IntervalMetricReader intervalMetricReader = createIntervalMetricReader(); - testMetricExporter.waitForData(); - intervalMetricReader.shutdown(); - - verify("system.memory.usage", "By", MetricDataType.LONG_GAUGE, /* checkNonZeroValue= */ true); - verify( - "system.memory.utilization", - "1", - MetricDataType.DOUBLE_GAUGE, - /* checkNonZeroValue= */ true); - - verify("system.network.io", "By", MetricDataType.LONG_GAUGE, /* checkNonZeroValue= */ false); - verify( - "system.network.packets", - "packets", - MetricDataType.LONG_GAUGE, - /* checkNonZeroValue= */ false); - verify( - "system.network.errors", - "errors", - MetricDataType.LONG_GAUGE, - /* checkNonZeroValue= */ false); - - verify("system.disk.io", "By", MetricDataType.LONG_GAUGE, /* checkNonZeroValue= */ false); - verify( - "system.disk.operations", - "operations", - MetricDataType.LONG_GAUGE, - /* checkNonZeroValue= */ false); + waitAndAssertMetrics( + metric -> + metric + .hasName("system.memory.usage") + .hasUnit("By") + .hasLongGauge() + .points() + .anySatisfy(point -> assertThat(point.getValue()).isPositive()), + metric -> + metric + .hasName("system.memory.utilization") + .hasUnit("1") + .hasDoubleGauge() + .points() + .anySatisfy(point -> assertThat(point.getValue()).isPositive()), + metric -> metric.hasName("system.network.io").hasUnit("By").hasLongGauge(), + metric -> metric.hasName("system.network.packets").hasUnit("packets").hasLongGauge(), + metric -> metric.hasName("system.network.errors").hasUnit("errors").hasLongGauge(), + metric -> metric.hasName("system.disk.operations").hasUnit("operations").hasLongGauge()); } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java index 9527dcbd6b..b316b94ab9 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/OpenTelemetryInstaller.java @@ -7,6 +7,8 @@ package io.opentelemetry.javaagent.tooling; import com.google.auto.service.AutoService; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.metrics.GlobalMeterProvider; +import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.extension.noopapi.NoopOpenTelemetry; import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.javaagent.extension.AgentListener; @@ -15,7 +17,7 @@ import io.opentelemetry.javaagent.tooling.config.ConfigPropertiesAdapter; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.OpenTelemetrySdkAutoConfiguration; import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,8 +53,14 @@ public class OpenTelemetryInstaller implements AgentListener { OpenTelemetrySdkAccess.internalSetForceFlush( (timeout, unit) -> { CompletableResultCode traceResult = sdk.getSdkTracerProvider().forceFlush(); - CompletableResultCode flushResult = IntervalMetricReader.forceFlushGlobal(); - CompletableResultCode.ofAll(Arrays.asList(traceResult, flushResult)) + MeterProvider meterProvider = GlobalMeterProvider.get(); + final CompletableResultCode metricsResult; + if (meterProvider instanceof SdkMeterProvider) { + metricsResult = ((SdkMeterProvider) meterProvider).forceFlush(); + } else { + metricsResult = CompletableResultCode.ofSuccess(); + } + CompletableResultCode.ofAll(Arrays.asList(traceResult, metricsResult)) .join(timeout, unit); }); } diff --git a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingExporterFactory.java b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingExporterFactory.java index 2b25518b69..a2ca32a837 100644 --- a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingExporterFactory.java +++ b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingExporterFactory.java @@ -26,6 +26,6 @@ public class AgentTestingExporterFactory { } public static boolean forceFlushCalled() { - return AgentTestingSdkCustomizer.spanProcessor.forceFlushCalled; + return AgentTestingTracingCustomizer.spanProcessor.forceFlushCalled; } } diff --git a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingMetricsCustomizer.java b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingMetricsCustomizer.java new file mode 100644 index 0000000000..7454398ddf --- /dev/null +++ b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingMetricsCustomizer.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.testing.exporter; + +import com.google.auto.service.AutoService; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.metrics.SdkMeterProviderConfigurer; +import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import java.time.Duration; + +@AutoService(SdkMeterProviderConfigurer.class) +public class AgentTestingMetricsCustomizer implements SdkMeterProviderConfigurer { + @Override + public void configure( + SdkMeterProviderBuilder sdkMeterProviderBuilder, ConfigProperties configProperties) { + sdkMeterProviderBuilder.registerMetricReader( + PeriodicMetricReader.create( + AgentTestingExporterFactory.metricExporter, Duration.ofMillis(100))); + } +} diff --git a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingSdkCustomizer.java b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingTracingCustomizer.java similarity index 56% rename from testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingSdkCustomizer.java rename to testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingTracingCustomizer.java index 0c935d2e5f..9401f7bfa0 100644 --- a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingSdkCustomizer.java +++ b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingTracingCustomizer.java @@ -6,17 +6,13 @@ package io.opentelemetry.javaagent.testing.exporter; import com.google.auto.service.AutoService; -import io.opentelemetry.api.metrics.GlobalMeterProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.traces.SdkTracerProviderConfigurer; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.export.IntervalMetricReader; import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import java.util.Collections; @AutoService(SdkTracerProviderConfigurer.class) -public class AgentTestingSdkCustomizer implements SdkTracerProviderConfigurer { +public class AgentTestingTracingCustomizer implements SdkTracerProviderConfigurer { static final AgentTestingSpanProcessor spanProcessor = new AgentTestingSpanProcessor( @@ -29,13 +25,5 @@ public class AgentTestingSdkCustomizer implements SdkTracerProviderConfigurer { @Override public void configure(SdkTracerProviderBuilder tracerProviderBuilder, ConfigProperties config) { tracerProviderBuilder.addSpanProcessor(spanProcessor); - - // Until metrics story settles down there is no SPI for it, we rely on the fact that metrics is - // already set up when tracing configuration begins. - IntervalMetricReader.builder() - .setExportIntervalMillis(100) - .setMetricExporter(AgentTestingExporterFactory.metricExporter) - .setMetricProducers(Collections.singleton((SdkMeterProvider) GlobalMeterProvider.get())) - .buildAndStart(); } }