Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a AutoConfiguredComponentWrapper SPI #3714

Closed
wants to merge 3 commits into from
Closed
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
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
Comparing source compatibility of against
No changes.
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfiguredComponentWrapper (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.resources.Resource wrap(io.opentelemetry.sdk.resources.Resource, io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.trace.samplers.Sampler wrap(io.opentelemetry.sdk.trace.samplers.Sampler, io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.trace.export.SpanExporter wrap(io.opentelemetry.sdk.trace.export.SpanExporter, io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.context.propagation.TextMapPropagator wrap(io.opentelemetry.context.propagation.TextMapPropagator, io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties)
24 changes: 23 additions & 1 deletion docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,24 @@
Comparing source compatibility of against
No changes.
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.trace.data.DelegatingSpanData (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW INTERFACE: io.opentelemetry.sdk.trace.data.SpanData
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) FINAL(+) boolean equals(java.lang.Object)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.common.Attributes getAttributes()
+++ NEW METHOD: PUBLIC(+) long getEndEpochNanos()
+++ NEW METHOD: PUBLIC(+) java.util.List getEvents()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationLibraryInfo getInstrumentationLibraryInfo()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.trace.SpanKind getKind()
+++ NEW METHOD: PUBLIC(+) java.util.List getLinks()
+++ NEW METHOD: PUBLIC(+) java.lang.String getName()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.trace.SpanContext getParentSpanContext()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.resources.Resource getResource()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.trace.SpanContext getSpanContext()
+++ NEW METHOD: PUBLIC(+) long getStartEpochNanos()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.trace.data.StatusData getStatus()
+++ NEW METHOD: PUBLIC(+) int getTotalAttributeCount()
+++ NEW METHOD: PUBLIC(+) int getTotalRecordedEvents()
+++ NEW METHOD: PUBLIC(+) int getTotalRecordedLinks()
+++ NEW METHOD: PUBLIC(+) boolean hasEnded()
+++ NEW METHOD: PUBLIC(+) int hashCode()
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.spi;

import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;

/**
* A service provider interface (SPI) for wrapping autoconfigured components. For any component
* automatically created by autoconfiguration, for example a span exporter, implementations of this
* interface will be invoked to replace it, resulting in the final used component.
*/
public interface AutoConfiguredComponentWrapper {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have defined this and used in place of my previous proposed SpanExporterWrapper. Let me know if this looks OK and I'll slot it in the rest of the places


/** Wraps a {@link Resource}. */
default Resource wrap(Resource resource, ConfigProperties config) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap is an odd name here, since you'd presumably just use the normal merge functionality for Resources, wouldn't you?

I wonder if the names of these methods should be something more generic than wrap, but a good name escapes me right this second. augment? decorate? customize maybe?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the more I think about it, the more I like "AutoConfiguredComponentCustomizer" as the SPI name.

return resource;
}

/** Wraps a {@link Sampler}. */
default Sampler wrap(Sampler sampler, ConfigProperties config) {
return sampler;
}

/**
* Wraps a {@link SpanExporter}. It is common to use in conjunction with {@link
* io.opentelemetry.sdk.trace.data.DelegatingSpanData} to adjust the exported data.
*/
default SpanExporter wrap(SpanExporter exporter, ConfigProperties config) {
return exporter;
}

/** Wraps a {@link TextMapPropagator}. */
default TextMapPropagator wrap(TextMapPropagator propagator, ConfigProperties config) {
return propagator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.spi.internal;

import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfiguredComponentWrapper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;

/**
* Wraps components with SPI 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 ComponentWrapping {

private static final List<AutoConfiguredComponentWrapper> wrappers;

static {
List<AutoConfiguredComponentWrapper> loaded = new ArrayList<>();
ServiceLoader.load(AutoConfiguredComponentWrapper.class).forEach(loaded::add);
wrappers = Collections.unmodifiableList(loaded);
}

/** Wraps a {@link Resource}. */
public static Resource wrap(Resource resource, ConfigProperties config) {
for (AutoConfiguredComponentWrapper wrapper : wrappers) {
resource = wrapper.wrap(resource, config);
}
return resource;
}

/** Wraps a {@link Sampler}. */
public static Sampler wrap(Sampler sampler, ConfigProperties config) {
for (AutoConfiguredComponentWrapper wrapper : wrappers) {
sampler = wrapper.wrap(sampler, config);
}
return sampler;
}

/**
* Wraps a {@link SpanExporter}. It is common to use in conjunction with {@link
* io.opentelemetry.sdk.trace.data.DelegatingSpanData} to adjust the exported data.
*/
public static SpanExporter wrap(SpanExporter exporter, ConfigProperties config) {
for (AutoConfiguredComponentWrapper wrapper : wrappers) {
exporter = wrapper.wrap(exporter, config);
}
return exporter;
}

/** Wraps a {@link TextMapPropagator}. */
public static TextMapPropagator wrap(TextMapPropagator propagator, ConfigProperties config) {
for (AutoConfiguredComponentWrapper wrapper : wrappers) {
propagator = wrapper.wrap(propagator, config);
}
return propagator;
}

private ComponentWrapping() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

/** Internal utilities for autoconfiguration. */
@ParametersAreNonnullByDefault
package io.opentelemetry.sdk.autoconfigure.spi.internal;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporterBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentWrapping;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.time.Duration;
Expand Down Expand Up @@ -77,7 +78,10 @@ static Map<String, SpanExporter> configureSpanExporters(ConfigProperties config)
.collect(
toMap(
Function.identity(),
exporterName -> configureExporter(exporterName, config, spiExporters)));
exporterName -> {
SpanExporter exporter = configureExporter(exporterName, config, spiExporters);
return ComponentWrapping.wrap(exporter, config);
}));
}

// Visible for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ void configureSpanExporters_spiExporter() {
.hasSize(1)
.containsKey("testExporter")
.extracting(map -> map.get("testExporter"))
.isInstanceOf(TestComponentWrapper.WrappingSpanExporter.class)
.extracting("delegate")
.isInstanceOf(TestConfigurableSpanExporterProvider.TestSpanExporter.class)
.extracting("config")
.isSameAs(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ void configures() throws Exception {
.setKey("configured")
.setValue(AnyValue.newBuilder().setBoolValue(true).build())
.build(),
KeyValue.newBuilder()
.setKey("wrapped")
.setValue(AnyValue.newBuilder().setBoolValue(true).build())
.build(),
KeyValue.newBuilder()
.setKey("cat")
.setValue(AnyValue.newBuilder().setStringValue("meow").build())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfiguredComponentWrapper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.DelegatingSpanData;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public final class TestComponentWrapper implements AutoConfiguredComponentWrapper {
@Override
public SpanExporter wrap(SpanExporter delegate, ConfigProperties config) {
return new WrappingSpanExporter(delegate) {
@Override
public CompletableResultCode export(Collection<SpanData> spans) {
List<SpanData> wrapped =
spans.stream()
.map(
span ->
new DelegatingSpanData(span) {
@Override
public Attributes getAttributes() {
return span.getAttributes().toBuilder().put("wrapped", true).build();
}
})
.collect(Collectors.toList());
return delegate.export(wrapped);
}
};
}

abstract static class WrappingSpanExporter implements SpanExporter {

private final SpanExporter delegate;

WrappingSpanExporter(SpanExporter delegate) {
this.delegate = delegate;
}

@Override
public CompletableResultCode flush() {
return delegate.flush();
}

@Override
public CompletableResultCode shutdown() {
return delegate.shutdown();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.sdk.autoconfigure.TestComponentWrapper
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@
* // }
* // }
* }</pre>
*
* @deprecated Use {@link io.opentelemetry.sdk.trace.data.DelegatingSpanData}, which is the exact
* same as this one.
*/
@Deprecated
public abstract class DelegatingSpanData implements SpanData {

private final SpanData delegate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration;
import org.junit.jupiter.api.Test;

@SuppressWarnings("deprecation") // Tests deprecated class
class DelegatingSpanDataTest {

private static final AttributeKey<String> CLIENT_TYPE_KEY = stringKey("client_type");
Expand Down
1 change: 1 addition & 0 deletions sdk/trace/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {

testImplementation(project(":sdk:testing"))
testImplementation("com.google.guava:guava")
testImplementation("com.google.guava:guava-testlib")

jmh(project(":sdk:metrics"))
jmh(project(":sdk:testing")) {
Expand Down
Loading