Extend InstrumentationScopeInfo with scope attributes (#4696)

* Extend InstrumentationScopeInfo with scope attributes

* Add InstrumentationScopeInfoBuilder
This commit is contained in:
jack-berg 2022-08-22 12:26:54 -05:00 committed by GitHub
parent c5bc5a0555
commit d0c6cd4480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 217 additions and 124 deletions

View File

@ -1,2 +1,12 @@
Comparing source compatibility of against
No changes.
**** MODIFIED CLASS: PUBLIC ABSTRACT io.opentelemetry.sdk.common.InstrumentationScopeInfo (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder builder(java.lang.String)
+++* NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.api.common.Attributes getAttributes()
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfo build()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder setAttributes(io.opentelemetry.api.common.Attributes)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder setSchemaUrl(java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder setVersion(java.lang.String)

View File

@ -8,6 +8,7 @@ package io.opentelemetry.sdk.common;
import static java.util.Objects.requireNonNull;
import com.google.auto.value.AutoValue;
import io.opentelemetry.api.common.Attributes;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@ -26,15 +27,30 @@ public abstract class InstrumentationScopeInfo {
/** Creates a new instance of {@link InstrumentationScopeInfo}. */
public static InstrumentationScopeInfo create(String name) {
requireNonNull(name, "name");
return new AutoValue_InstrumentationScopeInfo(name, null, null);
return InstrumentationScopeInfo.create(name, null, null, Attributes.empty());
}
/** Creates a new instance of {@link InstrumentationScopeInfo}. */
public static InstrumentationScopeInfo create(
String name, @Nullable String version, @Nullable String schemaUrl) {
return InstrumentationScopeInfo.create(name, version, schemaUrl, Attributes.empty());
}
static InstrumentationScopeInfo create(
String name, @Nullable String version, @Nullable String schemaUrl, Attributes attributes) {
requireNonNull(name, "name");
return new AutoValue_InstrumentationScopeInfo(name, version, schemaUrl);
requireNonNull(attributes, "attributes");
return new AutoValue_InstrumentationScopeInfo(name, version, schemaUrl, attributes);
}
/**
* Returns a {@link InstrumentationScopeInfoBuilder builder} for a {@link
* InstrumentationScopeInfo}.
*
* @since 1.18.0
*/
public static InstrumentationScopeInfoBuilder builder(String name) {
return new InstrumentationScopeInfoBuilder(name);
}
/** Returns an "empty" {@link InstrumentationScopeInfo}. */
@ -56,5 +72,8 @@ public abstract class InstrumentationScopeInfo {
@Nullable
public abstract String getSchemaUrl();
/** Returns the attributes of this instrumentation scope. */
public abstract Attributes getAttributes();
InstrumentationScopeInfo() {}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.common;
import io.opentelemetry.api.common.Attributes;
import javax.annotation.Nullable;
/**
* A builder for {@link InstrumentationScopeInfo}.
*
* @since 1.18.0
*/
public final class InstrumentationScopeInfoBuilder {
private final String name;
@Nullable private String version;
@Nullable private String schemaUrl;
@Nullable private Attributes attributes;
InstrumentationScopeInfoBuilder(String name) {
this.name = name;
}
/** Set the version. */
public InstrumentationScopeInfoBuilder setVersion(String version) {
this.version = version;
return this;
}
/** Set the schema URL. */
public InstrumentationScopeInfoBuilder setSchemaUrl(String schemaUrl) {
this.schemaUrl = schemaUrl;
return this;
}
/** Set the attributes. */
public InstrumentationScopeInfoBuilder setAttributes(Attributes attributes) {
this.attributes = attributes;
return this;
}
/** Return a {@link InstrumentationScopeInfo} with the configuration of this builder. */
public InstrumentationScopeInfo build() {
return InstrumentationScopeInfo.create(
name, version, schemaUrl, attributes == null ? Attributes.empty() : attributes);
}
}

View File

@ -12,10 +12,10 @@ import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import javax.annotation.Nullable;
/**
* Base class for all the provider classes (TracerProvider, MeterProvider, etc.).
* Component (tracer, meter, etc) registry class for all the provider classes (TracerProvider,
* MeterProvider, etc.).
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
@ -32,48 +32,10 @@ public final class ComponentRegistry<V> {
}
/**
* Returns the registered value associated with this name and {@code null} version if any,
* otherwise creates a new instance and associates it with the given name and {@code null} version
* and schemaUrl.
*
* @param instrumentationScopeName the name of the instrumentation scope.
* @return the registered value associated with this name and {@code null} version.
* Returns the registered value associated with this {@link InstrumentationScopeInfo scope} if
* any, otherwise creates a new instance and associates it with the given scope.
*/
public V get(String instrumentationScopeName) {
return get(instrumentationScopeName, null);
}
/**
* Returns the registered value associated with this name and version if any, otherwise creates a
* new instance and associates it with the given name and version. The schemaUrl will be set to
* null.
*
* @param instrumentationScopeName the name of the instrumentation scope.
* @param instrumentationScopeVersion the version of the instrumentation scope.
* @return the registered value associated with this name and version.
*/
public V get(String instrumentationScopeName, @Nullable String instrumentationScopeVersion) {
return get(instrumentationScopeName, instrumentationScopeVersion, null);
}
/**
* Returns the registered value associated with this name and version if any, otherwise creates a
* new instance and associates it with the given name and version.
*
* @param instrumentationScopeName the name of the instrumentation scope.
* @param instrumentationScopeVersion the version of the instrumentation scope.
* @param schemaUrl the URL of the OpenTelemetry schema used by the instrumentation scope.
* @return the registered value associated with this name and version.
* @since 1.4.0
*/
public V get(
String instrumentationScopeName,
@Nullable String instrumentationScopeVersion,
@Nullable String schemaUrl) {
InstrumentationScopeInfo instrumentationScopeInfo =
InstrumentationScopeInfo.create(
instrumentationScopeName, instrumentationScopeVersion, schemaUrl);
public V get(InstrumentationScopeInfo instrumentationScopeInfo) {
// Optimistic lookup, before creating the new component.
V component = registry.get(instrumentationScopeInfo);
if (component != null) {

View File

@ -6,22 +6,40 @@
package io.opentelemetry.sdk.common;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import io.opentelemetry.api.common.Attributes;
import org.junit.jupiter.api.Test;
class InstrumentationScopeInfoTest {
@Test
void create_InvalidArguments() {
assertThatThrownBy(() -> InstrumentationScopeInfo.builder(null).build())
.isInstanceOf(NullPointerException.class)
.hasMessage("name");
}
@Test
void create_Valid() {
assertThatCode(() -> InstrumentationScopeInfo.builder("name").build())
.doesNotThrowAnyException();
assertThatCode(() -> InstrumentationScopeInfo.builder("name").setVersion(null).build())
.doesNotThrowAnyException();
assertThatCode(() -> InstrumentationScopeInfo.builder("name").setSchemaUrl(null).build())
.doesNotThrowAnyException();
assertThatCode(
() ->
InstrumentationScopeInfo.builder("name")
.setAttributes(Attributes.builder().put("key", "value").build())
.build())
.doesNotThrowAnyException();
}
@Test
void emptyScopeInfo() {
assertThat(InstrumentationScopeInfo.empty().getName()).isEmpty();
assertThat(InstrumentationScopeInfo.empty().getVersion()).isNull();
}
@Test
void nullName() {
assertThatThrownBy(() -> InstrumentationScopeInfo.create(null))
.isInstanceOf(NullPointerException.class)
.hasMessage("name");
}
}

View File

@ -6,63 +6,100 @@
package io.opentelemetry.sdk.internal;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import org.junit.jupiter.api.Test;
class ComponentRegistryTest {
private static final String INSTRUMENTATION_NAME = "test_name";
private static final String INSTRUMENTATION_VERSION = "version";
private static final String NAME = "test_name";
private static final String VERSION = "version";
private static final String SCHEMA_URL = "http://schema.com";
private static final Attributes ATTRIBUTES = Attributes.builder().put("k1", "v1").build();
private final ComponentRegistry<TestComponent> registry =
new ComponentRegistry<>(TestComponent::new);
new ComponentRegistry<>(unused -> new TestComponent());
@Test
void scopeName_MustNotBeNull() {
assertThatThrownBy(() -> registry.get(null, "version"))
.isInstanceOf(NullPointerException.class)
.hasMessage("name");
void get_SameInstance() {
assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).build()))
.isSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()))
.isSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()));
assertThat(
registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()))
.isSameAs(
registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()));
assertThat(
registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()))
.isSameAs(
registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()));
assertThat(
registry.get(
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL)
.setAttributes(ATTRIBUTES)
.build()))
.isSameAs(
registry.get(
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL)
.setAttributes(ATTRIBUTES)
.build()));
}
@Test
void scopeVersion_AllowsNull() {
TestComponent testComponent = registry.get(INSTRUMENTATION_NAME, null);
assertThat(testComponent).isNotNull();
assertThat(testComponent.instrumentationScopeInfo.getName()).isEqualTo(INSTRUMENTATION_NAME);
assertThat(testComponent.instrumentationScopeInfo.getVersion()).isNull();
void get_DifferentInstance() {
InstrumentationScopeInfo allFields =
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL)
.setAttributes(ATTRIBUTES)
.build();
assertThat(registry.get(allFields))
.isNotSameAs(
registry.get(
InstrumentationScopeInfo.builder(NAME + "_1")
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL)
.setAttributes(ATTRIBUTES)
.build()));
assertThat(registry.get(allFields))
.isNotSameAs(
registry.get(
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION + "_1")
.setSchemaUrl(SCHEMA_URL)
.setAttributes(ATTRIBUTES)
.build()));
assertThat(registry.get(allFields))
.isNotSameAs(
registry.get(
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL + "_1")
.setAttributes(ATTRIBUTES)
.build()));
assertThat(registry.get(allFields))
.isNotSameAs(
registry.get(
InstrumentationScopeInfo.builder(NAME)
.setVersion(VERSION)
.setSchemaUrl(SCHEMA_URL)
.setAttributes(Attributes.builder().put("k1", "v2").build())
.build()));
assertThat(registry.get(InstrumentationScopeInfo.builder(NAME).setVersion(VERSION).build()))
.isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
assertThat(
registry.get(InstrumentationScopeInfo.builder(NAME).setSchemaUrl(SCHEMA_URL).build()))
.isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
assertThat(
registry.get(InstrumentationScopeInfo.builder(NAME).setAttributes(ATTRIBUTES).build()))
.isNotSameAs(registry.get(InstrumentationScopeInfo.builder(NAME).build()));
}
@Test
void getSameInstanceForSameName_WithoutVersion() {
assertThat(registry.get(INSTRUMENTATION_NAME)).isSameAs(registry.get(INSTRUMENTATION_NAME));
assertThat(registry.get(INSTRUMENTATION_NAME))
.isSameAs(registry.get(INSTRUMENTATION_NAME, null));
}
@Test
void getSameInstanceForSameName_WithVersion() {
assertThat(registry.get(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION))
.isSameAs(registry.get(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION));
}
@Test
void getDifferentInstancesForDifferentNames() {
assertThat(registry.get(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION))
.isNotSameAs(registry.get(INSTRUMENTATION_NAME + "_2", INSTRUMENTATION_VERSION));
}
@Test
void getDifferentInstancesForDifferentVersions() {
assertThat(registry.get(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION))
.isNotSameAs(registry.get(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION + "_1"));
}
private static final class TestComponent {
private final InstrumentationScopeInfo instrumentationScopeInfo;
private TestComponent(InstrumentationScopeInfo instrumentationScopeInfo) {
this.instrumentationScopeInfo = instrumentationScopeInfo;
}
}
private static final class TestComponent {}
}

