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

grpc / grpc-java / #19213

08 May 2024 11:23PM UTC coverage: 88.329% (-0.006%) from 88.335%
#19213

push

github

ejona86
Migrate GlobalInterceptors to ConfiguratorRegistry

This should preserve all the existing behavior of GlobalInterceptors as
used by grpc-gcp-observability, including it disabling the implicit
OpenCensus integration.

Both the old and new API are internal. I hid Configurator and
ConfiguratorRegistry behind Internal-prefixed classes, like had been
done with GlobalInterceptors to further discourage use until the API is
ready.

GlobalInterceptorsTest was modified to become ConfiguratorRegistryTest.

31506 of 35669 relevant lines covered (88.33%)

0.88 hits per line

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

80.99
/../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.Server;
35
import io.grpc.ServerBuilder;
36
import io.grpc.ServerCallExecutorSupplier;
37
import io.grpc.ServerInterceptor;
38
import io.grpc.ServerMethodDefinition;
39
import io.grpc.ServerServiceDefinition;
40
import io.grpc.ServerStreamTracer;
41
import io.grpc.ServerTransportFilter;
42
import java.io.File;
43
import java.lang.reflect.InvocationTargetException;
44
import java.lang.reflect.Method;
45
import java.util.ArrayList;
46
import java.util.Collections;
47
import java.util.List;
48
import java.util.concurrent.Executor;
49
import java.util.concurrent.TimeUnit;
50
import java.util.logging.Level;
51
import java.util.logging.Logger;
52
import javax.annotation.Nullable;
53

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

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

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

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

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

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

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

120
  @Override
121
  public ServerImplBuilder directExecutor() {
122
    return executor(MoreExecutors.directExecutor());
1✔
123
  }
124

125
  @Override
126
  public ServerImplBuilder executor(@Nullable Executor executor) {
127
    this.executorPool = executor != null ? new FixedObjectPool<>(executor) : DEFAULT_EXECUTOR_POOL;
1✔
128
    return this;
1✔
129
  }
130

131
  @Override
132
  public ServerImplBuilder callExecutor(ServerCallExecutorSupplier executorSupplier) {
133
    this.executorSupplier = checkNotNull(executorSupplier);
×
134
    return this;
×
135
  }
136

137
  @Override
138
  public ServerImplBuilder addService(ServerServiceDefinition service) {
139
    registryBuilder.addService(checkNotNull(service, "service"));
1✔
140
    return this;
1✔
141
  }
142

143
  @Override
144
  public ServerImplBuilder addService(BindableService bindableService) {
145
    return addService(checkNotNull(bindableService, "bindableService").bindService());
1✔
146
  }
147

148
  @Override
149
  public ServerImplBuilder addTransportFilter(ServerTransportFilter filter) {
150
    transportFilters.add(checkNotNull(filter, "filter"));
1✔
151
    return this;
1✔
152
  }
153

154
  @Override
155
  public ServerImplBuilder intercept(ServerInterceptor interceptor) {
156
    interceptors.add(checkNotNull(interceptor, "interceptor"));
1✔
157
    return this;
1✔
158
  }
159

160
  @Override
161
  public ServerImplBuilder addStreamTracerFactory(ServerStreamTracer.Factory factory) {
162
    streamTracerFactories.add(checkNotNull(factory, "factory"));
1✔
163
    return this;
1✔
164
  }
165

166
  @Override
167
  public ServerImplBuilder fallbackHandlerRegistry(@Nullable HandlerRegistry registry) {
168
    this.fallbackRegistry = registry != null ? registry : DEFAULT_FALLBACK_REGISTRY;
1✔
169
    return this;
1✔
170
  }
171

172
  @Override
173
  public ServerImplBuilder decompressorRegistry(@Nullable DecompressorRegistry registry) {
174
    this.decompressorRegistry = registry != null ? registry : DEFAULT_DECOMPRESSOR_REGISTRY;
1✔
175
    return this;
1✔
176
  }
