From 74297ce45abb30fbfb79282fa8d661b85d35084f Mon Sep 17 00:00:00 2001 From: jack-berg <34418638+jack-berg@users.noreply.github.com> Date: Mon, 28 Nov 2022 10:14:44 -0600 Subject: [PATCH] Implement logging exporter providers (#4950) --- exporters/logging/build.gradle.kts | 2 ++ .../LoggingLogRecordExporterProvider.java | 29 +++++++++++++++++++ .../LoggingMetricExporterProvider.java | 29 +++++++++++++++++++ .../internal/LoggingSpanExporterProvider.java | 29 +++++++++++++++++++ ...logs.ConfigurableLogRecordExporterProvider | 1 + ...metrics.ConfigurableMetricExporterProvider | 1 + ...pi.traces.ConfigurableSpanExporterProvider | 1 + sdk-extensions/autoconfigure/build.gradle.kts | 1 - .../LogRecordExporterConfiguration.java | 22 +++++++++----- .../MetricExporterConfiguration.java | 29 +++++++++++-------- .../SpanExporterConfiguration.java | 23 ++++++++++----- .../sdk/autoconfigure/NotOnClasspathTest.java | 12 ++++---- 12 files changed, 146 insertions(+), 33 deletions(-) create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java create mode 100644 exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider create mode 100644 exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider diff --git a/exporters/logging/build.gradle.kts b/exporters/logging/build.gradle.kts index 8107ed13a9a..ca1adf08d1a 100644 --- a/exporters/logging/build.gradle.kts +++ b/exporters/logging/build.gradle.kts @@ -13,6 +13,8 @@ dependencies { api(project(":sdk:metrics")) api(project(":sdk:logs")) + implementation(project(":sdk-extensions:autoconfigure-spi")) + testImplementation(project(":sdk:testing")) testImplementation(project(":sdk:logs-testing")) } diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java new file mode 100644 index 00000000000..e6fbd6fbc8d --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingLogRecordExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; +import io.opentelemetry.sdk.logs.export.LogRecordExporter; + +/** + * {@link LogRecordExporter} SPI implementation for {@link SystemOutLogRecordExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider { + @Override + public LogRecordExporter createExporter(ConfigProperties config) { + return SystemOutLogRecordExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java new file mode 100644 index 00000000000..47605ac1154 --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingMetricExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.LoggingMetricExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider; +import io.opentelemetry.sdk.metrics.export.MetricExporter; + +/** + * {@link MetricExporter} SPI implementation for {@link LoggingMetricExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingMetricExporterProvider implements ConfigurableMetricExporterProvider { + @Override + public MetricExporter createExporter(ConfigProperties config) { + return LoggingMetricExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java new file mode 100644 index 00000000000..5854a12fe64 --- /dev/null +++ b/exporters/logging/src/main/java/io/opentelemetry/exporter/logging/internal/LoggingSpanExporterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.internal; + +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; +import io.opentelemetry.sdk.trace.export.SpanExporter; + +/** + * {@link SpanExporter} SPI implementation for {@link LoggingSpanExporter}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class LoggingSpanExporterProvider implements ConfigurableSpanExporterProvider { + @Override + public SpanExporter createExporter(ConfigProperties config) { + return LoggingSpanExporter.create(); + } + + @Override + public String getName() { + return "logging"; + } +} diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider new file mode 100644 index 00000000000..8d8842825ba --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingLogRecordExporterProvider diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider new file mode 100644 index 00000000000..3ad21a55ccd --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingMetricExporterProvider diff --git a/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider new file mode 100644 index 00000000000..8806e4b9608 --- /dev/null +++ b/exporters/logging/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider @@ -0,0 +1 @@ +io.opentelemetry.exporter.logging.internal.LoggingSpanExporterProvider diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index 182e6389c92..6328e6785c4 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -16,7 +16,6 @@ dependencies { implementation(project(":exporters:common")) compileOnly(project(":exporters:jaeger")) - compileOnly(project(":exporters:logging")) compileOnly(project(":exporters:otlp:all")) compileOnly(project(":exporters:otlp:logs")) compileOnly(project(":exporters:otlp:common")) diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java index 927b4eceb2f..9dd3dc19647 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LogRecordExporterConfiguration.java @@ -11,7 +11,6 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.exporter.internal.retry.RetryUtil; -import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; @@ -30,6 +29,12 @@ class LogRecordExporterConfiguration { private static final String EXPORTER_NONE = "none"; + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } // Visible for test static Map configureLogRecordExporters( @@ -85,15 +90,18 @@ static LogRecordExporter configureExporter( switch (name) { case "otlp": return configureOtlpLogs(config, meterProvider); - case "logging": - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.SystemOutLogRecordExporter", - "Logging Log Exporter", - "opentelemetry-exporter-logging"); - return SystemOutLogRecordExporter.create(); default: LogRecordExporter spiExporter = spiExportersManager.getByName(name); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.logs.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.logs.exporter: " + name); } return spiExporter; diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java index ac8e6784b3f..75671f8d314 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java @@ -10,7 +10,6 @@ import static io.opentelemetry.sdk.autoconfigure.OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF; import io.opentelemetry.exporter.internal.retry.RetryUtil; -import io.opentelemetry.exporter.logging.LoggingMetricExporter; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; @@ -24,12 +23,20 @@ import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import java.util.function.BiFunction; import javax.annotation.Nullable; final class MetricExporterConfiguration { private static final Duration DEFAULT_EXPORT_INTERVAL = Duration.ofMinutes(1); + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } static MetricReader configureExporter( String name, @@ -46,12 +53,18 @@ static MetricReader configureExporter( case "otlp": metricExporter = configureOtlpMetrics(config); break; - case "logging": - metricExporter = configureLoggingExporter(); - break; default: MetricExporter spiExporter = configureSpiExporter(name, config, serviceClassLoader); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.metrics.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.metrics.exporter: " + name); } metricExporter = spiExporter; @@ -61,14 +74,6 @@ static MetricReader configureExporter( return configurePeriodicMetricReader(config, metricExporter); } - private static MetricExporter configureLoggingExporter() { - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.LoggingMetricExporter", - "Logging Metrics Exporter", - "opentelemetry-exporter-logging"); - return LoggingMetricExporter.create(); - } - // Visible for testing. @Nullable static MetricExporter configureSpiExporter( diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java index a3d2c394783..89a42620b48 100644 --- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java +++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/SpanExporterConfiguration.java @@ -14,7 +14,6 @@ import io.opentelemetry.exporter.internal.retry.RetryUtil; import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter; import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporterBuilder; -import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; @@ -27,6 +26,7 @@ import io.opentelemetry.sdk.trace.export.SpanExporter; import java.time.Duration; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; @@ -35,6 +35,12 @@ final class SpanExporterConfiguration { private static final String EXPORTER_NONE = "none"; + private static final Map EXPORTER_ARTIFACT_ID_BY_NAME; + + static { + EXPORTER_ARTIFACT_ID_BY_NAME = new HashMap<>(); + EXPORTER_ARTIFACT_ID_BY_NAME.put("logging", "opentelemetry-exporter-logging"); + } // Visible for testing static Map configureSpanExporters( @@ -92,15 +98,18 @@ static SpanExporter configureExporter( return configureJaeger(config, meterProvider); case "zipkin": return configureZipkin(config); - case "logging": - ClasspathUtil.checkClassExists( - "io.opentelemetry.exporter.logging.LoggingSpanExporter", - "Logging Trace Exporter", - "opentelemetry-exporter-logging"); - return LoggingSpanExporter.create(); default: SpanExporter spiExporter = spiExportersManager.getByName(name); if (spiExporter == null) { + String artifactId = EXPORTER_ARTIFACT_ID_BY_NAME.get(name); + if (artifactId != null) { + throw new ConfigurationException( + "otel.traces.exporter set to \"" + + name + + "\" but " + + artifactId + + " not found on classpath. Make sure to add it as a dependency."); + } throw new ConfigurationException("Unrecognized value for otel.traces.exporter: " + name); } return spiExporter; diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java index a4a476b2c62..f3c36438fd0 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/NotOnClasspathTest.java @@ -77,8 +77,8 @@ void loggingSpans() { "logging", EMPTY, NamedSpiManager.createEmpty(), MeterProvider.noop())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Trace Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.traces.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test @@ -92,8 +92,8 @@ void loggingMetrics() { (a, unused) -> a)) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Metrics Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.metrics.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test @@ -104,8 +104,8 @@ void loggingLogs() { "logging", EMPTY, NamedSpiManager.createEmpty(), MeterProvider.noop())) .isInstanceOf(ConfigurationException.class) .hasMessageContaining( - "Logging Log Exporter enabled but opentelemetry-exporter-logging not found on " - + "classpath"); + "otel.logs.exporter set to \"logging\" but opentelemetry-exporter-logging not found on classpath." + + " Make sure to add it as a dependency."); } @Test