View File

@ -5,35 +5,34 @@
package io.opentelemetry.sdk.logs;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import javax.annotation.Nullable;
final class SdkLogEmitterBuilder implements LogEmitterBuilder {
private final ComponentRegistry<SdkLogEmitter> registry;
private final String instrumentationScopeName;
@Nullable private String instrumentationScopeVersion;
@Nullable private String schemaUrl;
private final InstrumentationScopeInfoBuilder scopeBuilder;
SdkLogEmitterBuilder(ComponentRegistry<SdkLogEmitter> registry, String instrumentationScopeName) {
this.registry = registry;
this.instrumentationScopeName = instrumentationScopeName;
this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
}
@Override
public SdkLogEmitterBuilder setSchemaUrl(String schemaUrl) {
this.schemaUrl = schemaUrl;
scopeBuilder.setSchemaUrl(schemaUrl);
return this;
}
@Override
public SdkLogEmitterBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
this.instrumentationScopeVersion = instrumentationScopeVersion;
scopeBuilder.setVersion(instrumentationScopeVersion);
return this;
}
@Override
public SdkLogEmitter build() {
return registry.get(instrumentationScopeName, instrumentationScopeVersion, schemaUrl);
return registry.get(scopeBuilder.build());
}
}

View File

@ -7,35 +7,34 @@ package io.opentelemetry.sdk.metrics;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterBuilder;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import javax.annotation.Nullable;
class SdkMeterBuilder implements MeterBuilder {
private final ComponentRegistry<SdkMeter> registry;
private final String instrumentationScopeName;
@Nullable private String instrumentationScopeVersion;
@Nullable private String schemaUrl;
private final InstrumentationScopeInfoBuilder scopeBuilder;
SdkMeterBuilder(ComponentRegistry<SdkMeter> registry, String instrumentationScopeName) {
this.registry = registry;
this.instrumentationScopeName = instrumentationScopeName;
this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
}
@Override
public MeterBuilder setSchemaUrl(String schemaUrl) {
this.schemaUrl = schemaUrl;
scopeBuilder.setSchemaUrl(schemaUrl);
return this;
}
@Override
public MeterBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
this.instrumentationScopeVersion = instrumentationScopeVersion;
scopeBuilder.setVersion(instrumentationScopeVersion);
return this;
}
@Override
public Meter build() {
return registry.get(instrumentationScopeName, instrumentationScopeVersion, schemaUrl);
return registry.get(scopeBuilder.build());
}
}

