diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java index e6829be11cb..244d1a6d910 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java @@ -28,6 +28,7 @@ import com.google.auth.oauth2.OAuth2Credentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; import com.google.common.io.Files; import com.google.protobuf.ByteString; import io.grpc.CallOptions; @@ -57,6 +58,9 @@ import io.grpc.netty.NettyChannelBuilder; import io.grpc.okhttp.InternalOkHttpChannelBuilder; import io.grpc.okhttp.OkHttpChannelBuilder; +import io.grpc.opentelemetry.GrpcOpenTelemetry; +import io.grpc.opentelemetry.GrpcTraceBinContextPropagator; +import io.grpc.opentelemetry.InternalGrpcOpenTelemetry; import io.grpc.stub.ClientCalls; import io.grpc.stub.MetadataUtils; import io.grpc.stub.StreamObserver; @@ -68,6 +72,8 @@ import io.grpc.testing.integration.Messages.StreamingOutputCallRequest; import io.grpc.testing.integration.Messages.StreamingOutputCallResponse; import io.grpc.testing.integration.Messages.TestOrcaReport; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; @@ -136,7 +142,7 @@ public static void main(String[] args) throws Exception { private int soakResponseSize = 314159; private String additionalMetadata = ""; private static LoadBalancerProvider customBackendMetricsLoadBalancerProvider; - + private boolean useOpenTelemetryTracing; private Tester tester = new Tester(); @VisibleForTesting @@ -216,6 +222,8 @@ void parseArgs(String[] args) throws Exception { soakResponseSize = Integer.parseInt(value); } else if ("additional_metadata".equals(key)) { additionalMetadata = value; + } else if ("use_open_telemetry_tracing".equals(key)) { + useOpenTelemetryTracing = Boolean.parseBoolean(value); } else { System.err.println("Unknown argument: " + key); usage = true; @@ -294,6 +302,14 @@ void parseArgs(String[] args) throws Exception { + "\n Additional metadata to send in each request, as a " + "\n semicolon-separated list of key:value pairs. Default " + c.additionalMetadata + + "\n --use_open_telemetry_tracing " + + "\n Whether to use open telemetry tracing. Use otel " + + "\n AutoConfig to configure sdk. To use w3c, use" + + "\n '-Dotel.propagators=tracecontext'. If you do not " + + "\n specify otel.propagators system property, default " + + "\n propagator is grpc-trace-bin. Default " + + c.useOpenTelemetryTracing + ); System.exit(1); } @@ -678,6 +694,32 @@ protected ManagedChannelBuilder createChannelBuilder() { if (addMdInterceptor != null) { nettyBuilder.intercept(addMdInterceptor); } + if (useOpenTelemetryTracing) { + OpenTelemetrySdk openTelemetrySdk = AutoConfiguredOpenTelemetrySdk.builder() + .addPropagatorCustomizer((reader, config) -> { + if (config.getString("otel.propagators") == null) { + return GrpcTraceBinContextPropagator.defaultInstance(); + } else { + return reader; + } + }) + .addPropertiesSupplier(() -> ImmutableMap.of( + "otel.logs.exporter", "none", + "otel.traces.exporter", "none", + "otel.metrics.exporter", "none")) + .build() + .getOpenTelemetrySdk(); + + GrpcOpenTelemetry.Builder grpcOpentelemetryBuilder = GrpcOpenTelemetry.newBuilder() + .sdk(openTelemetrySdk); + InternalGrpcOpenTelemetry.enableTracing(grpcOpentelemetryBuilder, true); + GrpcOpenTelemetry grpcOpenTelemetry = grpcOpentelemetryBuilder.build(); + // Disabling census-tracing is necessary to avoid trace ID mismatches. + // This is because census-tracing overrides the grpc-trace-bin header with + // OpenTelemetry's GrpcTraceBinPropagator. + InternalNettyChannelBuilder.setTracingEnabled(nettyBuilder, false); + grpcOpenTelemetry.configureChannelBuilder(nettyBuilder); + } return nettyBuilder.intercept(createCensusStatsClientInterceptor()); } diff --git a/opentelemetry/src/main/java/io/grpc/opentelemetry/MetadataSetter.java b/opentelemetry/src/main/java/io/grpc/opentelemetry/MetadataSetter.java index 5892c7accfe..553e13e56f1 100644 --- a/opentelemetry/src/main/java/io/grpc/opentelemetry/MetadataSetter.java +++ b/opentelemetry/src/main/java/io/grpc/opentelemetry/MetadataSetter.java @@ -20,6 +20,7 @@ import com.google.common.io.BaseEncoding; import io.grpc.Metadata; import io.opentelemetry.context.propagation.TextMapSetter; +import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -40,6 +41,8 @@ public static MetadataSetter getInstance() { @Override public void set(@Nullable Metadata carrier, String key, String value) { + logger.log(Level.FINE, "Setting text trace header key={0} value={1}", + new Object[]{key, value}); if (carrier == null) { logger.log(Level.FINE, "Carrier is null, setting no data"); return; @@ -57,6 +60,8 @@ public void set(@Nullable Metadata carrier, String key, String value) { } void set(@Nullable Metadata carrier, String key, byte[] value) { + logger.log(Level.FINE, "Setting binary trace header key={0} value={1}", + new Object[]{key, Arrays.toString(value)}); if (carrier == null) { logger.log(Level.FINE, "Carrier is null, setting no data"); return;