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 34ec77bdf..359d0ff8a 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 000000000..d23b487ca --- /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 da0831304..5cab91c92 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 c6b0a80c7..d1870dd83 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 a12dd3cfb..91b650e6a 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 d72eac405..b651f231d 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(