View File

@ -7,35 +7,34 @@ package io.opentelemetry.sdk.trace;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerBuilder;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import javax.annotation.Nullable;
class SdkTracerBuilder implements TracerBuilder {
private final ComponentRegistry<SdkTracer> registry;
private final String instrumentationScopeName;
@Nullable private String instrumentationScopeVersion;
@Nullable private String schemaUrl;
private final InstrumentationScopeInfoBuilder scopeBuilder;
SdkTracerBuilder(ComponentRegistry<SdkTracer> registry, String instrumentationScopeName) {
this.registry = registry;
this.instrumentationScopeName = instrumentationScopeName;
this.scopeBuilder = InstrumentationScopeInfo.builder(instrumentationScopeName);
}
@Override
public TracerBuilder setSchemaUrl(String schemaUrl) {
this.schemaUrl = schemaUrl;
scopeBuilder.setSchemaUrl(schemaUrl);
return this;
}
@Override
public TracerBuilder setInstrumentationVersion(String instrumentationScopeVersion) {
this.instrumentationScopeVersion = instrumentationScopeVersion;
scopeBuilder.setVersion(instrumentationScopeVersion);
return this;
}
@Override
public Tracer build() {
return registry.get(instrumentationScopeName, instrumentationScopeVersion, schemaUrl);
return registry.get(scopeBuilder.build());
}
}

View File

@ -993,7 +993,7 @@ class SdkSpanBuilderTest {
+ "telemetry.sdk.language=\"java\", telemetry.sdk.name=\"opentelemetry\", "
+ "telemetry.sdk.version=\"\\d+.\\d+.\\d+(-rc.\\d+)?(-SNAPSHOT)?\"}}, "
+ "instrumentationScopeInfo=InstrumentationScopeInfo\\{"
+ "name=SpanBuilderSdkTest, version=null, schemaUrl=null}, "
+ "name=SpanBuilderSdkTest, version=null, schemaUrl=null, attributes=\\{}}, "
+ "name=span_name, "
+ "kind=INTERNAL, "
+ "startEpochNanos=[0-9]+, "