• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20230

31 Mar 2026 09:55AM UTC coverage: 88.734% (+0.01%) from 88.72%
#20230

push

github

web-flow
openTelemetry: add tcp metrics (#12652)

Implements [A80](https://github.com/grpc/proposal/pull/519)

35697 of 40229 relevant lines covered (88.73%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.89
/../core/src/main/java/io/grpc/internal/ServerImplBuilder.java
1
/*
2
 * Copyright 2020 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.internal;
18

19
import static com.google.common.base.Preconditions.checkArgument;
20
import static com.google.common.base.Preconditions.checkNotNull;
21

22
import com.google.common.annotations.VisibleForTesting;
23
import com.google.common.util.concurrent.MoreExecutors;
24
import com.google.errorprone.annotations.DoNotCall;
25
import io.grpc.BinaryLog;
26
import io.grpc.BindableService;
27
import io.grpc.CompressorRegistry;
28
import io.grpc.Context;
29
import io.grpc.Deadline;
30
import io.grpc.DecompressorRegistry;
31
import io.grpc.HandlerRegistry;
32
import io.grpc.InternalChannelz;
33
import io.grpc.InternalConfiguratorRegistry;
34
import io.grpc.MetricInstrumentRegistry;
35
import io.grpc.MetricRecorder;
36
import io.grpc.MetricSink;
37
import io.grpc.Server;
38
import io.grpc.ServerBuilder;
39
import io.grpc.ServerCallExecutorSupplier;
40
import io.grpc.ServerInterceptor;
41
import io.grpc.ServerMethodDefinition;
42
import io.grpc.ServerServiceDefinition;
43
import io.grpc.ServerStreamTracer;
44
import io.grpc.ServerTransportFilter;
45
import java.io.File;
46
import java.lang.reflect.InvocationTargetException;
47
import java.lang.reflect.Method;
48
import java.util.ArrayList;
49
import java.util.Collections;
50
import java.util.List;
51
import java.util.concurrent.Executor;
52
import java.util.concurrent.TimeUnit;
53
import java.util.logging.Level;
54
import java.util.logging.Logger;
55
import javax.annotation.Nullable;
56

57
/**
58
 * Default builder for {@link io.grpc.Server} instances, for usage in Transport implementations.
59
 */
60
public final class ServerImplBuilder extends ServerBuilder<ServerImplBuilder> {
61

62
  private static final Logger log = Logger.getLogger(ServerImplBuilder.class.getName());
1✔
63

64
  @DoNotCall("ClientTransportServersBuilder is required, use a constructor")
65
  public static ServerBuilder<?> forPort(int port) {
66
    throw new UnsupportedOperationException(
×
67
        "ClientTransportServersBuilder is required, use a constructor");
68
  }
69

70
  // defaults
71
  private static final ObjectPool<? extends Executor> DEFAULT_EXECUTOR_POOL =
1✔
72
      SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
1✔
73
  private static final HandlerRegistry DEFAULT_FALLBACK_REGISTRY = new DefaultFallbackRegistry();
1✔
74
  private static final DecompressorRegistry DEFAULT_DECOMPRESSOR_REGISTRY =
75
      DecompressorRegistry.getDefaultInstance();
1✔
76
  private static final CompressorRegistry DEFAULT_COMPRESSOR_REGISTRY =
77
      CompressorRegistry.getDefaultInstance();
1✔
78
  private static final long DEFAULT_HANDSHAKE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(120);
1✔
79

80
  // mutable state
81
  final InternalHandlerRegistry.Builder registryBuilder =
1✔
82
      new InternalHandlerRegistry.Builder();
83
  final List<ServerTransportFilter> transportFilters = new ArrayList<>();
1✔
84
  final List<ServerInterceptor> interceptors = new ArrayList<>();
1✔
85
  private final List<ServerStreamTracer.Factory> streamTracerFactories = new ArrayList<>();
1✔
86
  final List<MetricSink> metricSinks = new ArrayList<>();
1✔
87
  private final ClientTransportServersBuilder clientTransportServersBuilder;
88
  HandlerRegistry fallbackRegistry = DEFAULT_FALLBACK_REGISTRY;
1✔
89
  ObjectPool<? extends Executor> executorPool = DEFAULT_EXECUTOR_POOL;
1✔
90
  DecompressorRegistry decompressorRegistry = DEFAULT_DECOMPRESSOR_REGISTRY;
1✔
91
  CompressorRegistry compressorRegistry = DEFAULT_COMPRESSOR_REGISTRY;
1✔
92
  long handshakeTimeoutMillis = DEFAULT_HANDSHAKE_TIMEOUT_MILLIS;
1✔
93
  Deadline.Ticker ticker = Deadline.getSystemTicker();
1✔
94
  private boolean statsEnabled = true;
1✔
95
  private boolean recordStartedRpcs = true;
1✔
96
  private boolean recordFinishedRpcs = true;
1✔
97
  private boolean recordRealTimeMetrics = false;
1✔
98
  private boolean tracingEnabled = true;
1✔
99
  @Nullable BinaryLog binlog;
100
  InternalChannelz channelz = InternalChannelz.instance();
1✔
101
  CallTracer.Factory callTracerFactory = CallTracer.getDefaultFactory();
1✔
102
  @Nullable
103
  ServerCallExecutorSupplier executorSupplier;
104

105
  /**
106
   * An interface to provide transport specific information for the server. This method
107
   * is meant for Transport implementors and should not be used by normal users.
108
   */
109
  public interface ClientTransportServersBuilder {
110
    InternalServer buildClientTransportServers(
111
        List<? extends ServerStreamTracer.Factory> streamTracerFactories,
112
        MetricRecorder metricRecorder);
113
  }
114

115
  /**
116
   * Creates a new server builder with given transport servers provider.
117
   */
118
  public ServerImplBuilder(ClientTransportServersBuilder clientTransportServersBuilder) {
1✔
119
    this.clientTransportServersBuilder = checkNotNull(clientTransportServersBuilder,
1✔
120
        "clientTransportServersBuilder");
121
    // TODO(dnvindhya): Move configurator to all the individual builders
122
    InternalConfiguratorRegistry.configureServerBuilder(this);
1✔
123
  }
1✔
124

125
  @Override
126
  public ServerImplBuilder directExecutor() {
127
    return executor(MoreExecutors.directExecutor());
1✔
128
  }
129

130
  @Override
131
  public ServerImplBuilder executor(@Nullable Executor executor) {
132
    this.executorPool = executor != null ? new FixedObjectPool<>(executor) : DEFAULT_EXECUTOR_POOL;
1✔
133
    return this;
1✔
134
  }
135

136
  @Override
137
  public ServerImplBuilder callExecutor(ServerCallExecutorSupplier executorSupplier) {
138
    this.executorSupplier = checkNotNull(executorSupplier);
×
139
    return this;
×
140
  }
141

142
  @Override
143
  public ServerImplBuilder addService(ServerServiceDefinition service) {
144
    registryBuilder.addService(checkNotNull(service, "service"));
1✔
145
    return this;
1✔
146
  }
147

148
  @Override
149
  public ServerImplBuilder addService(BindableService bindableService) {
150
    return addService(checkNotNull(bindableService, "bindableService").bindService());
1✔
151
  }
152

153
  @Override
154
  public ServerImplBuilder addTransportFilter(ServerTransportFilter filter) {
155
    transportFilters.add(checkNotNull(filter, "filter"));
1✔
156
    return this;
1✔
157
  }
158

159
  @Override
160
  public ServerImplBuilder intercept(ServerInterceptor interceptor) {
161
    interceptors.add(checkNotNull(interceptor, "interceptor"));
1✔
162
    return this;
1✔
163
  }
164

165
  /**
166
   * Adds a MetricSink to the server.
167
   */
168
  @Override
169
  public ServerImplBuilder addMetricSink(MetricSink metricSink) {
170
    metricSinks.add(checkNotNull(metricSink, "metricSink"));
1✔
171
    return this;
1✔
172
  }
173

174
  @Override
175
  public ServerImplBuilder addStreamTracerFactory(ServerStreamTracer.Factory factory) {
176
    streamTracerFactories.add(checkNotNull(factory, "factory"));
1✔
177
    return this;
1✔
178
  }
179

180
  @Override
181
  public ServerImplBuilder fallbackHandlerRegistry(@Nullable HandlerRegistry registry) {
182
    this.fallbackRegistry = registry != null ? registry : DEFAULT_FALLBACK_REGISTRY;
1✔
183
    return this;
1✔
184
  }
185

186
  @Override
187
  public ServerImplBuilder decompressorRegistry(@Nullable DecompressorRegistry registry) {
188
    this.decompressorRegistry = registry != null ? registry : DEFAULT_DECOMPRESSOR_REGISTRY;
1✔
189
    return this;
1✔
190
  }
191

192
  @Override
193
  public ServerImplBuilder compressorRegistry(@Nullable CompressorRegistry registry) {
194
    this.compressorRegistry = registry != null ? registry : DEFAULT_COMPRESSOR_REGISTRY;
1✔
195
    return this;
1✔
196
  }
197

198
  @Override
199
  public ServerImplBuilder handshakeTimeout(long timeout, TimeUnit unit) {
200
    checkArgument(timeout > 0, "handshake timeout is %s, but must be positive", timeout);
1✔
201
    this.handshakeTimeoutMillis = checkNotNull(unit, "unit").toMillis(timeout);
1✔
202
    return this;
1✔
203
  }
204

205
  @Override
206
  public ServerImplBuilder setBinaryLog(@Nullable BinaryLog binaryLog) {
207
    this.binlog = binaryLog;
×
208
    return this;
×
209
  }
210

211
  /**
212
   * Disable or enable stats features.  Enabled by default.
213
   */
214
  public void setStatsEnabled(boolean value) {
215
    this.statsEnabled = value;
1✔
216
  }
1✔
217

218
  /**
219
   * Disable or enable stats recording for RPC upstarts.  Effective only if {@link
220
   * #setStatsEnabled} is set to true.  Enabled by default.
221
   */
222
  public void setStatsRecordStartedRpcs(boolean value) {
223
    recordStartedRpcs = value;
1✔
224
  }
1✔
225

226
  /**
227
   * Disable or enable stats recording for RPC completions.  Effective only if {@link
228
   * #setStatsEnabled} is set to true.  Enabled by default.
229
   */
230
  public void setStatsRecordFinishedRpcs(boolean value) {
231
    recordFinishedRpcs = value;
1✔
232
  }
1✔
233

234
  /**
235
   * Disable or enable real-time metrics recording.  Effective only if {@link #setStatsEnabled} is
236
   * set to true.  Disabled by default.
237
   */
238
  public void setStatsRecordRealTimeMetrics(boolean value) {
239
    recordRealTimeMetrics = value;
×
240
  }
×
241

242
  /**
243
   * Disable or enable tracing features.  Enabled by default.
244
   */
245
  public void setTracingEnabled(boolean value) {
246
    tracingEnabled = value;
1✔
247
  }
1✔
248

249
  /**
250
   * Sets a custom deadline ticker.  This should only be called from InProcessServerBuilder.
251
   */
252
  public void setDeadlineTicker(Deadline.Ticker ticker) {
253
    this.ticker = checkNotNull(ticker, "ticker");
×
254
  }
×
255

256
  @Override
257
  public Server build() {
258
    MetricRecorder metricRecorder = new MetricRecorderImpl(metricSinks,
1✔
259
        MetricInstrumentRegistry.getDefaultRegistry());
1✔
260
    return new ServerImpl(this,
1✔
261
        clientTransportServersBuilder.buildClientTransportServers(
1✔
262
                getTracerFactories(), metricRecorder),
1✔
263
        Context.ROOT);
264
  }
265

266
  @VisibleForTesting
267
  List<? extends ServerStreamTracer.Factory> getTracerFactories() {
268
    boolean disableImplicitCensus = InternalConfiguratorRegistry.wasSetConfiguratorsCalled();
1✔
269
    if (disableImplicitCensus) {
1✔
270
      return streamTracerFactories;
×
271
    }
272
    ArrayList<ServerStreamTracer.Factory> tracerFactories = new ArrayList<>();
1✔
273
    if (statsEnabled) {
1✔
274
      ServerStreamTracer.Factory censusStatsTracerFactory = null;
1✔
275
      try {
276
        Class<?> censusStatsAccessor =
1✔
277
            Class.forName("io.grpc.census.InternalCensusStatsAccessor");
1✔
278
        Method getServerStreamTracerFactoryMethod =
1✔
279
            censusStatsAccessor.getDeclaredMethod(
1✔
280
                "getServerStreamTracerFactory",
281
                boolean.class,
282
                boolean.class,
283
                boolean.class);
284
        censusStatsTracerFactory =
1✔
285
            (ServerStreamTracer.Factory) getServerStreamTracerFactoryMethod
286
                .invoke(
1✔
287
                    null,
288
                    recordStartedRpcs,
1✔
289
                    recordFinishedRpcs,
1✔
290
                    recordRealTimeMetrics);
1✔
291
      } catch (ClassNotFoundException e) {
1✔
292
        // Replace these separate catch statements with multicatch when Android min-API >= 19
293
        log.log(Level.FINE, "Unable to apply census stats", e);
1✔
294
      } catch (NoSuchMethodException e) {
×
295
        log.log(Level.FINE, "Unable to apply census stats", e);
×
296
      } catch (IllegalAccessException e) {
×
297
        log.log(Level.FINE, "Unable to apply census stats", e);
×
298
      } catch (InvocationTargetException e) {
×
299
        log.log(Level.FINE, "Unable to apply census stats", e);
×
300
      }
1✔
301
      if (censusStatsTracerFactory != null) {
1✔
302
        tracerFactories.add(censusStatsTracerFactory);
1✔
303
      }
304
    }
305
    if (tracingEnabled) {
1✔
306
      ServerStreamTracer.Factory tracingStreamTracerFactory = null;
1✔
307
      try {
308
        Class<?> censusTracingAccessor =
1✔
309
            Class.forName("io.grpc.census.InternalCensusTracingAccessor");
1✔
310
        Method getServerStreamTracerFactoryMethod =
1✔
311
            censusTracingAccessor.getDeclaredMethod("getServerStreamTracerFactory");
1✔
312
        tracingStreamTracerFactory =
1✔
313
            (ServerStreamTracer.Factory) getServerStreamTracerFactoryMethod.invoke(null);
1✔
314
      } catch (ClassNotFoundException e) {
1✔
315
        // Replace these separate catch statements with multicatch when Android min-API >= 19
316
        log.log(Level.FINE, "Unable to apply census stats", e);
1✔
317
      } catch (NoSuchMethodException e) {
×
318
        log.log(Level.FINE, "Unable to apply census stats", e);
×
319
      } catch (IllegalAccessException e) {
×
320
        log.log(Level.FINE, "Unable to apply census stats", e);
×
321
      } catch (InvocationTargetException e) {
×
322
        log.log(Level.FINE, "Unable to apply census stats", e);
×
323
      }
1✔
324
      if (tracingStreamTracerFactory != null) {
1✔
325
        tracerFactories.add(tracingStreamTracerFactory);
1✔
326
      }
327
    }
328
    tracerFactories.addAll(streamTracerFactories);
1✔
329
    tracerFactories.trimToSize();
1✔
330
    return Collections.unmodifiableList(tracerFactories);
1✔
331
  }
332

333
  public InternalChannelz getChannelz() {
334
    return channelz;
1✔
335
  }
336

337
  private static final class DefaultFallbackRegistry extends HandlerRegistry {
338
    @Override
339
    public List<ServerServiceDefinition> getServices() {
340
      return Collections.emptyList();
1✔
341
    }
342

343
    @Nullable
344
    @Override
345
    public ServerMethodDefinition<?, ?> lookupMethod(
346
        String methodName, @Nullable String authority) {
347
      return null;
1✔
348
    }
349
  }
350

351
  /**
352
   * Returns the internal ExecutorPool for offloading tasks.
353
   */
354
  public ObjectPool<? extends Executor> getExecutorPool() {
355
    return this.executorPool;
1✔
356
  }
357

358
  @Override
359
  public ServerImplBuilder useTransportSecurity(File certChain, File privateKey) {
360
    throw new UnsupportedOperationException("TLS not supported in ServerImplBuilder");
×
361
  }
362
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc