diff --git a/android-interop-testing/app/build.gradle b/android-interop-testing/app/build.gradle index 16d0daf5f7..63ce33190b 100644 --- a/android-interop-testing/app/build.gradle +++ b/android-interop-testing/app/build.gradle @@ -73,6 +73,7 @@ dependencies { // You need to build grpc-java to obtain the grpc libraries below. implementation 'io.grpc:grpc-auth:1.27.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-census:1.27.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-okhttp:1.27.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-protobuf-lite:1.27.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-stub:1.27.0-SNAPSHOT' // CURRENT_GRPC_VERSION diff --git a/census/BUILD.bazel b/census/BUILD.bazel new file mode 100644 index 0000000000..c0bf29b3f3 --- /dev/null +++ b/census/BUILD.bazel @@ -0,0 +1,15 @@ +java_library( + name = "census", + srcs = glob([ + "src/main/java/**/*.java", + ]), + visibility = ["//visibility:public"], + deps = [ + "//api", + "//context", + "@com_google_code_findbugs_jsr305//jar", + "@com_google_guava_guava//jar", + "@io_opencensus_opencensus_api//jar", + "@io_opencensus_opencensus_contrib_grpc_metrics//jar", + ], +) diff --git a/census/build.gradle b/census/build.gradle new file mode 100644 index 0000000000..1c08390d18 --- /dev/null +++ b/census/build.gradle @@ -0,0 +1,43 @@ +plugins { + id "java" + id "maven-publish" +} + +description = 'gRPC: Census' + +evaluationDependsOn(project(':grpc-api').path) + +dependencies { + compile project(':grpc-api') + + compile (libraries.opencensus_api) { + // prefer 3.0.2 from libraries instead of 3.0.1 + exclude group: 'com.google.code.findbugs', module: 'jsr305' + // prefer 20.0 from libraries instead of 19.0 + exclude group: 'com.google.guava', module: 'guava' + // we'll always be more up-to-date + exclude group: 'io.grpc', module: 'grpc-context' + } + + compile (libraries.opencensus_contrib_grpc_metrics) { + // prefer 3.0.2 from libraries instead of 3.0.1 + exclude group: 'com.google.code.findbugs', module: 'jsr305' + // we'll always be more up-to-date + exclude group: 'io.grpc', module: 'grpc-context' + // prefer 20.0 from libraries instead of 19.0 + exclude group: 'com.google.guava', module: 'guava' + } + + testCompile project(':grpc-api').sourceSets.test.output, + project(':grpc-context').sourceSets.test.output, + project(':grpc-core').sourceSets.test.output, + project(':grpc-testing'), + libraries.guava_testlib, + libraries.opencensus_impl +} + +javadoc { + failOnError false // no public or protected classes found to document + exclude 'io/grpc/census/internal/**' + exclude 'io/grpc/census/Internal*' +} diff --git a/core/src/main/java/io/grpc/internal/CensusStatsModule.java b/census/src/main/java/io/grpc/census/CensusStatsModule.java similarity index 99% rename from core/src/main/java/io/grpc/internal/CensusStatsModule.java rename to census/src/main/java/io/grpc/census/CensusStatsModule.java index 17262a0655..d625a6f5c6 100644 --- a/core/src/main/java/io/grpc/internal/CensusStatsModule.java +++ b/census/src/main/java/io/grpc/census/CensusStatsModule.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.grpc.internal; +package io.grpc.census; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -35,6 +35,7 @@ import io.grpc.MethodDescriptor; import io.grpc.ServerStreamTracer; import io.grpc.Status; import io.grpc.StreamTracer; +import io.grpc.census.internal.DeprecatedCensusConstants; import io.opencensus.contrib.grpc.metrics.RpcMeasureConstants; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; @@ -67,7 +68,7 @@ import javax.annotation.Nullable; * starts earlier than the ServerCall. Therefore, only one tracer is created per stream/call and * it's the tracer that reports the summary to Census. */ -public final class CensusStatsModule { +final class CensusStatsModule { private static final Logger logger = Logger.getLogger(CensusStatsModule.class.getName()); private static final double NANOS_PER_MILLI = TimeUnit.MILLISECONDS.toNanos(1); @@ -98,7 +99,7 @@ public final class CensusStatsModule { /** * Creates a {@link CensusStatsModule} with the given OpenCensus implementation. */ - public CensusStatsModule( + CensusStatsModule( final Tagger tagger, final TagContextBinarySerializer tagCtxSerializer, StatsRecorder statsRecorder, Supplier stopwatchSupplier, diff --git a/core/src/main/java/io/grpc/internal/CensusTracingModule.java b/census/src/main/java/io/grpc/census/CensusTracingModule.java similarity index 99% rename from core/src/main/java/io/grpc/internal/CensusTracingModule.java rename to census/src/main/java/io/grpc/census/CensusTracingModule.java index b30c02d6ad..e9e12941ed 100644 --- a/core/src/main/java/io/grpc/internal/CensusTracingModule.java +++ b/census/src/main/java/io/grpc/census/CensusTracingModule.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.grpc.internal; +package io.grpc.census; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/census/src/main/java/io/grpc/census/InternalCensusStatsAccessor.java b/census/src/main/java/io/grpc/census/InternalCensusStatsAccessor.java new file mode 100644 index 0000000000..96be3258df --- /dev/null +++ b/census/src/main/java/io/grpc/census/InternalCensusStatsAccessor.java @@ -0,0 +1,117 @@ +/* + * Copyright 2019 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.census; + +import com.google.common.base.Stopwatch; +import com.google.common.base.Supplier; +import io.grpc.ClientInterceptor; +import io.grpc.Internal; +import io.grpc.ServerStreamTracer; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.tags.Tagger; +import io.opencensus.tags.propagation.TagContextBinarySerializer; + +/** + * Accessor for getting {@link ClientInterceptor} or {@link ServerStreamTracer.Factory} with + * default Census stats implementation. + */ +@Internal +public final class InternalCensusStatsAccessor { + + private static final Supplier STOPWATCH_SUPPLIER = new Supplier() { + @Override + public Stopwatch get() { + return Stopwatch.createUnstarted(); + } + }; + + // Prevent instantiation. + private InternalCensusStatsAccessor() { + } + + /** + * Returns a {@link ClientInterceptor} with default stats implementation. + */ + public static ClientInterceptor getClientInterceptor( + boolean recordStartedRpcs, + boolean recordFinishedRpcs, + boolean recordRealTimeMetrics) { + CensusStatsModule censusStats = + new CensusStatsModule( + STOPWATCH_SUPPLIER, + true, /* propagateTags */ + recordStartedRpcs, + recordFinishedRpcs, + recordRealTimeMetrics); + return censusStats.getClientInterceptor(); + } + + /** + * Returns a {@link ClientInterceptor} with custom stats implementation. + */ + public static ClientInterceptor getClientInterceptor( + Tagger tagger, + TagContextBinarySerializer tagCtxSerializer, + StatsRecorder statsRecorder, + Supplier stopwatchSupplier, + boolean propagateTags, + boolean recordStartedRpcs, + boolean recordFinishedRpcs, + boolean recordRealTimeMetrics) { + CensusStatsModule censusStats = + new CensusStatsModule( + tagger, tagCtxSerializer, statsRecorder, stopwatchSupplier, + propagateTags, recordStartedRpcs, recordFinishedRpcs, recordRealTimeMetrics); + return censusStats.getClientInterceptor(); + } + + /** + * Returns a {@link ServerStreamTracer.Factory} with default stats implementation. + */ + public static ServerStreamTracer.Factory getServerStreamTracerFactory( + boolean recordStartedRpcs, + boolean recordFinishedRpcs, + boolean recordRealTimeMetrics) { + CensusStatsModule censusStats = + new CensusStatsModule( + STOPWATCH_SUPPLIER, + true, /* propagateTags */ + recordStartedRpcs, + recordFinishedRpcs, + recordRealTimeMetrics); + return censusStats.getServerTracerFactory(); + } + + /** + * Returns a {@link ServerStreamTracer.Factory} with custom stats implementation. + */ + public static ServerStreamTracer.Factory getServerStreamTracerFactory( + Tagger tagger, + TagContextBinarySerializer tagCtxSerializer, + StatsRecorder statsRecorder, + Supplier stopwatchSupplier, + boolean propagateTags, + boolean recordStartedRpcs, + boolean recordFinishedRpcs, + boolean recordRealTimeMetrics) { + CensusStatsModule censusStats = + new CensusStatsModule( + tagger, tagCtxSerializer, statsRecorder, stopwatchSupplier, + propagateTags, recordStartedRpcs, recordFinishedRpcs, recordRealTimeMetrics); + return censusStats.getServerTracerFactory(); + } +} diff --git a/census/src/main/java/io/grpc/census/InternalCensusTracingAccessor.java b/census/src/main/java/io/grpc/census/InternalCensusTracingAccessor.java new file mode 100644 index 0000000000..2df6c5fb4b --- /dev/null +++ b/census/src/main/java/io/grpc/census/InternalCensusTracingAccessor.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.census; + +import io.grpc.ClientInterceptor; +import io.grpc.Internal; +import io.grpc.ServerStreamTracer; +import io.opencensus.trace.Tracing; + +/** + * Accessor for getting {@link ClientInterceptor} or {@link ServerStreamTracer.Factory} with + * default Census tracing implementation. + */ +@Internal +public final class InternalCensusTracingAccessor { + + // Prevent instantiation. + private InternalCensusTracingAccessor() { + } + + /** + * Returns a {@link ClientInterceptor} with default tracing implementation. + */ + public static ClientInterceptor getClientInterceptor() { + CensusTracingModule censusTracing = + new CensusTracingModule( + Tracing.getTracer(), + Tracing.getPropagationComponent().getBinaryFormat()); + return censusTracing.getClientInterceptor(); + } + + /** + * Returns a {@link ServerStreamTracer.Factory} with default stats implementation. + */ + public static ServerStreamTracer.Factory getServerStreamTracerFactory() { + CensusTracingModule censusTracing = + new CensusTracingModule( + Tracing.getTracer(), + Tracing.getPropagationComponent().getBinaryFormat()); + return censusTracing.getServerTracerFactory(); + } +} diff --git a/core/src/main/java/io/grpc/internal/DeprecatedCensusConstants.java b/census/src/main/java/io/grpc/census/internal/DeprecatedCensusConstants.java similarity index 99% rename from core/src/main/java/io/grpc/internal/DeprecatedCensusConstants.java rename to census/src/main/java/io/grpc/census/internal/DeprecatedCensusConstants.java index 76be69b053..2b0a4763a2 100644 --- a/core/src/main/java/io/grpc/internal/DeprecatedCensusConstants.java +++ b/census/src/main/java/io/grpc/census/internal/DeprecatedCensusConstants.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.grpc.internal; +package io.grpc.census.internal; import com.google.common.annotations.VisibleForTesting; import io.opencensus.contrib.grpc.metrics.RpcMeasureConstants; diff --git a/core/src/test/java/io/grpc/internal/CensusModulesTest.java b/census/src/test/java/io/grpc/census/CensusModulesTest.java similarity index 97% rename from core/src/test/java/io/grpc/internal/CensusModulesTest.java rename to census/src/test/java/io/grpc/census/CensusModulesTest.java index 9ceb063fb4..8187d38456 100644 --- a/core/src/test/java/io/grpc/internal/CensusModulesTest.java +++ b/census/src/test/java/io/grpc/census/CensusModulesTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.grpc.internal; +package io.grpc.census; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -56,7 +56,10 @@ import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.ServerServiceDefinition; import io.grpc.ServerStreamTracer; +import io.grpc.ServerStreamTracer.ServerCallInfo; import io.grpc.Status; +import io.grpc.census.internal.DeprecatedCensusConstants; +import io.grpc.internal.FakeClock; import io.grpc.internal.testing.StatsTestUtils; import io.grpc.internal.testing.StatsTestUtils.FakeStatsRecorder; import io.grpc.internal.testing.StatsTestUtils.FakeTagContextBinarySerializer; @@ -95,6 +98,7 @@ import java.util.List; import java.util.Random; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.Nullable; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -1044,7 +1048,7 @@ public class CensusModulesTest { assertSame(spyServerSpan, ContextUtils.getValue(filteredContext)); serverStreamTracer.serverCallStarted( - new ServerCallInfoImpl<>(method, Attributes.EMPTY, null)); + new CallInfo<>(method, Attributes.EMPTY, null)); verify(spyServerSpan, never()).end(any(EndSpanOptions.class)); @@ -1087,7 +1091,7 @@ public class CensusModulesTest { serverStreamTracer.filterContext(Context.ROOT); serverStreamTracer.serverCallStarted( - new ServerCallInfoImpl<>(sampledMethod, Attributes.EMPTY, null)); + new CallInfo<>(sampledMethod, Attributes.EMPTY, null)); serverStreamTracer.streamClosed(Status.CANCELLED); @@ -1250,8 +1254,39 @@ public class CensusModulesTest { new Function() { @Override public Long apply(AggregationData arg) { - return ((io.opencensus.stats.AggregationData.MeanData) arg).getCount(); + return ((AggregationData.MeanData) arg).getCount(); } }); } + + private static class CallInfo extends ServerCallInfo { + private final MethodDescriptor methodDescriptor; + private final Attributes attributes; + private final String authority; + + CallInfo( + MethodDescriptor methodDescriptor, + Attributes attributes, + @Nullable String authority) { + this.methodDescriptor = methodDescriptor; + this.attributes = attributes; + this.authority = authority; + } + + @Override + public MethodDescriptor getMethodDescriptor() { + return methodDescriptor; + } + + @Override + public Attributes getAttributes() { + return attributes; + } + + @Nullable + @Override + public String getAuthority() { + return authority; + } + } } diff --git a/core/BUILD.bazel b/core/BUILD.bazel index 5b4dbe8d52..c6e1ffbb6d 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -38,8 +38,6 @@ java_library( "@com_google_errorprone_error_prone_annotations//jar", "@com_google_guava_guava//jar", "@com_google_j2objc_j2objc_annotations//jar", - "@io_opencensus_opencensus_api//jar", - "@io_opencensus_opencensus_contrib_grpc_metrics//jar", "@io_perfmark_perfmark_api//jar", "@org_codehaus_mojo_animal_sniffer_annotations//jar", ], diff --git a/core/build.gradle b/core/build.gradle index ee12f834d9..e4a218cf3b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -20,25 +20,14 @@ dependencies { compile (libraries.perfmark) { exclude group: 'com.google.errorprone', module: 'error_prone_annotations' } - compile (libraries.opencensus_api) { - // prefer our own versions instead of opencensus-api's dependency - exclude group: 'com.google.code.findbugs', module: 'jsr305' - exclude group: 'com.google.guava', module: 'guava' - exclude group: 'io.grpc', module: 'grpc-context' - } - compile (libraries.opencensus_contrib_grpc_metrics) { - // prefer our own versions instead of opencensus-contrib's dependency - exclude group: 'com.google.code.findbugs', module: 'jsr305' - exclude group: 'io.grpc', module: 'grpc-context' - exclude group: 'com.google.guava', module: 'guava' - } testCompile project(':grpc-context').sourceSets.test.output, project(':grpc-api').sourceSets.test.output, project(':grpc-testing'), project(':grpc-grpclb'), - libraries.guava_testlib, - libraries.opencensus_impl + libraries.guava_testlib + + testRuntimeOnly project(':grpc-census') jmh project(':grpc-testing') diff --git a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java index 49c9fae24b..93883da921 100644 --- a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java @@ -33,7 +33,8 @@ import io.grpc.ManagedChannelBuilder; import io.grpc.NameResolver; import io.grpc.NameResolverRegistry; import io.grpc.ProxyDetector; -import io.opencensus.trace.Tracing; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.SocketAddress; import java.net.URI; import java.net.URISyntaxException; @@ -45,6 +46,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.Nullable; /** @@ -56,6 +59,9 @@ public abstract class AbstractManagedChannelImplBuilder > extends ManagedChannelBuilder { private static final String DIRECT_ADDRESS_SCHEME = "directaddress"; + private static final Logger log = + Logger.getLogger(AbstractManagedChannelImplBuilder.class.getName()); + public static ManagedChannelBuilder forAddress(String name, int port) { throw new UnsupportedOperationException("Subclass failed to hide static factory"); } @@ -184,9 +190,6 @@ public abstract class AbstractManagedChannelImplBuilder private boolean recordRealTimeMetrics = false; private boolean tracingEnabled = true; - @Nullable - private CensusStatsModule censusStatsOverride; - protected AbstractManagedChannelImplBuilder(String target) { this.target = Preconditions.checkNotNull(target, "target"); this.directServerAddress = null; @@ -376,15 +379,6 @@ public abstract class AbstractManagedChannelImplBuilder return thisT(); } - /** - * Override the default stats implementation. - */ - @VisibleForTesting - protected final T overrideCensusStatsModule(CensusStatsModule censusStats) { - this.censusStatsOverride = censusStats; - return thisT(); - } - @Override public T proxyDetector(@Nullable ProxyDetector proxyDetector) { this.proxyDetector = proxyDetector; @@ -565,22 +559,49 @@ public abstract class AbstractManagedChannelImplBuilder temporarilyDisableRetry = false; if (statsEnabled) { temporarilyDisableRetry = true; - CensusStatsModule censusStats = this.censusStatsOverride; - if (censusStats == null) { - censusStats = new CensusStatsModule( - GrpcUtil.STOPWATCH_SUPPLIER, true, recordStartedRpcs, recordFinishedRpcs, - recordRealTimeMetrics); + ClientInterceptor statsInterceptor = null; + try { + Class censusStatsAccessor = + Class.forName("io.grpc.census.InternalCensusStatsAccessor"); + Method getClientInterceptorMethod = + censusStatsAccessor.getDeclaredMethod( + "getClientInterceptor", + boolean.class, + boolean.class, + boolean.class); + statsInterceptor = + (ClientInterceptor) getClientInterceptorMethod + .invoke( + null, + recordStartedRpcs, + recordFinishedRpcs, + recordRealTimeMetrics); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException + | InvocationTargetException e) { + log.log(Level.FINE, "Unable to apply census stats", e); + } + if (statsInterceptor != null) { + // First interceptor runs last (see ClientInterceptors.intercept()), so that no + // other interceptor can override the tracer factory we set in CallOptions. + effectiveInterceptors.add(0, statsInterceptor); } - // First interceptor runs last (see ClientInterceptors.intercept()), so that no - // other interceptor can override the tracer factory we set in CallOptions. - effectiveInterceptors.add(0, censusStats.getClientInterceptor()); } if (tracingEnabled) { temporarilyDisableRetry = true; - CensusTracingModule censusTracing = - new CensusTracingModule(Tracing.getTracer(), - Tracing.getPropagationComponent().getBinaryFormat()); - effectiveInterceptors.add(0, censusTracing.getClientInterceptor()); + ClientInterceptor tracingInterceptor = null; + try { + Class censusTracingAccessor = + Class.forName("io.grpc.census.InternalCensusTracingAccessor"); + Method getClientInterceptroMethod = + censusTracingAccessor.getDeclaredMethod("getClientInterceptor"); + tracingInterceptor = (ClientInterceptor) getClientInterceptroMethod.invoke(null); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException + | InvocationTargetException e) { + log.log(Level.FINE, "Unable to apply census tracing", e); + } + if (tracingInterceptor != null) { + effectiveInterceptors.add(0, tracingInterceptor); + } } return effectiveInterceptors; } diff --git a/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java index 3b2bed6049..ff151d1a6d 100644 --- a/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java @@ -37,12 +37,15 @@ import io.grpc.ServerMethodDefinition; import io.grpc.ServerServiceDefinition; import io.grpc.ServerStreamTracer; import io.grpc.ServerTransportFilter; -import io.opencensus.trace.Tracing; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.Nullable; /** @@ -53,6 +56,8 @@ import javax.annotation.Nullable; public abstract class AbstractServerImplBuilder> extends ServerBuilder { + private static final Logger log = Logger.getLogger(AbstractServerImplBuilder.class.getName()); + public static ServerBuilder forPort(int port) { throw new UnsupportedOperationException("Subclass failed to hide static factory"); } @@ -80,7 +85,6 @@ public abstract class AbstractServerImplBuilder getTracerFactories() { ArrayList tracerFactories = new ArrayList<>(); if (statsEnabled) { - CensusStatsModule censusStats = censusStatsOverride; - if (censusStats == null) { - censusStats = new CensusStatsModule( - GrpcUtil.STOPWATCH_SUPPLIER, true, recordStartedRpcs, recordFinishedRpcs, - recordRealTimeMetrics); + ServerStreamTracer.Factory censusStatsTracerFactory = null; + try { + Class censusStatsAccessor = + Class.forName("io.grpc.census.InternalCensusStatsAccessor"); + Method getServerStreamTracerFactoryMethod = + censusStatsAccessor.getDeclaredMethod( + "getServerStreamTracerFactory", + boolean.class, + boolean.class, + boolean.class); + censusStatsTracerFactory = + (ServerStreamTracer.Factory) getServerStreamTracerFactoryMethod + .invoke( + null, + recordStartedRpcs, + recordFinishedRpcs, + recordRealTimeMetrics); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException + | InvocationTargetException e) { + log.log(Level.FINE, "Unable to apply census stats", e); + } + if (censusStatsTracerFactory != null) { + tracerFactories.add(censusStatsTracerFactory); } - tracerFactories.add(censusStats.getServerTracerFactory()); } if (tracingEnabled) { - CensusTracingModule censusTracing = - new CensusTracingModule(Tracing.getTracer(), - Tracing.getPropagationComponent().getBinaryFormat()); - tracerFactories.add(censusTracing.getServerTracerFactory()); + ServerStreamTracer.Factory tracingStreamTracerFactory = null; + try { + Class censusTracingAccessor = + Class.forName("io.grpc.census.InternalCensusTracingAccessor"); + Method getServerStreamTracerFactoryMethod = + censusTracingAccessor.getDeclaredMethod("getServerStreamTracerFactory"); + tracingStreamTracerFactory = + (ServerStreamTracer.Factory) getServerStreamTracerFactoryMethod.invoke(null); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException + | InvocationTargetException e) { + log.log(Level.FINE, "Unable to apply census tracing", e); + } + if (tracingStreamTracerFactory != null) { + tracerFactories.add(tracingStreamTracerFactory); + } } tracerFactories.addAll(streamTracerFactories); tracerFactories.trimToSize(); diff --git a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java index 371fbd6748..1a39671af5 100644 --- a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java +++ b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java @@ -36,9 +36,6 @@ import io.grpc.CompressorRegistry; import io.grpc.DecompressorRegistry; import io.grpc.MethodDescriptor; import io.grpc.NameResolver; -import io.grpc.internal.testing.StatsTestUtils.FakeStatsRecorder; -import io.grpc.internal.testing.StatsTestUtils.FakeTagContextBinarySerializer; -import io.grpc.internal.testing.StatsTestUtils.FakeTagger; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.URI; @@ -284,10 +281,10 @@ public class AbstractManagedChannelImplBuilderTest { builder.intercept(DUMMY_USER_INTERCEPTOR); List effectiveInterceptors = builder.getEffectiveInterceptors(); assertEquals(3, effectiveInterceptors.size()); - assertThat(effectiveInterceptors.get(0)) - .isInstanceOf(CensusTracingModule.TracingClientInterceptor.class); - assertThat(effectiveInterceptors.get(1)) - .isInstanceOf(CensusStatsModule.StatsClientInterceptor.class); + assertThat(effectiveInterceptors.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor"); + assertThat(effectiveInterceptors.get(1).getClass().getName()) + .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor"); assertThat(effectiveInterceptors.get(2)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR); } @@ -297,8 +294,8 @@ public class AbstractManagedChannelImplBuilderTest { builder.setStatsEnabled(false); List effectiveInterceptors = builder.getEffectiveInterceptors(); assertEquals(2, effectiveInterceptors.size()); - assertThat(effectiveInterceptors.get(0)) - .isInstanceOf(CensusTracingModule.TracingClientInterceptor.class); + assertThat(effectiveInterceptors.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusTracingModule$TracingClientInterceptor"); assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR); } @@ -308,8 +305,8 @@ public class AbstractManagedChannelImplBuilderTest { builder.setTracingEnabled(false); List effectiveInterceptors = builder.getEffectiveInterceptors(); assertEquals(2, effectiveInterceptors.size()); - assertThat(effectiveInterceptors.get(0)) - .isInstanceOf(CensusStatsModule.StatsClientInterceptor.class); + assertThat(effectiveInterceptors.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusStatsModule$StatsClientInterceptor"); assertThat(effectiveInterceptors.get(1)).isSameInstanceAs(DUMMY_USER_INTERCEPTOR); } @@ -500,24 +497,10 @@ public class AbstractManagedChannelImplBuilderTest { static class Builder extends AbstractManagedChannelImplBuilder { Builder(String target) { super(target); - overrideCensusStatsModule( - new CensusStatsModule( - new FakeTagger(), - new FakeTagContextBinarySerializer(), - new FakeStatsRecorder(), - GrpcUtil.STOPWATCH_SUPPLIER, - true, true, true, true)); } Builder(SocketAddress directServerAddress, String authority) { super(directServerAddress, authority); - overrideCensusStatsModule( - new CensusStatsModule( - new FakeTagger(), - new FakeTagContextBinarySerializer(), - new FakeStatsRecorder(), - GrpcUtil.STOPWATCH_SUPPLIER, - true, true, true, true)); } @Override diff --git a/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java index 0021d9224d..77aced7826 100644 --- a/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java +++ b/core/src/test/java/io/grpc/internal/AbstractServerImplBuilderTest.java @@ -21,9 +21,6 @@ import static org.junit.Assert.assertEquals; import io.grpc.Metadata; import io.grpc.ServerStreamTracer; -import io.grpc.internal.testing.StatsTestUtils.FakeStatsRecorder; -import io.grpc.internal.testing.StatsTestUtils.FakeTagContextBinarySerializer; -import io.grpc.internal.testing.StatsTestUtils.FakeTagger; import java.io.File; import java.util.List; import org.junit.Test; @@ -51,8 +48,10 @@ public class AbstractServerImplBuilderTest { List factories = builder.getTracerFactories(); assertEquals(3, factories.size()); - assertThat(factories.get(0)).isInstanceOf(CensusStatsModule.ServerTracerFactory.class); - assertThat(factories.get(1)).isInstanceOf(CensusTracingModule.ServerTracerFactory.class); + assertThat(factories.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusStatsModule$ServerTracerFactory"); + assertThat(factories.get(1).getClass().getName()) + .isEqualTo("io.grpc.census.CensusTracingModule$ServerTracerFactory"); assertThat(factories.get(2)).isSameInstanceAs(DUMMY_USER_TRACER); } @@ -64,7 +63,8 @@ public class AbstractServerImplBuilderTest { List factories = builder.getTracerFactories(); assertEquals(2, factories.size()); - assertThat(factories.get(0)).isInstanceOf(CensusTracingModule.ServerTracerFactory.class); + assertThat(factories.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusTracingModule$ServerTracerFactory"); assertThat(factories.get(1)).isSameInstanceAs(DUMMY_USER_TRACER); } @@ -76,7 +76,8 @@ public class AbstractServerImplBuilderTest { List factories = builder.getTracerFactories(); assertEquals(2, factories.size()); - assertThat(factories.get(0)).isInstanceOf(CensusStatsModule.ServerTracerFactory.class); + assertThat(factories.get(0).getClass().getName()) + .isEqualTo("io.grpc.census.CensusStatsModule$ServerTracerFactory"); assertThat(factories.get(1)).isSameInstanceAs(DUMMY_USER_TRACER); } @@ -90,15 +91,6 @@ public class AbstractServerImplBuilderTest { } static class Builder extends AbstractServerImplBuilder { - Builder() { - overrideCensusStatsModule( - new CensusStatsModule( - new FakeTagger(), - new FakeTagContextBinarySerializer(), - new FakeStatsRecorder(), - GrpcUtil.STOPWATCH_SUPPLIER, - true, true, true, true)); - } @Override protected List buildTransportServers( diff --git a/interop-testing/build.gradle b/interop-testing/build.gradle index b11ed26ebc..169007e517 100644 --- a/interop-testing/build.gradle +++ b/interop-testing/build.gradle @@ -18,6 +18,7 @@ evaluationDependsOn(project(':grpc-context').path) dependencies { compile project(':grpc-alts'), project(':grpc-auth'), + project(':grpc-census'), project(':grpc-core'), project(':grpc-netty'), project(':grpc-okhttp'), diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java index 65274cad70..dc8819eaf9 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractInteropTest.java @@ -61,9 +61,9 @@ import io.grpc.ServerStreamTracer; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.auth.MoreCallCredentials; +import io.grpc.census.InternalCensusStatsAccessor; +import io.grpc.census.internal.DeprecatedCensusConstants; import io.grpc.internal.AbstractServerImplBuilder; -import io.grpc.internal.CensusStatsModule; -import io.grpc.internal.DeprecatedCensusConstants; import io.grpc.internal.GrpcUtil; import io.grpc.internal.testing.StatsTestUtils; import io.grpc.internal.testing.StatsTestUtils.FakeStatsRecorder; @@ -240,15 +240,15 @@ public abstract class AbstractInteropTest { .addStreamTracerFactory(serverStreamTracerFactory); if (builder instanceof AbstractServerImplBuilder) { customCensusModulePresent = true; + ServerStreamTracer.Factory censusTracerFactory = + InternalCensusStatsAccessor + .getServerStreamTracerFactory( + tagger, tagContextBinarySerializer, serverStatsRecorder, + GrpcUtil.STOPWATCH_SUPPLIER, + true, true, true, false /* real-time metrics */); AbstractServerImplBuilder sb = (AbstractServerImplBuilder) builder; - io.grpc.internal.TestingAccessor.setStatsImplementation( - sb, - new CensusStatsModule( - tagger, - tagContextBinarySerializer, - serverStatsRecorder, - GrpcUtil.STOPWATCH_SUPPLIER, - true, true, true, false /* real-time metrics */)); + io.grpc.internal.TestingAccessor.setStatsEnabled(sb, false); + sb.addStreamTracerFactory(censusTracerFactory); } if (metricsExpected()) { assertThat(builder).isInstanceOf(AbstractServerImplBuilder.class); @@ -353,10 +353,13 @@ public abstract class AbstractInteropTest { return null; } - protected final CensusStatsModule createClientCensusStatsModule() { - return new CensusStatsModule( - tagger, tagContextBinarySerializer, clientStatsRecorder, GrpcUtil.STOPWATCH_SUPPLIER, - true, true, true, false /* real-time metrics */); + protected final ClientInterceptor createCensusStatsClientInterceptor() { + return + InternalCensusStatsAccessor + .getClientInterceptor( + tagger, tagContextBinarySerializer, clientStatsRecorder, + GrpcUtil.STOPWATCH_SUPPLIER, + true, true, true, false /* real-time metrics */); } /** 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 486c518941..714306f92b 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 @@ -450,9 +450,9 @@ public class TestServiceClient { } builder = okBuilder; } - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } @Override diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/AutoWindowSizingOnTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/AutoWindowSizingOnTest.java index 1260966674..462ad480a4 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/AutoWindowSizingOnTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/AutoWindowSizingOnTest.java @@ -46,8 +46,8 @@ public class AutoWindowSizingOnTest extends AbstractInteropTest { NettyChannelBuilder builder = NettyChannelBuilder.forAddress(getListenAddress()) .negotiationType(NegotiationType.PLAINTEXT) .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } } diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java index 0410a7281b..d934621f74 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java @@ -57,9 +57,9 @@ public class Http2NettyLocalChannelTest extends AbstractInteropTest { .eventLoopGroup(eventLoopGroup) .flowControlWindow(65 * 1024) .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } @Override diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java index 74c5147cc4..76726d1802 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java @@ -71,9 +71,9 @@ public class Http2NettyTest extends AbstractInteropTest { .trustManager(TestUtils.loadX509Cert("ca.pem")) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE) .build()); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } catch (Exception ex) { throw new RuntimeException(ex); } diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java index 4830fa9014..927b0ed447 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java @@ -100,15 +100,15 @@ public class Http2OkHttpTest extends AbstractInteropTest { .build()) .overrideAuthority(GrpcUtil.authorityFromHostAndPort( TestUtils.TEST_SERVER_HOST, port)); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); try { builder.sslSocketFactory(TestUtils.newSslSocketFactoryForCa(Platform.get().getProvider(), TestUtils.loadCert("ca.pem"))); } catch (Exception e) { throw new RuntimeException(e); } - return builder; + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()); } @Test diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java index 32c753b207..3592f4b96b 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java @@ -38,9 +38,9 @@ public class InProcessTest extends AbstractInteropTest { @Override protected ManagedChannel createChannel() { InProcessChannelBuilder builder = InProcessChannelBuilder.forName(SERVER_NAME); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } @Override diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/TransportCompressionTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/TransportCompressionTest.java index e99ba561b2..a776a83121 100644 --- a/interop-testing/src/test/java/io/grpc/testing/integration/TransportCompressionTest.java +++ b/interop-testing/src/test/java/io/grpc/testing/integration/TransportCompressionTest.java @@ -165,9 +165,9 @@ public class TransportCompressionTest extends AbstractInteropTest { } }) .usePlaintext(); - io.grpc.internal.TestingAccessor.setStatsImplementation( - builder, createClientCensusStatsModule()); - return builder.build(); + // Disable the default census stats interceptor, use testing interceptor instead. + io.grpc.internal.TestingAccessor.setStatsEnabled(builder, false); + return builder.intercept(createCensusStatsClientInterceptor()).build(); } /** diff --git a/repositories.bzl b/repositories.bzl index 3f129cadb4..78cdf086f3 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -70,6 +70,7 @@ IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS = { "io.grpc:grpc-alts": "@io_grpc_grpc_java//alts", "io.grpc:grpc-api": "@io_grpc_grpc_java//api", "io.grpc:grpc-auth": "@io_grpc_grpc_java//auth", + "io.grpc:grpc-census": "@io_grpc_grpc_java//census", "io.grpc:grpc-context": "@io_grpc_grpc_java//context", "io.grpc:grpc-core": "@io_grpc_grpc_java//core:core_maven", "io.grpc:grpc-grpclb": "@io_grpc_grpc_java//grpclb", diff --git a/settings.gradle b/settings.gradle index 0ce56b202c..7881b4e80c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,6 +29,7 @@ include ":grpc-api" include ":grpc-core" include ":grpc-context" include ":grpc-stub" +include ":grpc-census" include ":grpc-auth" include ":grpc-okhttp" include ":grpc-protobuf" @@ -51,6 +52,7 @@ project(':grpc-api').projectDir = "$rootDir/api" as File project(':grpc-core').projectDir = "$rootDir/core" as File project(':grpc-context').projectDir = "$rootDir/context" as File project(':grpc-stub').projectDir = "$rootDir/stub" as File +project(':grpc-census').projectDir = "$rootDir/census" as File project(':grpc-auth').projectDir = "$rootDir/auth" as File project(':grpc-okhttp').projectDir = "$rootDir/okhttp" as File project(':grpc-protobuf').projectDir = "$rootDir/protobuf" as File diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel index 09d0796fa4..f1e9a5743e 100644 --- a/testing/BUILD.bazel +++ b/testing/BUILD.bazel @@ -31,5 +31,6 @@ java_library( deps = [ "//api", "//core:internal", + "@io_opencensus_opencensus_api//jar", ], ) diff --git a/testing/build.gradle b/testing/build.gradle index 619f13e7d7..7365d7d53f 100644 --- a/testing/build.gradle +++ b/testing/build.gradle @@ -14,6 +14,15 @@ dependencies { project(':grpc-stub'), libraries.junit + compile (libraries.opencensus_api) { + // prefer 3.0.2 from libraries instead of 3.0.1 + exclude group: 'com.google.code.findbugs', module: 'jsr305' + // prefer 20.0 from libraries instead of 19.0 + exclude group: 'com.google.guava', module: 'guava' + // we'll always be more up-to-date + exclude group: 'io.grpc', module: 'grpc-context' + } + testCompile (libraries.mockito) { // prefer our own versions instead of mockito's dependency exclude group: 'org.hamcrest', module: 'hamcrest-core' diff --git a/testing/src/main/java/io/grpc/internal/TestingAccessor.java b/testing/src/main/java/io/grpc/internal/TestingAccessor.java index 4c994299b8..d5b00e025f 100644 --- a/testing/src/main/java/io/grpc/internal/TestingAccessor.java +++ b/testing/src/main/java/io/grpc/internal/TestingAccessor.java @@ -21,19 +21,20 @@ package io.grpc.internal; */ public final class TestingAccessor { /** - * Sets a custom stats implementation for tests. + * Disable or enable client side census stats features. */ - public static void setStatsImplementation( - AbstractManagedChannelImplBuilder builder, CensusStatsModule censusStats) { - builder.overrideCensusStatsModule(censusStats); + public static void setStatsEnabled( + AbstractManagedChannelImplBuilder builder, boolean statsEnabled) { + builder.setStatsEnabled(statsEnabled); } /** - * Sets a custom stats implementation for tests. + * Disable or enable server side census stats features. */ - public static void setStatsImplementation( - AbstractServerImplBuilder builder, CensusStatsModule censusStats) { - builder.overrideCensusStatsModule(censusStats); + public static void setStatsEnabled( + AbstractServerImplBuilder builder, + boolean statsEnabled) { + builder.setStatsEnabled(statsEnabled); } private TestingAccessor() {