From a38c8be3f53d387c513b52f64f9247606d866375 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Tue, 7 Nov 2023 13:19:37 -0600 Subject: [PATCH 1/2] Add log support to junit extensions --- .../opentelemetry-sdk-testing.txt | 9 ++++- .../sdk/testing/junit4/OpenTelemetryRule.java | 39 ++++++++++++++++++- .../junit5/OpenTelemetryExtension.java | 39 ++++++++++++++++++- .../testing/junit4/OpenTelemetryRuleTest.java | 34 ++++++++++++++++ .../junit5/OpenTelemetryExtensionTest.java | 33 ++++++++++++++++ 5 files changed, 149 insertions(+), 5 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt index df26146497b..e8f3d45d4f7 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt @@ -1,2 +1,9 @@ Comparing source compatibility of against -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) void clearLogRecords() + +++ NEW METHOD: PUBLIC(+) java.util.List getLogRecords() +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) void clearLogRecords() + +++ NEW METHOD: PUBLIC(+) java.util.List getLogRecords() diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java index b0b15782a12..a5e7c6485df 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java @@ -10,10 +10,14 @@ import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil; +import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter; import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.SdkTracerProvider; @@ -71,27 +75,38 @@ public static OpenTelemetryRule create() { SdkMeterProvider meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); + InMemoryLogRecordExporter logRecordExporter = InMemoryLogRecordExporter.create(); + + SdkLoggerProvider loggerProvider = + SdkLoggerProvider.builder() + .addLogRecordProcessor(SimpleLogRecordProcessor.create(logRecordExporter)) + .build(); + OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder() .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .setTracerProvider(tracerProvider) .setMeterProvider(meterProvider) + .setLoggerProvider(loggerProvider) .build(); - return new OpenTelemetryRule(openTelemetry, spanExporter, metricReader); + return new OpenTelemetryRule(openTelemetry, spanExporter, metricReader, logRecordExporter); } private final OpenTelemetrySdk openTelemetry; private final InMemorySpanExporter spanExporter; private final InMemoryMetricReader metricReader; + private final InMemoryLogRecordExporter logRecordExporter; private OpenTelemetryRule( OpenTelemetrySdk openTelemetry, InMemorySpanExporter spanExporter, - InMemoryMetricReader metricReader) { + InMemoryMetricReader metricReader, + InMemoryLogRecordExporter logRecordExporter) { this.openTelemetry = openTelemetry; this.spanExporter = spanExporter; this.metricReader = metricReader; + this.logRecordExporter = logRecordExporter; } /** Returns the {@link OpenTelemetrySdk} created by this extension. */ @@ -113,6 +128,15 @@ public List getMetrics() { return new ArrayList<>(metricReader.collectAllMetrics()); } + /** + * Returns all the exported {@link LogRecordData} so far. + * + * @since 1.33.0 + */ + public List getLogRecords() { + return new ArrayList<>(logRecordExporter.getFinishedLogRecordItems()); + } + /** * Clears the collected exported {@link SpanData}. Consider making your test smaller instead of * manually clearing state using this method. @@ -130,12 +154,23 @@ public void clearMetrics() { SdkMeterProviderUtil.resetForTest(openTelemetry.getSdkMeterProvider()); } + /** + * Clears the collected exported {@link LogRecordData}. Consider making your test smaller instead + * of manually clearing state using this method. + * + * @since 1.33.0 + */ + public void clearLogRecords() { + logRecordExporter.reset(); + } + @Override protected void before() { GlobalOpenTelemetry.resetForTest(); GlobalOpenTelemetry.set(openTelemetry); clearSpans(); clearMetrics(); + clearLogRecords(); } @Override diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java index 35ed9f4a637..012af1b345c 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java @@ -12,11 +12,15 @@ import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil; import io.opentelemetry.sdk.testing.assertj.TracesAssert; +import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter; import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.SdkTracerProvider; @@ -73,27 +77,38 @@ public static OpenTelemetryExtension create() { SdkMeterProvider meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); + InMemoryLogRecordExporter logRecordExporter = InMemoryLogRecordExporter.create(); + + SdkLoggerProvider loggerProvider = + SdkLoggerProvider.builder() + .addLogRecordProcessor(SimpleLogRecordProcessor.create(logRecordExporter)) + .build(); + OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder() .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .setTracerProvider(tracerProvider) .setMeterProvider(meterProvider) + .setLoggerProvider(loggerProvider) .build(); - return new OpenTelemetryExtension(openTelemetry, spanExporter, metricReader); + return new OpenTelemetryExtension(openTelemetry, spanExporter, metricReader, logRecordExporter); } private final OpenTelemetrySdk openTelemetry; private final InMemorySpanExporter spanExporter; private final InMemoryMetricReader metricReader; + private final InMemoryLogRecordExporter logRecordExporter; private OpenTelemetryExtension( OpenTelemetrySdk openTelemetry, InMemorySpanExporter spanExporter, - InMemoryMetricReader metricReader) { + InMemoryMetricReader metricReader, + InMemoryLogRecordExporter logRecordExporter) { this.openTelemetry = openTelemetry; this.spanExporter = spanExporter; this.metricReader = metricReader; + this.logRecordExporter = logRecordExporter; } /** Returns the {@link OpenTelemetrySdk} created by this extension. */ @@ -115,6 +130,15 @@ public List getMetrics() { return new ArrayList<>(metricReader.collectAllMetrics()); } + /** + * Returns all the exported {@link LogRecordData} so far. + * + * @since 1.33.0 + */ + public List getLogRecords() { + return new ArrayList<>(logRecordExporter.getFinishedLogRecordItems()); + } + /** * Returns a {@link TracesAssert} for asserting on the currently exported traces. This method * requires AssertJ to be on the classpath. @@ -140,10 +164,21 @@ public void clearMetrics() { SdkMeterProviderUtil.resetForTest(openTelemetry.getSdkMeterProvider()); } + /** + * Clears the collected exported {@link LogRecordData}. Consider making your test smaller instead + * of manually clearing state using this method. + * + * @since 1.33.0 + */ + public void clearLogRecords() { + logRecordExporter.reset(); + } + @Override public void beforeEach(ExtensionContext context) { clearSpans(); clearMetrics(); + clearLogRecords(); } @Override diff --git a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRuleTest.java b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRuleTest.java index a9450c471fb..b8a14c5975d 100644 --- a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRuleTest.java +++ b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRuleTest.java @@ -7,6 +7,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.api.logs.Logger; import io.opentelemetry.api.metrics.LongCounter; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.trace.Tracer; @@ -21,11 +22,13 @@ public class OpenTelemetryRuleTest { private Tracer tracer; private Meter meter; + private Logger logger; @Before public void setup() { tracer = otelTesting.getOpenTelemetry().getTracer("test"); meter = otelTesting.getOpenTelemetry().getMeter("test"); + logger = otelTesting.getOpenTelemetry().getLogsBridge().get("test"); } @Test @@ -83,4 +86,35 @@ public void getMetricsAgain() { .hasLongSumSatisfying( sum -> sum.hasPointsSatisfying(point -> point.hasValue(1)))); } + + @Test + public void getLogRecords() { + logger.logRecordBuilder().setBody("body").emit(); + + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + // Logs cleared between tests, not when retrieving + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + } + + // We have two tests to verify logs get cleared up between tests. + @Test + public void getLogRecordsAgain() { + logger.logRecordBuilder().setBody("body").emit(); + + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + // Logs cleared between tests, not when retrieving + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + } } diff --git a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtensionTest.java b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtensionTest.java index 3f658bf0724..f2e7257b2bd 100644 --- a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtensionTest.java +++ b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtensionTest.java @@ -10,6 +10,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.logs.Logger; import io.opentelemetry.api.metrics.LongCounter; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.trace.Span; @@ -30,6 +31,7 @@ class OpenTelemetryExtensionTest { private final Tracer tracer = otelTesting.getOpenTelemetry().getTracer("test"); private final Meter meter = otelTesting.getOpenTelemetry().getMeter("test"); + private final Logger logger = otelTesting.getOpenTelemetry().getLogsBridge().get("test"); @Test public void getSpans() { @@ -175,6 +177,37 @@ void getMetricsAgain() { sum -> sum.hasPointsSatisfying(point -> point.hasValue(1)))); } + @Test + public void getLogRecords() { + logger.logRecordBuilder().setBody("body").emit(); + + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + // Logs cleared between tests, not when retrieving + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + } + + // We have two tests to verify spans get cleared up between tests. + @Test + public void getLogRecordsAgain() { + logger.logRecordBuilder().setBody("body").emit(); + + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + // Logs cleared between tests, not when retrieving + assertThat(otelTesting.getLogRecords()) + .singleElement() + .satisfies( + logRecordData -> assertThat(logRecordData.getBody().asString()).isEqualTo("body")); + } + @Test void afterAll() { // Use a different instance of OpenTelemetryExtension to avoid interfering with other tests From 3aa7d7f044c220fe5aad4bdf2a836e036850dcf5 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Thu, 9 Nov 2023 08:56:07 -0600 Subject: [PATCH 2/2] Update since annotation to 1.32.0 --- .../opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java | 4 ++-- .../sdk/testing/junit5/OpenTelemetryExtension.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java index a5e7c6485df..7cf3a873cba 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit4/OpenTelemetryRule.java @@ -131,7 +131,7 @@ public List getMetrics() { /** * Returns all the exported {@link LogRecordData} so far. * - * @since 1.33.0 + * @since 1.32.0 */ public List getLogRecords() { return new ArrayList<>(logRecordExporter.getFinishedLogRecordItems()); @@ -158,7 +158,7 @@ public void clearMetrics() { * Clears the collected exported {@link LogRecordData}. Consider making your test smaller instead * of manually clearing state using this method. * - * @since 1.33.0 + * @since 1.32.0 */ public void clearLogRecords() { logRecordExporter.reset(); diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java index 012af1b345c..3aedad968c7 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/junit5/OpenTelemetryExtension.java @@ -133,7 +133,7 @@ public List getMetrics() { /** * Returns all the exported {@link LogRecordData} so far. * - * @since 1.33.0 + * @since 1.32.0 */ public List getLogRecords() { return new ArrayList<>(logRecordExporter.getFinishedLogRecordItems()); @@ -168,7 +168,7 @@ public void clearMetrics() { * Clears the collected exported {@link LogRecordData}. Consider making your test smaller instead * of manually clearing state using this method. * - * @since 1.33.0 + * @since 1.32.0 */ public void clearLogRecords() { logRecordExporter.reset();