Skip to content

Commit

Permalink
Allow passing schemaUrl to tracer and meter provider, separate sdk op…
Browse files Browse the repository at this point in the history
…tions to a new class
  • Loading branch information
lmolkova committed Sep 19, 2024
1 parent 93c25d8 commit 5e93d11
Show file tree
Hide file tree
Showing 21 changed files with 343 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.azure.core.util.Context;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.MetricsOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TelemetryAttributes;
import com.azure.core.util.metrics.DoubleHistogram;
import com.azure.core.util.metrics.LongCounter;
Expand All @@ -28,15 +29,21 @@ class OpenTelemetryMeter implements Meter {
private final io.opentelemetry.api.metrics.Meter meter;
private final boolean isEnabled;

OpenTelemetryMeter(String libraryName, String libraryVersion, MetricsOptions options) {
OpenTelemetryMeter(SdkTelemetryOptions sdkOptions, MetricsOptions applicationOptions) {
MeterProvider otelProvider = GlobalOpenTelemetry.getMeterProvider();
if (options != null && options.isEnabled() && options instanceof OpenTelemetryMetricsOptions) {
OpenTelemetryMetricsOptions otelOptions = (OpenTelemetryMetricsOptions) options;
if (applicationOptions != null
&& applicationOptions.isEnabled()
&& applicationOptions instanceof OpenTelemetryMetricsOptions) {
OpenTelemetryMetricsOptions otelOptions = (OpenTelemetryMetricsOptions) applicationOptions;
otelProvider = otelOptions.getOpenTelemetryProvider();
}

this.isEnabled = (options == null || options.isEnabled()) && otelProvider != MeterProvider.noop();
this.meter = otelProvider.meterBuilder(libraryName).setInstrumentationVersion(libraryVersion).build();
this.isEnabled
= (applicationOptions == null || applicationOptions.isEnabled()) && otelProvider != MeterProvider.noop();
this.meter = otelProvider.meterBuilder(sdkOptions.getSdkName())
.setInstrumentationVersion(sdkOptions.getSdkVersion())
.setSchemaUrl(sdkOptions.getSchemaUrl())
.build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.azure.core.metrics.opentelemetry;

import com.azure.core.util.MetricsOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.metrics.Meter;
import com.azure.core.util.metrics.MeterProvider;

Expand All @@ -23,6 +24,22 @@ public final class OpenTelemetryMeterProvider implements MeterProvider {
public OpenTelemetryMeterProvider() {
}

/**
* Creates named and versioned OpenTelemetry-based implementation of {@link Meter}
*
* @param libraryName Azure client library package name
* @param libraryVersion Azure client library version
* @param applicationOptions instance of {@link MetricsOptions} provided by the application.
* @return a meter instance.
*/
@Override
public Meter createMeter(String libraryName, String libraryVersion, MetricsOptions applicationOptions) {
Objects.requireNonNull(libraryName, "'libraryName' cannot be null.");
final SdkTelemetryOptions sdkOptions
= new SdkTelemetryOptions().setSdkName(libraryName).setSdkVersion(libraryVersion);
return new OpenTelemetryMeter(sdkOptions, applicationOptions);
}

/**
* Creates named and versioned OpenTelemetry-based implementation of {@link Meter}
*
Expand Down Expand Up @@ -103,14 +120,13 @@ public OpenTelemetryMeterProvider() {
* </pre>
* <!-- end com.azure.core.util.metrics.OpenTelemetryMeterProvider.createMeter#custom -->
*
* @param libraryName Azure client library package name
* @param libraryVersion Azure client library version
* @param options instance of {@link MetricsOptions}
* @param sdkOptions Azure SDK telemetry options.
* @param applicationOptions instance of {@link MetricsOptions} provided by the application.
* @return a meter instance.
*/
@Override
public Meter createMeter(String libraryName, String libraryVersion, MetricsOptions options) {
Objects.requireNonNull(libraryName, "'libraryName' cannot be null.");
return new OpenTelemetryMeter(libraryName, libraryVersion, options);
public Meter createMeter(SdkTelemetryOptions sdkOptions, MetricsOptions applicationOptions) {
Objects.requireNonNull(sdkOptions, "'sdkOptions' cannot be null.");
return new OpenTelemetryMeter(sdkOptions, applicationOptions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.azure.core.util.ClientOptions;
import com.azure.core.util.Context;
import com.azure.core.util.MetricsOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TelemetryAttributes;
import com.azure.core.util.metrics.DoubleHistogram;
import com.azure.core.util.metrics.Meter;
Expand Down Expand Up @@ -192,7 +193,12 @@ private static final class AzureClient {
private final DoubleHistogram callDuration;
private final TelemetryAttributes attributes;
AzureClient(String endpoint, ClientOptions options) {
meter = DEFAULT_PROVIDER.createMeter("azure-core-samples", "1.0.0", options == null ? null : options.getMetricsOptions());
SdkTelemetryOptions sdkTelemetryOptions = new SdkTelemetryOptions()
.setSdkName("azure-samples")
.setSdkVersion("1.0.0")
.setSdkVersion("Microsoft.Sample")
.setSchemaUrl("https://opentelemetry.io/schemas/1.23.1");
meter = DEFAULT_PROVIDER.createMeter(sdkTelemetryOptions, options == null ? null : options.getMetricsOptions());
callDuration = meter.createDoubleHistogram("az.sample.method.duration", "Duration of sample method call", "ms");
attributes = meter.createAttributes(Collections.singletonMap("endpoint", endpoint));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.azure.core.util.Context;
import com.azure.core.util.MetricsOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TelemetryAttributes;
import com.azure.core.util.metrics.DoubleHistogram;
import com.azure.core.util.metrics.LongCounter;
Expand Down Expand Up @@ -367,4 +368,23 @@ public void gaugeMultiple() throws Exception {
testClock.advance(Duration.ofNanos(SECOND_NANOS));
assertThat(sdkMeterReader.collectAllMetrics()).isEmpty();
}

@Test
public void sdkOptions() {
SdkTelemetryOptions sdkOptions = new SdkTelemetryOptions().setSdkName("az.sdk-name")
.setSdkVersion("1.0.0-beta.1")
.setSchemaUrl("https://aka.ms/az/sdk/schema:1.42.0");
InstrumentationScopeInfo expectedInstrumentationScope = InstrumentationScopeInfo.create(sdkOptions.getSdkName(),
sdkOptions.getSdkVersion(), sdkOptions.getSchemaUrl());

Meter meter = MeterProvider.getDefaultProvider()
.createMeter(sdkOptions, new OpenTelemetryMetricsOptions().setOpenTelemetry(openTelemetry));
assertTrue(meter.isEnabled());
DoubleHistogram histogram = meter.createDoubleHistogram("az.sdk.test-histogram", "important metric", null);
assertTrue(histogram.isEnabled());
histogram.record(1, new OpenTelemetryAttributes(Collections.emptyMap()), Context.NONE);
testClock.advance(Duration.ofNanos(SECOND_NANOS));
assertThat(sdkMeterReader.collectAllMetrics())
.satisfiesExactly(metric -> assertThat(metric).hasInstrumentationScope(expectedInstrumentationScope));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.azure.core.test.utils.metrics.TestMeter;
import com.azure.core.util.MetricsOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.metrics.Meter;
import com.azure.core.util.metrics.MeterProvider;
import org.junit.jupiter.api.Test;
Expand All @@ -16,7 +17,7 @@

public class OpenTelemetryMeterProviderTests {
@Test
public void noopMEter() {
public void noopMeter() {
Meter meter = MeterProvider.getDefaultProvider().createMeter("foo", null, null);
assertNotNull(meter);
assertFalse(meter.isEnabled());
Expand All @@ -26,6 +27,11 @@ public void noopMEter() {
public void invalidParams() {
assertThrows(NullPointerException.class,
() -> MeterProvider.getDefaultProvider().createMeter(null, null, null));

assertThrows(NullPointerException.class, () -> MeterProvider.getDefaultProvider().createMeter(null, null));

assertThrows(NullPointerException.class,
() -> MeterProvider.getDefaultProvider().createMeter(new SdkTelemetryOptions(), null));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.azure.core.tracing.opentelemetry.OpenTelemetryTracingOptions;
import com.azure.core.util.ClientOptions;
import com.azure.core.util.Context;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TracingOptions;
import com.azure.core.util.tracing.TracerProvider;
import io.opentelemetry.api.OpenTelemetry;
Expand Down Expand Up @@ -142,8 +143,13 @@ private static final class AzureClient {
private static final TracerProvider DEFAULT_PROVIDER = TracerProvider.getDefaultProvider();
private final com.azure.core.util.tracing.Tracer tracer;
AzureClient(String endpoint, ClientOptions options) {
tracer = DEFAULT_PROVIDER.createTracer("azure-storage-blob", "12.20.0",
"Microsoft.Storage", options == null ? null : options.getTracingOptions());
SdkTelemetryOptions sdkTelemetryOptions = new SdkTelemetryOptions()
.setSdkName("azure-sample")
.setSdkVersion("12.20.0")
.setSdkVersion("Microsoft.Sample")
.setSchemaUrl("https://opentelemetry.io/schemas/1.23.1");

tracer = DEFAULT_PROVIDER.createTracer(sdkTelemetryOptions, options == null ? null : options.getTracingOptions());
}

public String methodCall(String request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import com.azure.core.util.Context;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TracingOptions;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.tracing.StartSpanOptions;
Expand Down Expand Up @@ -41,7 +42,7 @@ public class OpenTelemetryTracer implements com.azure.core.util.tracing.Tracer {
private static final StartSpanOptions DEFAULT_SPAN_START_OPTIONS
= new StartSpanOptions(com.azure.core.util.tracing.SpanKind.INTERNAL);
private static final TextMapPropagator TRACE_CONTEXT_FORMAT = W3CTraceContextPropagator.getInstance();
private static final String SCHEMA_URL = "https://opentelemetry.io/schemas/1.23.1";
private static final String DEFAULT_SCHEMA_URL = "https://opentelemetry.io/schemas/1.23.1";
private static final ClientLogger LOGGER = new ClientLogger(OpenTelemetryTracer.class);
private static final AutoCloseable NOOP_CLOSEABLE = () -> {
};
Expand Down Expand Up @@ -92,22 +93,23 @@ public class OpenTelemetryTracer implements com.azure.core.util.tracing.Tracer {
*
*/
public OpenTelemetryTracer() {
this("azure-core", null, null, null);
this(new SdkTelemetryOptions().setSdkName("azure-core"), null);
}

/**
* Creates new {@link OpenTelemetryTracer} using default global tracer -
* {@link GlobalOpenTelemetry#getTracer(String)}
*
*/
OpenTelemetryTracer(String libraryName, String libraryVersion, String azNamespace, TracingOptions options) {

TracerProvider otelProvider = getTracerProvider(options);
this.isEnabled = (options == null || options.isEnabled()) && otelProvider != TracerProvider.noop();
this.azNamespace = azNamespace;
this.tracer = otelProvider.tracerBuilder(libraryName)
.setInstrumentationVersion(libraryVersion)
.setSchemaUrl(SCHEMA_URL)
OpenTelemetryTracer(SdkTelemetryOptions sdkOptions, TracingOptions applicationOptions) {

TracerProvider otelProvider = getTracerProvider(applicationOptions);
this.isEnabled
= (applicationOptions == null || applicationOptions.isEnabled()) && otelProvider != TracerProvider.noop();
this.azNamespace = sdkOptions.getResourceProviderNamespace();
this.tracer = otelProvider.tracerBuilder(sdkOptions.getSdkName())
.setInstrumentationVersion(sdkOptions.getSdkVersion())
.setSchemaUrl(sdkOptions.getSchemaUrl() != null ? sdkOptions.getSchemaUrl() : DEFAULT_SCHEMA_URL)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.azure.core.tracing.opentelemetry;

import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.TracingOptions;
import com.azure.core.util.tracing.Tracer;
import com.azure.core.util.tracing.TracerProvider;
Expand All @@ -29,12 +30,29 @@ public OpenTelemetryTracerProvider() {
* @param libraryName Azure client library package name
* @param libraryVersion Azure client library version
* @param azNamespace Azure Resource Provider namespace.
* @param options instance of {@link com.azure.core.util.TracingOptions}
* @param applicationOptions instance of {@link com.azure.core.util.TracingOptions} passed by the application.
* @return a tracer instance.
*/
@Override
public Tracer createTracer(String libraryName, String libraryVersion, String azNamespace, TracingOptions options) {
public Tracer createTracer(String libraryName, String libraryVersion, String azNamespace,
TracingOptions applicationOptions) {
Objects.requireNonNull(libraryName, "'libraryName' cannot be null.");
return new OpenTelemetryTracer(libraryName, libraryVersion, azNamespace, options);

final SdkTelemetryOptions sdkOptions = new SdkTelemetryOptions().setSdkName(libraryName)
.setSdkVersion(libraryVersion)
.setResourceProviderNamespace(azNamespace);
return new OpenTelemetryTracer(sdkOptions, applicationOptions);
}

/**
* Creates OpenTelemetry-based implementation of {@link Tracer}
*
* @param sdkOptions Library-specific tracing options.
* @param applicationOptions Tracing options configured by the application.
* @return a tracer instance.
*/
@Override
public Tracer createTracer(SdkTelemetryOptions sdkOptions, TracingOptions applicationOptions) {
return new OpenTelemetryTracer(sdkOptions, applicationOptions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package com.azure.core.tracing.opentelemetry;

import com.azure.core.util.Context;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.tracing.Tracer;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
Expand All @@ -26,7 +27,7 @@ public class AmqpPropagationFormatUtilTest {
private static final SdkTracerProvider TRACER_PROVIDER = SdkTracerProvider.builder().build();
private static final OpenTelemetry OPEN_TELEMETRY
= OpenTelemetrySdk.builder().setTracerProvider(TRACER_PROVIDER).build();
private static final Tracer TRACER = new OpenTelemetryTracer("test", null, null,
private static final Tracer TRACER = new OpenTelemetryTracer(new SdkTelemetryOptions().setSdkName("test"),
new OpenTelemetryTracingOptions().setOpenTelemetry(OPEN_TELEMETRY));

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.azure.core.tracing.opentelemetry;

import com.azure.core.util.Context;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.tracing.Tracer;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.baggage.Baggage;
Expand Down Expand Up @@ -34,7 +35,7 @@ public class ContextPropagationTests {
private static final SdkTracerProvider TRACER_PROVIDER = SdkTracerProvider.builder().build();
private static final OpenTelemetry OPEN_TELEMETRY
= OpenTelemetrySdk.builder().setTracerProvider(TRACER_PROVIDER).build();
private static final Tracer TRACER = new OpenTelemetryTracer("test", null, null,
private static final Tracer TRACER = new OpenTelemetryTracer(new SdkTelemetryOptions().setSdkName("test"),
new OpenTelemetryTracingOptions().setOpenTelemetry(OPEN_TELEMETRY));

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
package com.azure.core.tracing.opentelemetry;

import com.azure.core.util.Context;
import com.azure.core.util.tracing.SpanKind;
import com.azure.core.util.tracing.StartSpanOptions;
import com.azure.core.util.SdkTelemetryOptions;
import com.azure.core.util.tracing.Tracer;
import com.azure.core.util.tracing.TracerProvider;
import io.opentelemetry.api.OpenTelemetry;
Expand Down Expand Up @@ -100,19 +99,14 @@ public void createTracerWithAzNamespaceInContext() {
public void defaultSchemaVersion() {
OpenTelemetryTracingOptions options = new OpenTelemetryTracingOptions().setOpenTelemetry(openTelemetry);

Tracer tracer = TracerProvider.getDefaultProvider().createTracer("test", null, null, options);

StartSpanOptions startSpanOptions
= new StartSpanOptions(SpanKind.PRODUCER).setAttribute("hostname", "addr").setAttribute("not-mapped", 42);
Tracer tracer
= TracerProvider.getDefaultProvider().createTracer(new SdkTelemetryOptions().setSdkName("test"), options);

Context span = tracer.start("test", startSpanOptions, Context.NONE);
tracer.setAttribute("entity-path", "foo", span);
Context span = tracer.start("test", Context.NONE);
tracer.end(null, null, span);

SpanData data = getSpanData(span);
assertEquals(3, data.getAttributes().size());
assertEquals("foo", data.getAttributes().get(AttributeKey.stringKey("messaging.destination.name")));
assertEquals("addr", data.getAttributes().get(AttributeKey.stringKey("server.address")));
assertEquals(42, data.getAttributes().get(AttributeKey.longKey("not-mapped")));
assertEquals("https://opentelemetry.io/schemas/1.23.1",
getSpanData(span).getInstrumentationScopeInfo().getSchemaUrl());
}

@Test
Expand Down Expand Up @@ -143,6 +137,25 @@ public void instrumentationScopeVersion() {
assertEquals("1.2.3-beta.45", readableSpan.getInstrumentationScopeInfo().getVersion());
}

@Test
public void testSdkOptions() {
OpenTelemetryTracingOptions options = new OpenTelemetryTracingOptions().setOpenTelemetry(openTelemetry);

SdkTelemetryOptions sdkOptions = new SdkTelemetryOptions().setSdkName("test")
.setSdkVersion("1.2.3-beta.45")
.setResourceProviderNamespace("namespace")
.setSchemaUrl("https://aka.ms/az/sdk/schema:1.42.0");

Tracer tracer = TracerProvider.getDefaultProvider().createTracer(sdkOptions, options);

Context span = tracer.start("test", Context.NONE);
ReadableSpan readableSpan = getReadableSpan(span);
assertEquals("test", readableSpan.getInstrumentationScopeInfo().getName());
assertEquals("https://aka.ms/az/sdk/schema:1.42.0", readableSpan.getInstrumentationScopeInfo().getSchemaUrl());
assertEquals("1.2.3-beta.45", readableSpan.getInstrumentationScopeInfo().getVersion());
assertEquals("namespace", readableSpan.getAttributes().get(AttributeKey.stringKey("az.namespace")));
}

private static SpanData getSpanData(Context context) {
return getReadableSpan(context).toSpanData();
}
Expand Down
Loading

0 comments on commit 5e93d11

Please sign in to comment.