1919import com .google .api .core .InternalApi ;
2020import com .google .api .gax .core .BackgroundResource ;
2121import com .google .api .gax .core .CredentialsProvider ;
22+ import com .google .api .gax .core .ExecutorProvider ;
2223import com .google .api .gax .core .FixedCredentialsProvider ;
2324import com .google .api .gax .grpc .InstantiatingGrpcChannelProvider ;
2425import com .google .api .gax .rpc .ClientContext ;
4142import java .io .IOException ;
4243import java .net .URI ;
4344import java .net .URISyntaxException ;
45+ import java .util .concurrent .ScheduledExecutorService ;
4446import java .util .logging .Level ;
4547import java .util .logging .Logger ;
4648import javax .annotation .Nullable ;
@@ -58,6 +60,9 @@ public class BigtableClientContext {
5860 @ Nullable private final OpenTelemetrySdk internalOpenTelemetry ;
5961 private final MetricsProvider metricsProvider ;
6062 private final ClientContext clientContext ;
63+ // the background executor shared for OTEL instances and monitoring client and all other
64+ // background tasks
65+ private final ExecutorProvider backgroundExecutorProvider ;
6166
6267 public static BigtableClientContext create (EnhancedBigtableStubSettings settings )
6368 throws IOException {
@@ -75,6 +80,14 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
7580
7681 String universeDomain = settings .getUniverseDomain ();
7782
83+ boolean shouldAutoClose = settings .getBackgroundExecutorProvider ().shouldAutoClose ();
84+ ScheduledExecutorService backgroundExecutor =
85+ settings .getBackgroundExecutorProvider ().getExecutor ();
86+ // TODO: after gax change is merged, migrate to use gax's FixedExecutorProvider
87+ BigtableExecutorProvider executorProvider =
88+ BigtableExecutorProvider .create (backgroundExecutor , shouldAutoClose );
89+ builder .setBackgroundExecutorProvider (executorProvider );
90+
7891 // Set up OpenTelemetry
7992 OpenTelemetry openTelemetry = null ;
8093 try {
@@ -85,7 +98,8 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
8598 settings .getMetricsProvider (),
8699 credentials ,
87100 settings .getMetricsEndpoint (),
88- universeDomain );
101+ universeDomain ,
102+ backgroundExecutor );
89103 } catch (Throwable t ) {
90104 logger .log (Level .WARNING , "Failed to get OTEL, will skip exporting client side metrics" , t );
91105 }
@@ -103,7 +117,9 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
103117 // no reason to build the internal OtelProvider
104118 if (transportProvider != null ) {
105119 internalOtel =
106- settings .getInternalMetricsProvider ().createOtelProvider (settings , credentials );
120+ settings
121+ .getInternalMetricsProvider ()
122+ .createOtelProvider (settings , credentials , backgroundExecutor );
107123 if (internalOtel != null ) {
108124 channelPoolMetricsTracer =
109125 new ChannelPoolMetricsTracer (
@@ -148,7 +164,11 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
148164 }
149165
150166 return new BigtableClientContext (
151- clientContext , openTelemetry , internalOtel , settings .getMetricsProvider ());
167+ clientContext ,
168+ openTelemetry ,
169+ internalOtel ,
170+ settings .getMetricsProvider (),
171+ executorProvider );
152172 }
153173
154174 private static void configureGrpcOtel (
@@ -182,11 +202,13 @@ private BigtableClientContext(
182202 ClientContext clientContext ,
183203 @ Nullable OpenTelemetry openTelemetry ,
184204 @ Nullable OpenTelemetrySdk internalOtel ,
185- MetricsProvider metricsProvider ) {
205+ MetricsProvider metricsProvider ,
206+ ExecutorProvider backgroundExecutorProvider ) {
186207 this .clientContext = clientContext ;
187208 this .openTelemetry = openTelemetry ;
188209 this .internalOpenTelemetry = internalOtel ;
189210 this .metricsProvider = metricsProvider ;
211+ this .backgroundExecutorProvider = backgroundExecutorProvider ;
190212 }
191213
192214 public OpenTelemetry getOpenTelemetry () {
@@ -201,6 +223,15 @@ public ClientContext getClientContext() {
201223 return this .clientContext ;
202224 }
203225
226+ public BigtableClientContext withClientContext (ClientContext clientContext ) {
227+ return new BigtableClientContext (
228+ clientContext ,
229+ openTelemetry ,
230+ internalOpenTelemetry ,
231+ metricsProvider ,
232+ backgroundExecutorProvider );
233+ }
234+
204235 public void close () throws Exception {
205236 for (BackgroundResource resource : clientContext .getBackgroundResources ()) {
206237 resource .close ();
@@ -211,13 +242,17 @@ public void close() throws Exception {
211242 if (metricsProvider instanceof DefaultMetricsProvider && openTelemetry != null ) {
212243 ((OpenTelemetrySdk ) openTelemetry ).close ();
213244 }
245+ if (backgroundExecutorProvider .shouldAutoClose ()) {
246+ backgroundExecutorProvider .getExecutor ().shutdown ();
247+ }
214248 }
215249
216250 private static OpenTelemetry getOpenTelemetryFromMetricsProvider (
217251 MetricsProvider metricsProvider ,
218252 @ Nullable Credentials defaultCredentials ,
219253 @ Nullable String metricsEndpoint ,
220- String universeDomain )
254+ String universeDomain ,
255+ ScheduledExecutorService executor )
221256 throws IOException {
222257 if (metricsProvider instanceof CustomOpenTelemetryMetricsProvider ) {
223258 CustomOpenTelemetryMetricsProvider customMetricsProvider =
@@ -229,7 +264,8 @@ private static OpenTelemetry getOpenTelemetryFromMetricsProvider(
229264 ? BigtableDataSettings .getMetricsCredentials ()
230265 : defaultCredentials ;
231266 DefaultMetricsProvider defaultMetricsProvider = (DefaultMetricsProvider ) metricsProvider ;
232- return defaultMetricsProvider .getOpenTelemetry (metricsEndpoint , universeDomain , credentials );
267+ return defaultMetricsProvider .getOpenTelemetry (
268+ metricsEndpoint , universeDomain , credentials , executor );
233269 } else if (metricsProvider instanceof NoopMetricsProvider ) {
234270 return null ;
235271 }
0 commit comments