177

178
  @Override
179
  public ServerImplBuilder compressorRegistry(@Nullable CompressorRegistry registry) {
180
    this.compressorRegistry = registry != null ? registry : DEFAULT_COMPRESSOR_REGISTRY;
1✔
181
    return this;
1✔
182
  }
183

184
  @Override
185
  public ServerImplBuilder handshakeTimeout(long timeout, TimeUnit unit) {
186
    checkArgument(timeout > 0, "handshake timeout is %s, but must be positive", timeout);
1✔
187
    this.handshakeTimeoutMillis = checkNotNull(unit, "unit").toMillis(timeout);
1✔
188
    return this;
1✔
189
  }
190

191
  @Override
192
  public ServerImplBuilder setBinaryLog(@Nullable BinaryLog binaryLog) {
193
    this.binlog = binaryLog;
×
194
    return this;
×
195
  }
196

197
  /**
198
   * Disable or enable stats features.  Enabled by default.
199
   */
200
  public void setStatsEnabled(boolean value) {
201
    this.statsEnabled = value;
1✔
202
  }
1✔
203

204
  /**
205
   * Disable or enable stats recording for RPC upstarts.  Effective only if {@link
206
   * #setStatsEnabled} is set to true.  Enabled by default.
207
   */
208
  public void setStatsRecordStartedRpcs(boolean value) {
209
    recordStartedRpcs = value;
1✔
210
  }
1✔
211

212
  /**
213
   * Disable or enable stats recording for RPC completions.  Effective only if {@link
214
   * #setStatsEnabled} is set to true.  Enabled by default.
215
   */
216
  public void setStatsRecordFinishedRpcs(boolean value) {
217
    recordFinishedRpcs = value;
1✔
218
  }
1✔
219

220
  /**
221
   * Disable or enable real-time metrics recording.  Effective only if {@link #setStatsEnabled} is
222
   * set to true.  Disabled by default.
223
   */
224
  public void setStatsRecordRealTimeMetrics(boolean value) {
225
    recordRealTimeMetrics = value;
×
226
  }
×
227

228
  /**
229
   * Disable or enable tracing features.  Enabled by default.
230
   */
231
  public void setTracingEnabled(boolean value) {
232
    tracingEnabled = value;
1✔
233
  }
1✔
234

235
  /**
236
   * Sets a custom deadline ticker.  This should only be called from InProcessServerBuilder.
237
   */
238
  public void setDeadlineTicker(Deadline.Ticker ticker) {
239
    this.ticker = checkNotNull(ticker, "ticker");
×
240
  }
×
241

242
  @Override
243
  public Server build() {
244
    return new ServerImpl(this,
1✔
245
        clientTransportServersBuilder.buildClientTransportServers(getTracerFactories()),
1✔
246
        Context.ROOT);
247
  }
248

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

316
  public InternalChannelz getChannelz() {
317
    return channelz;
1✔
318
  }
319

320
  private static final class DefaultFallbackRegistry extends HandlerRegistry {
321
    @Override
322
    public List<ServerServiceDefinition> getServices() {
323
      return Collections.emptyList();
1✔
324
    }
325

326
    @Nullable
327
    @Override
328
    public ServerMethodDefinition<?, ?> lookupMethod(
329
        String methodName, @Nullable String authority) {
330
      return null;
1✔
331
    }
332
  }
333

334
  /**
335
   * Returns the internal ExecutorPool for offloading tasks.
336
   */
337
  public ObjectPool<? extends Executor> getExecutorPool() {
338
    return this.executorPool;
1✔
339
  }
340

341
  @Override
342
  public ServerImplBuilder useTransportSecurity(File certChain, File privateKey) {
343
    throw new UnsupportedOperationException("TLS not supported in ServerImplBuilder");
×
344
  }
345
}
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

© 2025 Coveralls, Inc