census: APIs for stats and tracing (#12050) · grpc/grpc-java@9193701
1+/*
2+ * Copyright 2025 The gRPC Authors
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+17+package io.grpc.census;
18+19+import com.google.common.base.Stopwatch;
20+import com.google.common.base.Supplier;
21+import io.grpc.ClientInterceptor;
22+import io.grpc.ExperimentalApi;
23+import io.grpc.ManagedChannelBuilder;
24+import io.grpc.ServerBuilder;
25+import io.grpc.ServerStreamTracer;
26+import io.opencensus.trace.Tracing;
27+28+/**
29+ * The entrypoint for OpenCensus instrumentation functionality in gRPC.
30+ *
31+ * <p>GrpcCensus uses {@link io.opencensus.api.OpenCensus} APIs for instrumentation.
32+ *
33+ */
34+@ExperimentalApi("https://github.com/grpc/grpc-java/issues/12178")
35+public final class GrpcCensus {
36+37+private final boolean statsEnabled;
38+private final boolean tracingEnabled;
39+40+private GrpcCensus(Builder builder) {
41+this.statsEnabled = builder.statsEnabled;
42+this.tracingEnabled = builder.tracingEnabled;
43+ }
44+45+/**
46+ * Creates a new builder for {@link GrpcCensus}.
47+ */
48+public static Builder newBuilder() {
49+return new Builder();
50+ }
51+52+private static final Supplier<Stopwatch> STOPWATCH_SUPPLIER = new Supplier<Stopwatch>() {
53+@Override
54+public Stopwatch get() {
55+return Stopwatch.createUnstarted();
56+ }
57+ };
58+59+/**
60+ * Configures a {@link ServerBuilder} to enable census stats and tracing.
61+ *
62+ * @param serverBuilder The server builder to configure.
63+ * @return The configured server builder.
64+ */
65+public <T extends ServerBuilder<T>> T configureServerBuilder(T serverBuilder) {
66+if (statsEnabled) {
67+serverBuilder.addStreamTracerFactory(newServerStatsStreamTracerFactory());
68+ }
69+if (tracingEnabled) {
70+serverBuilder.addStreamTracerFactory(newServerTracingStreamTracerFactory());
71+ }
72+return serverBuilder;
73+ }
74+75+/**
76+ * Configures a {@link ManagedChannelBuilder} to enable census stats and tracing.
77+ *
78+ * @param channelBuilder The channel builder to configure.
79+ * @return The configured channel builder.
80+ */
81+public <T extends ManagedChannelBuilder<T>> T configureChannelBuilder(T channelBuilder) {
82+if (statsEnabled) {
83+channelBuilder.intercept(newClientStatsInterceptor());
84+ }
85+if (tracingEnabled) {
86+channelBuilder.intercept(newClientTracingInterceptor());
87+ }
88+return channelBuilder;
89+ }
90+91+/**
92+ * Returns a {@link ClientInterceptor} with default stats implementation.
93+ */
94+private static ClientInterceptor newClientStatsInterceptor() {
95+CensusStatsModule censusStats =
96+new CensusStatsModule(
97+STOPWATCH_SUPPLIER,
98+true,
99+true,
100+true,
101+false,
102+true);
103+return censusStats.getClientInterceptor();
104+ }
105+106+/**
107+ * Returns a {@link ClientInterceptor} with default tracing implementation.
108+ */
109+private static ClientInterceptor newClientTracingInterceptor() {
110+CensusTracingModule censusTracing =
111+new CensusTracingModule(
112+Tracing.getTracer(),
113+Tracing.getPropagationComponent().getBinaryFormat());
114+return censusTracing.getClientInterceptor();
115+ }
116+117+/**
118+ * Returns a {@link ServerStreamTracer.Factory} with default stats implementation.
119+ */
120+private static ServerStreamTracer.Factory newServerStatsStreamTracerFactory() {
121+CensusStatsModule censusStats =
122+new CensusStatsModule(
123+STOPWATCH_SUPPLIER,
124+true,
125+true,
126+true,
127+false,
128+true);
129+return censusStats.getServerTracerFactory();
130+ }
131+132+/**
133+ * Returns a {@link ServerStreamTracer.Factory} with default tracing implementation.
134+ */
135+private static ServerStreamTracer.Factory newServerTracingStreamTracerFactory() {
136+CensusTracingModule censusTracing =
137+new CensusTracingModule(
138+Tracing.getTracer(),
139+Tracing.getPropagationComponent().getBinaryFormat());
140+return censusTracing.getServerTracerFactory();
141+ }
142+143+/**
144+ * Builder for {@link GrpcCensus}.
145+ */
146+public static final class Builder {
147+private boolean statsEnabled = true;
148+private boolean tracingEnabled = true;
149+150+private Builder() {
151+ }
152+153+/**
154+ * Disables stats collection.
155+ */
156+public Builder disableStats() {
157+this.statsEnabled = false;
158+return this;
159+ }
160+161+/**
162+ * Disables tracing.
163+ */
164+public Builder disableTracing() {
165+this.tracingEnabled = false;
166+return this;
167+ }
168+169+/**
170+ * Builds a new {@link GrpcCensus}.
171+ */
172+public GrpcCensus build() {
173+return new GrpcCensus(this);
174+ }
175+ }
176+}