Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dependencyManagement/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ val DEPENDENCY_BOMS = listOf(
// by FOSSA for containing EPL-licensed)

"com.fasterxml.jackson:jackson-bom:2.22.0",
"tools.jackson:jackson-bom:3.2.0",
"com.google.guava:guava-bom:33.6.0-jre",
"com.google.protobuf:protobuf-bom:4.35.1",
"com.squareup.okhttp3:okhttp-bom:$okhttpVersion",
Expand Down
9 changes: 4 additions & 5 deletions exporters/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ plugins {

description = "OpenTelemetry Exporter Common"
otelJava.moduleName.set("io.opentelemetry.exporter.internal")
otelJava.osgiOptionalPackages.set(listOf("com.fasterxml.jackson.core", "com.google.common.io", "io.opentelemetry.api.incubator.config", "io.opentelemetry.sdk.autoconfigure.spi"))
otelJava.osgiOptionalPackages.set(listOf("com.google.common.io", "io.opentelemetry.api.incubator.config", "io.opentelemetry.sdk.autoconfigure.spi"))
// sun.misc, io.grpc, and org.jspecify are not OSGi bundles and have no package versioning; must use unversioned optional.
otelJava.osgiUnversionedOptionalPackages.set(listOf("sun.misc", "io.grpc", "org.jspecify.annotations"))
// This bundle's exporters load sender implementations via SPI.
otelJava.osgiServiceLoaderRequires.set(listOf(
"io.opentelemetry.sdk.common.export.GrpcSenderProvider",
"io.opentelemetry.sdk.common.export.HttpSenderProvider"
"io.opentelemetry.sdk.common.export.HttpSenderProvider",
"io.opentelemetry.sdk.common.export.JsonProvider"
))

java {
Expand Down Expand Up @@ -69,13 +70,11 @@ dependencies {

annotationProcessor("com.google.auto.value:auto-value")

// We include helpers shared by gRPC exporters but do not want to impose these
// dependency on all of our consumers.
compileOnly("com.fasterxml.jackson.core:jackson-core")
// sun.misc.Unsafe from the JDK isn't found by the compiler, we provide our own trimmed down
// version that we can compile against.
compileOnly("io.grpc:grpc-stub")

testImplementation(project(":json:jackson-2"))
testImplementation(project(":sdk:common"))
testImplementation(project(":sdk:testing"))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.internal;

import io.opentelemetry.api.internal.ConfigUtil;
import io.opentelemetry.common.ComponentLoader;
import io.opentelemetry.sdk.common.export.JsonProvider;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Utilities for loading {@link JsonProvider} implementations.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public final class JsonProviderUtil {

private static final Logger LOGGER = Logger.getLogger(JsonProviderUtil.class.getName());

private static final String JSON_SPI_PROPERTY = "io.opentelemetry.sdk.common.export.JsonProvider";

private JsonProviderUtil() {}

/**
* Resolve the {@link JsonProvider}.
*
* <p>If no {@link JsonProvider} is available, throw {@link IllegalStateException}.
*
* <p>If only one {@link JsonProvider} is available, use it.
*
* <p>If multiple are available and..
*
* <ul>
* <li>{@code io.opentelemetry.sdk.common.export.JsonProvider} is empty, use the first found.
* <li>{@code io.opentelemetry.sdk.common.export.JsonProvider} is set, use the matching
* provider. If none match, throw {@link IllegalStateException}.
* </ul>
*/
public static JsonProvider resolveJsonProvider(ComponentLoader componentLoader) {
Map<String, JsonProvider> jsonProviders = new HashMap<>();
for (JsonProvider spi : componentLoader.load(JsonProvider.class)) {
jsonProviders.put(spi.getClass().getName(), spi);
}

// No provider on classpath, throw
if (jsonProviders.isEmpty()) {
throw new IllegalStateException(
"No JsonProvider found on classpath. Please add dependency on "
+ "opentelemetry-json-jackson-2 or opentelemetry-json-jackson-3");
}

// Exactly one provider on classpath, use it
if (jsonProviders.size() == 1) {
return jsonProviders.values().stream().findFirst().get();
}

// If we've reached here, there are multiple JsonProviders
String configuredProvider = ConfigUtil.getString(JSON_SPI_PROPERTY, "");

// Multiple providers but none configured, use first we find and log a warning
if (configuredProvider.isEmpty()) {
LOGGER.log(
Level.WARNING,
"Multiple JsonProvider found. Please include only one, "
+ "or specify preference setting "
+ JSON_SPI_PROPERTY
+ " to the FQCN of the preferred provider.");
return jsonProviders.values().stream().findFirst().get();
}

// Multiple providers with configuration match, use configuration match
if (jsonProviders.containsKey(configuredProvider)) {
return jsonProviders.get(configuredProvider);
}

// Multiple providers, configured does not match, throw
throw new IllegalStateException(
"No JsonProvider matched configured " + JSON_SPI_PROPERTY + ": " + configuredProvider);
}
}
Loading
Loading