diff --git a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java index a4156e0041..9c0d228594 100644 --- a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java +++ b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java @@ -19,6 +19,7 @@ package io.grpc.opentelemetry; import static com.google.common.base.Preconditions.checkNotNull; import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.METHOD_KEY; import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.STATUS_KEY; +import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.TARGET_KEY; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; @@ -97,8 +98,8 @@ final class OpenTelemetryMetricsModule { /** * Returns the client interceptor that facilitates OpenTelemetry metrics reporting. */ - ClientInterceptor getClientInterceptor() { - return new MetricsClientInterceptor(); + ClientInterceptor getClientInterceptor(String target) { + return new MetricsClientInterceptor(target); } static String recordMethodName(String fullMethodName, boolean isGeneratedMethod) { @@ -135,6 +136,7 @@ final class OpenTelemetryMetricsModule { final CallAttemptsTracerFactory attemptsState; final OpenTelemetryMetricsModule module; final StreamInfo info; + final String target; final String fullMethodName; volatile long outboundWireSize; volatile long inboundWireSize; @@ -142,10 +144,11 @@ final class OpenTelemetryMetricsModule { Code statusCode; ClientTracer(CallAttemptsTracerFactory attemptsState, OpenTelemetryMetricsModule module, - StreamInfo info, String fullMethodName) { + StreamInfo info, String target, String fullMethodName) { this.attemptsState = attemptsState; this.module = module; this.info = info; + this.target = target; this.fullMethodName = fullMethodName; this.stopwatch = module.stopwatchSupplier.get().start(); } @@ -189,9 +192,9 @@ final class OpenTelemetryMetricsModule { } void recordFinishedAttempt() { - // TODO(dnvindhya) : add target as an attribute io.opentelemetry.api.common.Attributes attribute = io.opentelemetry.api.common.Attributes.of(METHOD_KEY, fullMethodName, + TARGET_KEY, target, STATUS_KEY, statusCode.toString()); if (module.resource.clientAttemptDurationCounter() != null ) { @@ -212,6 +215,7 @@ final class OpenTelemetryMetricsModule { @VisibleForTesting static final class CallAttemptsTracerFactory extends ClientStreamTracer.Factory { private final OpenTelemetryMetricsModule module; + private final String target; private final Stopwatch attemptStopwatch; private final Stopwatch callStopWatch; @GuardedBy("lock") @@ -226,15 +230,17 @@ final class OpenTelemetryMetricsModule { @GuardedBy("lock") private boolean finishedCallToBeRecorded; - CallAttemptsTracerFactory(OpenTelemetryMetricsModule module, String fullMethodName) { + CallAttemptsTracerFactory( + OpenTelemetryMetricsModule module, String target, String fullMethodName) { this.module = checkNotNull(module, "module"); + this.target = checkNotNull(target, "target"); this.fullMethodName = checkNotNull(fullMethodName, "fullMethodName"); this.attemptStopwatch = module.stopwatchSupplier.get(); this.callStopWatch = module.stopwatchSupplier.get().start(); - // TODO(dnvindhya) : add target as an attribute - io.opentelemetry.api.common.Attributes attribute = - io.opentelemetry.api.common.Attributes.of(METHOD_KEY, fullMethodName); + io.opentelemetry.api.common.Attributes attribute = io.opentelemetry.api.common.Attributes.of( + METHOD_KEY, fullMethodName, + TARGET_KEY, target); // Record here in case mewClientStreamTracer() would never be called. if (module.resource.clientAttemptCountCounter() != null) { @@ -257,9 +263,9 @@ final class OpenTelemetryMetricsModule { // CallAttemptsTracerFactory constructor. attemptsPerCall will be non-zero after the first // attempt, as first attempt cannot be a transparent retry. if (attemptsPerCall.get() > 0) { - // TODO(dnvindhya): Add target as an attribute io.opentelemetry.api.common.Attributes attribute = - io.opentelemetry.api.common.Attributes.of(METHOD_KEY, fullMethodName); + io.opentelemetry.api.common.Attributes.of(METHOD_KEY, fullMethodName, + TARGET_KEY, target); if (module.resource.clientAttemptCountCounter() != null) { module.resource.clientAttemptCountCounter().add(1, attribute); } @@ -267,7 +273,7 @@ final class OpenTelemetryMetricsModule { if (!info.isTransparentRetry()) { attemptsPerCall.incrementAndGet(); } - return new ClientTracer(this, module, info, fullMethodName); + return new ClientTracer(this, module, info, target, fullMethodName); } // Called whenever each attempt is ended. @@ -309,15 +315,15 @@ final class OpenTelemetryMetricsModule { void recordFinishedCall() { if (attemptsPerCall.get() == 0) { - ClientTracer tracer = new ClientTracer(this, module, null, fullMethodName); + ClientTracer tracer = new ClientTracer(this, module, null, target, fullMethodName); tracer.attemptNanos = attemptStopwatch.elapsed(TimeUnit.NANOSECONDS); tracer.statusCode = status.getCode(); tracer.recordFinishedAttempt(); } callLatencyNanos = callStopWatch.elapsed(TimeUnit.NANOSECONDS); - // TODO(dnvindhya): record target as an attribute io.opentelemetry.api.common.Attributes attribute = io.opentelemetry.api.common.Attributes.of(METHOD_KEY, fullMethodName, + TARGET_KEY, target, STATUS_KEY, status.getCode().toString()); if (module.resource.clientCallDurationCounter() != null) { @@ -459,6 +465,12 @@ final class OpenTelemetryMetricsModule { @VisibleForTesting final class MetricsClientInterceptor implements ClientInterceptor { + private final String target; + + MetricsClientInterceptor(String target) { + this.target = checkNotNull(target, "target"); + } + @Override public ClientCall interceptCall( MethodDescriptor method, CallOptions callOptions, Channel next) { @@ -466,7 +478,7 @@ final class OpenTelemetryMetricsModule { // which is true for all generated methods. Otherwise, programatically // created methods result in high cardinality metrics. final CallAttemptsTracerFactory tracerFactory = new CallAttemptsTracerFactory( - OpenTelemetryMetricsModule.this, recordMethodName(method.getFullMethodName(), + OpenTelemetryMetricsModule.this, target, recordMethodName(method.getFullMethodName(), method.isSampledToLocalTracing())); ClientCall call = next.newCall(method, callOptions.withStreamTracerFactory(tracerFactory)); diff --git a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryModule.java b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryModule.java index 03a9cccbb9..3bb266699d 100644 --- a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryModule.java +++ b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryModule.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap; import io.grpc.ExperimentalApi; import io.grpc.InternalConfigurator; import io.grpc.InternalConfiguratorRegistry; +import io.grpc.InternalManagedChannelBuilder; import io.grpc.ManagedChannelBuilder; import io.grpc.MetricSink; import io.grpc.ServerBuilder; @@ -146,7 +147,8 @@ public final class OpenTelemetryModule { */ public void configureChannelBuilder(ManagedChannelBuilder builder) { builder.addMetricSink(sink); - builder.intercept(openTelemetryMetricsModule.getClientInterceptor()); + InternalManagedChannelBuilder.interceptWithTarget( + builder, openTelemetryMetricsModule::getClientInterceptor); } /** diff --git a/opentelemetry/src/test/java/io/grpc/opentelemetry/OpenTelemetryMetricsModuleTest.java b/opentelemetry/src/test/java/io/grpc/opentelemetry/OpenTelemetryMetricsModuleTest.java index 12c8e72f86..8304c13d58 100644 --- a/opentelemetry/src/test/java/io/grpc/opentelemetry/OpenTelemetryMetricsModuleTest.java +++ b/opentelemetry/src/test/java/io/grpc/opentelemetry/OpenTelemetryMetricsModuleTest.java @@ -19,6 +19,7 @@ package io.grpc.opentelemetry; import static io.grpc.ClientStreamTracer.NAME_RESOLUTION_DELAYED; import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.METHOD_KEY; import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.STATUS_KEY; +import static io.grpc.opentelemetry.internal.OpenTelemetryConstants.TARGET_KEY; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertEquals; @@ -185,7 +186,7 @@ public class OpenTelemetryMetricsModuleTest { Channel interceptedChannel = ClientInterceptors.intercept( grpcServerRule.getChannel(), callOptionsCatureInterceptor, - module.getClientInterceptor()); + module.getClientInterceptor("target:///")); ClientCall call; call = interceptedChannel.newCall(method, CALL_OPTIONS); @@ -211,16 +212,18 @@ public class OpenTelemetryMetricsModuleTest { @Test public void clientBasicMetrics() { + String target = "target:///"; OpenTelemetryMetricsResource resource = OpenTelemetryModule.createMetricInstruments(testMeter, enabledMetricsMap, disableDefaultMetrics); OpenTelemetryMetricsModule module = new OpenTelemetryMetricsModule(fakeClock.getStopwatchSupplier(), resource); OpenTelemetryMetricsModule.CallAttemptsTracerFactory callAttemptsTracerFactory = - new CallAttemptsTracerFactory(module, method.getFullMethodName()); + new CallAttemptsTracerFactory(module, target, method.getFullMethodName()); Metadata headers = new Metadata(); ClientStreamTracer tracer = callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, headers); io.opentelemetry.api.common.Attributes attributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName()); assertThat(openTelemetryTesting.getMetrics()) @@ -262,6 +265,7 @@ public class OpenTelemetryMetricsModuleTest { io.opentelemetry.api.common.Attributes clientAttributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName(), STATUS_KEY, Status.Code.OK.toString()); @@ -346,17 +350,19 @@ public class OpenTelemetryMetricsModuleTest { // This test is only unit-testing the metrics recording logic. The retry behavior is faked. @Test public void recordAttemptMetrics() { + String target = "dns:///example.com"; OpenTelemetryMetricsResource resource = OpenTelemetryModule.createMetricInstruments(testMeter, enabledMetricsMap, disableDefaultMetrics); OpenTelemetryMetricsModule module = new OpenTelemetryMetricsModule(fakeClock.getStopwatchSupplier(), resource); OpenTelemetryMetricsModule.CallAttemptsTracerFactory callAttemptsTracerFactory = - new OpenTelemetryMetricsModule.CallAttemptsTracerFactory(module, + new OpenTelemetryMetricsModule.CallAttemptsTracerFactory(module, target, method.getFullMethodName()); ClientStreamTracer tracer = callAttemptsTracerFactory.newClientStreamTracer(STREAM_INFO, new Metadata()); io.opentelemetry.api.common.Attributes attributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName()); assertThat(openTelemetryTesting.getMetrics()) @@ -387,6 +393,7 @@ public class OpenTelemetryMetricsModuleTest { io.opentelemetry.api.common.Attributes clientAttributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName(), STATUS_KEY, Code.UNAVAILABLE.toString()); @@ -467,6 +474,7 @@ public class OpenTelemetryMetricsModuleTest { io.opentelemetry.api.common.Attributes clientAttributes1 = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName(), STATUS_KEY, Code.NOT_FOUND.toString()); @@ -653,6 +661,7 @@ public class OpenTelemetryMetricsModuleTest { io.opentelemetry.api.common.Attributes clientAttributes2 = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName(), STATUS_KEY, Code.OK.toString()); @@ -767,12 +776,13 @@ public class OpenTelemetryMetricsModuleTest { @Test public void clientStreamNeverCreatedStillRecordMetrics() { + String target = "dns:///foo.example.com"; OpenTelemetryMetricsResource resource = OpenTelemetryModule.createMetricInstruments(testMeter, enabledMetricsMap, disableDefaultMetrics); OpenTelemetryMetricsModule module = new OpenTelemetryMetricsModule(fakeClock.getStopwatchSupplier(), resource); OpenTelemetryMetricsModule.CallAttemptsTracerFactory callAttemptsTracerFactory = - new OpenTelemetryMetricsModule.CallAttemptsTracerFactory(module, + new OpenTelemetryMetricsModule.CallAttemptsTracerFactory(module, target, method.getFullMethodName()); fakeClock.forwardTime(3000, MILLISECONDS); Status status = Status.DEADLINE_EXCEEDED.withDescription("5 seconds"); @@ -780,10 +790,12 @@ public class OpenTelemetryMetricsModuleTest { io.opentelemetry.api.common.Attributes attemptStartedAttributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName()); io.opentelemetry.api.common.Attributes clientAttributes = io.opentelemetry.api.common.Attributes.of( + TARGET_KEY, target, METHOD_KEY, method.getFullMethodName(), STATUS_KEY, Code.DEADLINE_EXCEEDED.toString());