From bfa156de26cb0cbf034bf437e715ab28d63d4346 Mon Sep 17 00:00:00 2001 From: Mattie Fu Date: Wed, 27 Nov 2024 14:52:25 -0500 Subject: [PATCH] chore: refactor to wrap client context in BigtableClientContext (#2433) Refactor ClientContext creation. We need to create OpenTelemetry before client context is created so we can inject the PerConnectionErrorTracker interceptor on the ManagedChannel. We need to access the open telemetry instance later when we create the TracerFactory. This PR creates a new BigtableCleintContext class that wraps gax ClientContext and OpenTelemetry so we can access both later to avoid creating a global open telemetry instance. Also moved client context creation logic from EnhancedBigtableStub to BigtableClientContext. --- .../data/v2/BigtableDataClientFactory.java | 51 ++-- .../data/v2/stub/BigtableClientContext.java | 239 ++++++++++++++++++ .../data/v2/stub/EnhancedBigtableStub.java | 186 +------------- .../stub/metrics/DefaultMetricsProvider.java | 23 +- .../metrics/BigtableTracerCallableTest.java | 15 +- .../v2/stub/metrics/MetricsTracerTest.java | 8 +- 6 files changed, 283 insertions(+), 239 deletions(-) create mode 100644 google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableClientContext.java diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java index 34ec77bdfc..359d0ff8aa 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java @@ -16,13 +16,10 @@ package com.google.cloud.bigtable.data.v2; import com.google.api.core.BetaApi; -import com.google.api.gax.core.BackgroundResource; import com.google.api.gax.rpc.ClientContext; +import com.google.cloud.bigtable.data.v2.stub.BigtableClientContext; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub; -import io.opentelemetry.api.OpenTelemetry; import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nonnull; /** @@ -66,11 +63,8 @@ @BetaApi("This feature is currently experimental and can change in the future") public final class BigtableDataClientFactory implements AutoCloseable { - private static final Logger logger = Logger.getLogger(BigtableDataClientFactory.class.getName()); - private final BigtableDataSettings defaultSettings; - private final ClientContext sharedClientContext; - private final OpenTelemetry openTelemetry; + private final BigtableClientContext sharedClientContext; /** * Create a instance of this factory. @@ -80,31 +74,16 @@ public final class BigtableDataClientFactory implements AutoCloseable { */ public static BigtableDataClientFactory create(BigtableDataSettings defaultSettings) throws IOException { - ClientContext sharedClientContext = - EnhancedBigtableStub.createClientContext(defaultSettings.getStubSettings()); - OpenTelemetry openTelemetry = null; - try { - // We don't want client side metrics to crash the client, so catch any exception when getting - // the OTEL instance and log the exception instead. - openTelemetry = - EnhancedBigtableStub.getOpenTelemetry( - defaultSettings.getProjectId(), - defaultSettings.getMetricsProvider(), - sharedClientContext.getCredentials(), - defaultSettings.getStubSettings().getMetricsEndpoint()); - } catch (Throwable t) { - logger.log(Level.WARNING, "Failed to get OTEL, will skip exporting client side metrics", t); - } - return new BigtableDataClientFactory(sharedClientContext, defaultSettings, openTelemetry); + BigtableClientContext sharedClientContext = + EnhancedBigtableStub.createBigtableClientContext(defaultSettings.getStubSettings()); + + return new BigtableDataClientFactory(sharedClientContext, defaultSettings); } private BigtableDataClientFactory( - ClientContext sharedClientContext, - BigtableDataSettings defaultSettings, - OpenTelemetry openTelemetry) { + BigtableClientContext sharedClientContext, BigtableDataSettings defaultSettings) { this.sharedClientContext = sharedClientContext; this.defaultSettings = defaultSettings; - this.openTelemetry = openTelemetry; } /** @@ -114,9 +93,7 @@ private BigtableDataClientFactory( */ @Override public void close() throws Exception { - for (BackgroundResource resource : sharedClientContext.getBackgroundResources()) { - resource.close(); - } + sharedClientContext.close(); } /** @@ -132,10 +109,11 @@ public BigtableDataClient createDefault() { try { ClientContext clientContext = sharedClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( - defaultSettings.getStubSettings(), openTelemetry)) + defaultSettings.getStubSettings(), sharedClientContext.getOpenTelemetry())) .build(); return BigtableDataClient.createWithClientContext(defaultSettings, clientContext); @@ -161,10 +139,11 @@ public BigtableDataClient createForAppProfile(@Nonnull String appProfileId) thro ClientContext clientContext = sharedClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( - settings.getStubSettings(), openTelemetry)) + settings.getStubSettings(), sharedClientContext.getOpenTelemetry())) .build(); return BigtableDataClient.createWithClientContext(settings, clientContext); } @@ -190,10 +169,11 @@ public BigtableDataClient createForInstance(@Nonnull String projectId, @Nonnull ClientContext clientContext = sharedClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( - settings.getStubSettings(), openTelemetry)) + settings.getStubSettings(), sharedClientContext.getOpenTelemetry())) .build(); return BigtableDataClient.createWithClientContext(settings, clientContext); @@ -220,10 +200,11 @@ public BigtableDataClient createForInstance( .build(); ClientContext clientContext = sharedClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( - settings.getStubSettings(), openTelemetry)) + settings.getStubSettings(), sharedClientContext.getOpenTelemetry())) .build(); return BigtableDataClient.createWithClientContext(settings, clientContext); } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableClientContext.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableClientContext.java new file mode 100644 index 0000000000..d23b487caf --- /dev/null +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableClientContext.java @@ -0,0 +1,239 @@ +/* + * Copyright 2024 Google LLC + * + * 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 + * + * https://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 com.google.cloud.bigtable.data.v2.stub; + +import com.google.api.core.ApiFunction; +import com.google.api.core.InternalApi; +import com.google.api.gax.core.BackgroundResource; +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.rpc.ClientContext; +import com.google.auth.Credentials; +import com.google.auth.oauth2.ServiceAccountJwtAccessCredentials; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.internal.JwtCredentialsWithAudience; +import com.google.cloud.bigtable.data.v2.stub.metrics.CustomOpenTelemetryMetricsProvider; +import com.google.cloud.bigtable.data.v2.stub.metrics.DefaultMetricsProvider; +import com.google.cloud.bigtable.data.v2.stub.metrics.ErrorCountPerConnectionMetricTracker; +import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsProvider; +import com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider; +import io.grpc.ManagedChannelBuilder; +import io.opentelemetry.api.OpenTelemetry; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * This class wraps all state needed during the lifetime of the Bigtable client. This includes gax's + * {@link ClientContext} plus any additional state that Bigtable Client needs. + */ +@InternalApi +public class BigtableClientContext { + + private static final Logger logger = Logger.getLogger(BigtableClientContext.class.getName()); + + @Nullable private final OpenTelemetry openTelemetry; + private final ClientContext clientContext; + + public static BigtableClientContext create(EnhancedBigtableStubSettings settings) + throws IOException { + EnhancedBigtableStubSettings.Builder builder = settings.toBuilder(); + + // Set up credentials + patchCredentials(builder); + + // Fix the credentials so that they can be shared + Credentials credentials = null; + if (builder.getCredentialsProvider() != null) { + credentials = builder.getCredentialsProvider().getCredentials(); + } + builder.setCredentialsProvider(FixedCredentialsProvider.create(credentials)); + + // Set up OpenTelemetry + OpenTelemetry openTelemetry = null; + try { + // We don't want client side metrics to crash the client, so catch any exception when getting + // the OTEL instance and log the exception instead. + // TODO openTelemetry doesn't need to be tied to a project id. This is incorrect and will be + // fixed in the following PR. + openTelemetry = + getOpenTelemetryFromMetricsProvider( + settings.getProjectId(), + settings.getMetricsProvider(), + credentials, + settings.getMetricsEndpoint()); + } catch (Throwable t) { + logger.log(Level.WARNING, "Failed to get OTEL, will skip exporting client side metrics", t); + } + + // Set up channel + InstantiatingGrpcChannelProvider.Builder transportProvider = + builder.getTransportChannelProvider() instanceof InstantiatingGrpcChannelProvider + ? ((InstantiatingGrpcChannelProvider) builder.getTransportChannelProvider()).toBuilder() + : null; + + ErrorCountPerConnectionMetricTracker errorCountPerConnectionMetricTracker = null; + + if (transportProvider != null) { + // Set up cookie holder if routing cookie is enabled + if (builder.getEnableRoutingCookie()) { + setupCookieHolder(transportProvider); + } + // Set up per connection error count tracker if OpenTelemetry is not null + if (openTelemetry != null) { + errorCountPerConnectionMetricTracker = + setupPerConnectionErrorTracer(builder, transportProvider, openTelemetry); + } + // Inject channel priming if enabled + if (builder.isRefreshingChannel()) { + transportProvider.setChannelPrimer( + BigtableChannelPrimer.create( + credentials, + settings.getProjectId(), + settings.getInstanceId(), + settings.getAppProfileId())); + } + + builder.setTransportChannelProvider(transportProvider.build()); + } + + ClientContext clientContext = ClientContext.create(builder.build()); + + if (errorCountPerConnectionMetricTracker != null) { + errorCountPerConnectionMetricTracker.startConnectionErrorCountTracker( + clientContext.getExecutor()); + } + + return new BigtableClientContext(clientContext, openTelemetry); + } + + private BigtableClientContext(ClientContext clientContext, OpenTelemetry openTelemetry) { + this.clientContext = clientContext; + this.openTelemetry = openTelemetry; + } + + public OpenTelemetry getOpenTelemetry() { + return this.openTelemetry; + } + + public ClientContext getClientContext() { + return this.clientContext; + } + + public void close() throws Exception { + for (BackgroundResource resource : clientContext.getBackgroundResources()) { + resource.close(); + } + } + + private static OpenTelemetry getOpenTelemetryFromMetricsProvider( + String projectId, + MetricsProvider metricsProvider, + @Nullable Credentials defaultCredentials, + @Nullable String metricsEndpoint) + throws IOException { + if (metricsProvider instanceof CustomOpenTelemetryMetricsProvider) { + CustomOpenTelemetryMetricsProvider customMetricsProvider = + (CustomOpenTelemetryMetricsProvider) metricsProvider; + return customMetricsProvider.getOpenTelemetry(); + } else if (metricsProvider instanceof DefaultMetricsProvider) { + Credentials credentials = + BigtableDataSettings.getMetricsCredentials() != null + ? BigtableDataSettings.getMetricsCredentials() + : defaultCredentials; + DefaultMetricsProvider defaultMetricsProvider = (DefaultMetricsProvider) metricsProvider; + return defaultMetricsProvider.getOpenTelemetry(projectId, metricsEndpoint, credentials); + } else if (metricsProvider instanceof NoopMetricsProvider) { + return null; + } + throw new IOException("Invalid MetricsProvider type " + metricsProvider); + } + + private static void patchCredentials(EnhancedBigtableStubSettings.Builder settings) + throws IOException { + int i = settings.getEndpoint().lastIndexOf(":"); + String host = settings.getEndpoint().substring(0, i); + String audience = settings.getJwtAudienceMapping().get(host); + + if (audience == null) { + return; + } + URI audienceUri = null; + try { + audienceUri = new URI(audience); + } catch (URISyntaxException e) { + throw new IllegalStateException("invalid JWT audience override", e); + } + + CredentialsProvider credentialsProvider = settings.getCredentialsProvider(); + if (credentialsProvider == null) { + return; + } + + Credentials credentials = credentialsProvider.getCredentials(); + if (credentials == null) { + return; + } + + if (!(credentials instanceof ServiceAccountJwtAccessCredentials)) { + return; + } + + ServiceAccountJwtAccessCredentials jwtCreds = (ServiceAccountJwtAccessCredentials) credentials; + JwtCredentialsWithAudience patchedCreds = new JwtCredentialsWithAudience(jwtCreds, audienceUri); + settings.setCredentialsProvider(FixedCredentialsProvider.create(patchedCreds)); + } + + private static ErrorCountPerConnectionMetricTracker setupPerConnectionErrorTracer( + EnhancedBigtableStubSettings.Builder builder, + InstantiatingGrpcChannelProvider.Builder transportProvider, + OpenTelemetry openTelemetry) { + ErrorCountPerConnectionMetricTracker errorCountPerConnectionMetricTracker = + new ErrorCountPerConnectionMetricTracker( + openTelemetry, EnhancedBigtableStub.createBuiltinAttributes(builder.build())); + ApiFunction oldChannelConfigurator = + transportProvider.getChannelConfigurator(); + transportProvider.setChannelConfigurator( + managedChannelBuilder -> { + managedChannelBuilder.intercept(errorCountPerConnectionMetricTracker.getInterceptor()); + + if (oldChannelConfigurator != null) { + managedChannelBuilder = oldChannelConfigurator.apply(managedChannelBuilder); + } + return managedChannelBuilder; + }); + return errorCountPerConnectionMetricTracker; + } + + private static void setupCookieHolder( + InstantiatingGrpcChannelProvider.Builder transportProvider) { + ApiFunction oldChannelConfigurator = + transportProvider.getChannelConfigurator(); + transportProvider.setChannelConfigurator( + managedChannelBuilder -> { + managedChannelBuilder.intercept(new CookiesInterceptor()); + + if (oldChannelConfigurator != null) { + managedChannelBuilder = oldChannelConfigurator.apply(managedChannelBuilder); + } + return managedChannelBuilder; + }); + } +} diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java index da0831304c..5cab91c92c 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java @@ -20,7 +20,6 @@ import static com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants.CLIENT_NAME_KEY; import static com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants.INSTANCE_ID_KEY; -import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.api.core.BetaApi; @@ -29,13 +28,10 @@ import com.google.api.gax.batching.BatcherImpl; import com.google.api.gax.batching.FlowController; import com.google.api.gax.core.BackgroundResource; -import com.google.api.gax.core.CredentialsProvider; -import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.grpc.GaxGrpcProperties; import com.google.api.gax.grpc.GrpcCallContext; import com.google.api.gax.grpc.GrpcCallSettings; import com.google.api.gax.grpc.GrpcRawCallableFactory; -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.BasicResultRetryAlgorithm; import com.google.api.gax.retrying.ExponentialRetryAlgorithm; import com.google.api.gax.retrying.RetryAlgorithm; @@ -57,8 +53,6 @@ import com.google.api.gax.tracing.SpanName; import com.google.api.gax.tracing.TracedServerStreamingCallable; import com.google.api.gax.tracing.TracedUnaryCallable; -import com.google.auth.Credentials; -import com.google.auth.oauth2.ServiceAccountJwtAccessCredentials; import com.google.bigtable.v2.BigtableGrpc; import com.google.bigtable.v2.CheckAndMutateRowResponse; import com.google.bigtable.v2.ExecuteQueryRequest; @@ -76,8 +70,6 @@ import com.google.bigtable.v2.RowRange; import com.google.bigtable.v2.SampleRowKeysResponse; import com.google.cloud.bigtable.Version; -import com.google.cloud.bigtable.data.v2.BigtableDataSettings; -import com.google.cloud.bigtable.data.v2.internal.JwtCredentialsWithAudience; import com.google.cloud.bigtable.data.v2.internal.NameUtil; import com.google.cloud.bigtable.data.v2.internal.RequestContext; import com.google.cloud.bigtable.data.v2.internal.SqlRow; @@ -109,12 +101,7 @@ import com.google.cloud.bigtable.data.v2.stub.metrics.BigtableTracerUnaryCallable; import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsTracerFactory; import com.google.cloud.bigtable.data.v2.stub.metrics.CompositeTracerFactory; -import com.google.cloud.bigtable.data.v2.stub.metrics.CustomOpenTelemetryMetricsProvider; -import com.google.cloud.bigtable.data.v2.stub.metrics.DefaultMetricsProvider; -import com.google.cloud.bigtable.data.v2.stub.metrics.ErrorCountPerConnectionMetricTracker; -import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsProvider; import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsTracerFactory; -import com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider; import com.google.cloud.bigtable.data.v2.stub.metrics.RpcMeasureConstants; import com.google.cloud.bigtable.data.v2.stub.metrics.StatsHeadersServerStreamingCallable; import com.google.cloud.bigtable.data.v2.stub.metrics.StatsHeadersUnaryCallable; @@ -145,7 +132,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.ByteString; -import io.grpc.ManagedChannelBuilder; import io.grpc.MethodDescriptor; import io.opencensus.stats.Stats; import io.opencensus.stats.StatsRecorder; @@ -156,8 +142,6 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.time.Duration; import java.util.Collections; import java.util.List; @@ -165,8 +149,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -185,8 +167,6 @@ @InternalApi public class EnhancedBigtableStub implements AutoCloseable { - private static final Logger logger = Logger.getLogger(EnhancedBigtableStub.class.getName()); - private static final String CLIENT_NAME = "Bigtable"; private static final long FLOW_CONTROL_ADJUSTING_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20); private final EnhancedBigtableStubSettings settings; @@ -220,22 +200,11 @@ public class EnhancedBigtableStub implements AutoCloseable { public static EnhancedBigtableStub create(EnhancedBigtableStubSettings settings) throws IOException { - ClientContext clientContext = createClientContext(settings); - OpenTelemetry openTelemetry = null; - try { - // We don't want client side metrics to crash the client, so catch any exception when getting - // the OTEL instance and log the exception instead. - openTelemetry = - getOpenTelemetry( - settings.getProjectId(), - settings.getMetricsProvider(), - clientContext.getCredentials(), - settings.getMetricsEndpoint()); - } catch (Throwable t) { - logger.log(Level.WARNING, "Failed to get OTEL, will skip exporting client side metrics", t); - } + BigtableClientContext bigtableClientContext = createBigtableClientContext(settings); + OpenTelemetry openTelemetry = bigtableClientContext.getOpenTelemetry(); ClientContext contextWithTracer = - clientContext + bigtableClientContext + .getClientContext() .toBuilder() .setTracerFactory(createBigtableTracerFactory(settings, openTelemetry)) .build(); @@ -248,89 +217,9 @@ public static EnhancedBigtableStub createWithClientContext( return new EnhancedBigtableStub(settings, clientContext, false); } - public static ClientContext createClientContext(EnhancedBigtableStubSettings settings) - throws IOException { - EnhancedBigtableStubSettings.Builder builder = settings.toBuilder(); - - // TODO: this implementation is on the cusp of unwieldy, if we end up adding more features - // consider splitting it up by feature. - - // workaround JWT audience issues - patchCredentials(builder); - - // Fix the credentials so that they can be shared - Credentials credentials = null; - if (builder.getCredentialsProvider() != null) { - credentials = builder.getCredentialsProvider().getCredentials(); - } - builder.setCredentialsProvider(FixedCredentialsProvider.create(credentials)); - - InstantiatingGrpcChannelProvider.Builder transportProvider = - builder.getTransportChannelProvider() instanceof InstantiatingGrpcChannelProvider - ? ((InstantiatingGrpcChannelProvider) builder.getTransportChannelProvider()).toBuilder() - : null; - - OpenTelemetry openTelemetry = null; - try { - // We don't want client side metrics to crash the client, so catch any exception when getting - // the OTEL instance and log the exception instead. - openTelemetry = - getOpenTelemetry( - settings.getProjectId(), - settings.getMetricsProvider(), - credentials, - settings.getMetricsEndpoint()); - } catch (Throwable t) { - logger.log(Level.WARNING, "Failed to get OTEL, will skip exporting client side metrics", t); - } - ErrorCountPerConnectionMetricTracker errorCountPerConnectionMetricTracker; - // Skip setting up ErrorCountPerConnectionMetricTracker if openTelemetry is null - if (openTelemetry != null && transportProvider != null) { - errorCountPerConnectionMetricTracker = - new ErrorCountPerConnectionMetricTracker( - openTelemetry, createBuiltinAttributes(settings)); - ApiFunction oldChannelConfigurator = - transportProvider.getChannelConfigurator(); - transportProvider.setChannelConfigurator( - managedChannelBuilder -> { - if (settings.getEnableRoutingCookie()) { - managedChannelBuilder.intercept(new CookiesInterceptor()); - } - - managedChannelBuilder.intercept(errorCountPerConnectionMetricTracker.getInterceptor()); - - if (oldChannelConfigurator != null) { - managedChannelBuilder = oldChannelConfigurator.apply(managedChannelBuilder); - } - return managedChannelBuilder; - }); - } else { - errorCountPerConnectionMetricTracker = null; - } - - // Inject channel priming - if (settings.isRefreshingChannel()) { - - if (transportProvider != null) { - transportProvider.setChannelPrimer( - BigtableChannelPrimer.create( - credentials, - settings.getProjectId(), - settings.getInstanceId(), - settings.getAppProfileId())); - } - } - - if (transportProvider != null) { - builder.setTransportChannelProvider(transportProvider.build()); - } - - ClientContext clientContext = ClientContext.create(builder.build()); - if (errorCountPerConnectionMetricTracker != null) { - errorCountPerConnectionMetricTracker.startConnectionErrorCountTracker( - clientContext.getExecutor()); - } - return clientContext; + public static BigtableClientContext createBigtableClientContext( + EnhancedBigtableStubSettings settings) throws IOException { + return BigtableClientContext.create(settings); } public static ApiTracerFactory createBigtableTracerFactory( @@ -387,31 +276,7 @@ public static ApiTracerFactory createBigtableTracerFactory( return new CompositeTracerFactory(tracerFactories.build()); } - @Nullable - public static OpenTelemetry getOpenTelemetry( - String projectId, - MetricsProvider metricsProvider, - @Nullable Credentials defaultCredentials, - @Nullable String metricsEndpoint) - throws IOException { - if (metricsProvider instanceof CustomOpenTelemetryMetricsProvider) { - CustomOpenTelemetryMetricsProvider customMetricsProvider = - (CustomOpenTelemetryMetricsProvider) metricsProvider; - return customMetricsProvider.getOpenTelemetry(); - } else if (metricsProvider instanceof DefaultMetricsProvider) { - Credentials credentials = - BigtableDataSettings.getMetricsCredentials() != null - ? BigtableDataSettings.getMetricsCredentials() - : defaultCredentials; - DefaultMetricsProvider defaultMetricsProvider = (DefaultMetricsProvider) metricsProvider; - return defaultMetricsProvider.getOpenTelemetry(projectId, metricsEndpoint, credentials); - } else if (metricsProvider instanceof NoopMetricsProvider) { - return null; - } - throw new IOException("Invalid MetricsProvider type " + metricsProvider); - } - - private static Attributes createBuiltinAttributes(EnhancedBigtableStubSettings settings) { + static Attributes createBuiltinAttributes(EnhancedBigtableStubSettings settings) { return Attributes.of( BIGTABLE_PROJECT_ID_KEY, settings.getProjectId(), @@ -423,41 +288,6 @@ private static Attributes createBuiltinAttributes(EnhancedBigtableStubSettings s "bigtable-java/" + Version.VERSION); } - private static void patchCredentials(EnhancedBigtableStubSettings.Builder settings) - throws IOException { - int i = settings.getEndpoint().lastIndexOf(":"); - String host = settings.getEndpoint().substring(0, i); - String audience = settings.getJwtAudienceMapping().get(host); - - if (audience == null) { - return; - } - URI audienceUri = null; - try { - audienceUri = new URI(audience); - } catch (URISyntaxException e) { - throw new IllegalStateException("invalid JWT audience override", e); - } - - CredentialsProvider credentialsProvider = settings.getCredentialsProvider(); - if (credentialsProvider == null) { - return; - } - - Credentials credentials = credentialsProvider.getCredentials(); - if (credentials == null) { - return; - } - - if (!(credentials instanceof ServiceAccountJwtAccessCredentials)) { - return; - } - - ServiceAccountJwtAccessCredentials jwtCreds = (ServiceAccountJwtAccessCredentials) credentials; - JwtCredentialsWithAudience patchedCreds = new JwtCredentialsWithAudience(jwtCreds, audienceUri); - settings.setCredentialsProvider(FixedCredentialsProvider.create(patchedCreds)); - } - public EnhancedBigtableStub(EnhancedBigtableStubSettings settings, ClientContext clientContext) { this(settings, clientContext, true); } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/DefaultMetricsProvider.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/DefaultMetricsProvider.java index c6b0a80c76..d1870dd834 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/DefaultMetricsProvider.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/DefaultMetricsProvider.java @@ -17,7 +17,6 @@ import com.google.api.core.InternalApi; import com.google.auth.Credentials; -import com.google.common.base.MoreObjects; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -36,30 +35,20 @@ public final class DefaultMetricsProvider implements MetricsProvider { public static DefaultMetricsProvider INSTANCE = new DefaultMetricsProvider(); - private OpenTelemetry openTelemetry; - private String projectId; - private DefaultMetricsProvider() {} @InternalApi public OpenTelemetry getOpenTelemetry( - String projectId, String metricsEndpoint, @Nullable Credentials credentials) + String projectId, @Nullable String metricsEndpoint, @Nullable Credentials credentials) throws IOException { - this.projectId = projectId; - if (openTelemetry == null) { - SdkMeterProviderBuilder meterProvider = SdkMeterProvider.builder(); - BuiltinMetricsView.registerBuiltinMetrics( - projectId, credentials, meterProvider, metricsEndpoint); - openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build(); - } - return openTelemetry; + SdkMeterProviderBuilder meterProvider = SdkMeterProvider.builder(); + BuiltinMetricsView.registerBuiltinMetrics( + projectId, credentials, meterProvider, metricsEndpoint); + return OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build(); } @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("projectId", projectId) - .add("openTelemetry", openTelemetry) - .toString(); + return "DefaultMetricsProvider"; } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java index a12dd3cfbd..91b650e6a8 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java @@ -44,6 +44,7 @@ import com.google.cloud.bigtable.data.v2.models.RowMutation; import com.google.cloud.bigtable.data.v2.models.SampleRowKeysRequest; import com.google.cloud.bigtable.data.v2.models.TableId; +import com.google.cloud.bigtable.data.v2.stub.BigtableClientContext; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub; import com.google.common.collect.ImmutableMap; import io.grpc.ForwardingServerCall.SimpleForwardingServerCall; @@ -126,10 +127,11 @@ public void sendHeaders(Metadata headers) { .setAppProfileId(APP_PROFILE_ID) .build(); + BigtableClientContext bigtableClientContext = + EnhancedBigtableStub.createBigtableClientContext(settings.getStubSettings()); ClientContext clientContext = - EnhancedBigtableStub.createClientContext(settings.getStubSettings()); - clientContext = - clientContext + bigtableClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( @@ -152,10 +154,11 @@ public void sendHeaders(Metadata headers) { .setAppProfileId(APP_PROFILE_ID) .build(); + BigtableClientContext noHeaderBigtableClientContext = + EnhancedBigtableStub.createBigtableClientContext(noHeaderSettings.getStubSettings()); ClientContext noHeaderClientContext = - EnhancedBigtableStub.createClientContext(noHeaderSettings.getStubSettings()); - noHeaderClientContext = - noHeaderClientContext + noHeaderBigtableClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory( diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java index d72eac4056..b651f231da 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java @@ -38,6 +38,7 @@ import com.google.cloud.bigtable.data.v2.models.Query; import com.google.cloud.bigtable.data.v2.models.Row; import com.google.cloud.bigtable.data.v2.models.RowMutationEntry; +import com.google.cloud.bigtable.data.v2.stub.BigtableClientContext; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub; import com.google.cloud.bigtable.data.v2.stub.mutaterows.MutateRowsBatchingDescriptor; import com.google.common.base.Stopwatch; @@ -120,10 +121,11 @@ public void setUp() throws Exception { .setAppProfileId(APP_PROFILE_ID) .build(); + BigtableClientContext bigtableClientContext = + EnhancedBigtableStub.createBigtableClientContext(settings.getStubSettings()); ClientContext clientContext = - EnhancedBigtableStub.createClientContext(settings.getStubSettings()); - clientContext = - clientContext + bigtableClientContext + .getClientContext() .toBuilder() .setTracerFactory( EnhancedBigtableStub.createBigtableTracerFactory(