Skip to content

Commit 08e1719

Browse files
authored
feat: migrate built in metrics to OTEL (#1796)
* feat: migrate exporter to OTEL * address comments * filter out only bigtable metrics * fix test * use the bom * update * update * feat: migrate builtin metrics to OTEl * update completeResultCode * add a comment * udpate * fix tests * remove unrelated changes * fix tests * add documentation * fix test * merge exporter changes * address comments * rebase on otel * revert changes in stats * fix import * update * merge back the endpoint change * refactor constants and settings * refactor and fix tests * remove unused dependency * add some javadoc * address part of the comments * update test * test with nano * measure everything in nanos and publish with double histogram * address comments * fix test * add toString
1 parent b8fd4d5 commit 08e1719

27 files changed

+1716
-497
lines changed

google-cloud-bigtable/clirr-ignored-differences.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@
156156
<differenceType>8001</differenceType>
157157
<className>com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerBatchedUnaryCallable</className>
158158
</difference>
159+
<!-- InternalApi constructor was updated -->
160+
<difference>
161+
<differenceType>7004</differenceType>
162+
<className>com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracerFactory</className>
163+
<method>*</method>
164+
</difference>
159165
<!-- InternalApi was updated -->
160166
<difference>
161167
<differenceType>6001</differenceType>

google-cloud-bigtable/pom.xml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,6 @@
6464
<dependencies>
6565
<!-- NOTE: Dependencies are organized into two groups, production and test.
6666
Within a group, dependencies are sorted by (groupId, artifactId) -->
67-
<dependency>
68-
<groupId>com.google.cloud</groupId>
69-
<artifactId>google-cloud-bigtable-stats</artifactId>
70-
<!-- Exclude all dependencies that have been shaded. This is to workaround maven's immutable project structure:
71-
after shading, the maven-shade-plugin tries to remove shaded dependencies, but it can't since the project
72-
structure is immutable. So we have to manually exclude the shaded transitive dependencies manually. -->
73-
<exclusions>
74-
<exclusion>
75-
<groupId>io.opencensus</groupId>
76-
<artifactId>*</artifactId>
77-
</exclusion>
78-
</exclusions>
79-
</dependency>
8067
<!-- Production dependencies -->
8168
<dependency>
8269
<groupId>com.google.api</groupId>
@@ -339,6 +326,10 @@
339326
<groupId>io.opentelemetry</groupId>
340327
<artifactId>opentelemetry-api</artifactId>
341328
</dependency>
329+
<dependency>
330+
<groupId>io.opentelemetry</groupId>
331+
<artifactId>opentelemetry-sdk</artifactId>
332+
</dependency>
342333
<dependency>
343334
<groupId>io.opentelemetry</groupId>
344335
<artifactId>opentelemetry-sdk-metrics</artifactId>
@@ -347,6 +338,11 @@
347338
<groupId>io.opentelemetry</groupId>
348339
<artifactId>opentelemetry-sdk-common</artifactId>
349340
</dependency>
341+
<dependency>
342+
<groupId>io.opentelemetry</groupId>
343+
<artifactId>opentelemetry-sdk-testing</artifactId>
344+
<scope>test</scope>
345+
</dependency>
350346
<dependency>
351347
<groupId>com.google.cloud</groupId>
352348
<artifactId>google-cloud-monitoring</artifactId>

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,16 @@
2525
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
2626
import com.google.api.gax.rpc.UnaryCallSettings;
2727
import com.google.auth.Credentials;
28-
import com.google.auth.oauth2.GoogleCredentials;
2928
import com.google.cloud.bigtable.data.v2.models.Query;
3029
import com.google.cloud.bigtable.data.v2.models.Row;
3130
import com.google.cloud.bigtable.data.v2.stub.BigtableBatchingCallSettings;
3231
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
33-
import com.google.cloud.bigtable.stats.BigtableStackdriverStatsExporter;
34-
import com.google.cloud.bigtable.stats.BuiltinViews;
32+
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsProvider;
3533
import com.google.common.base.MoreObjects;
3634
import com.google.common.base.Strings;
3735
import io.grpc.ManagedChannelBuilder;
3836
import java.io.IOException;
3937
import java.util.List;
40-
import java.util.concurrent.atomic.AtomicBoolean;
4138
import java.util.logging.Logger;
4239
import javax.annotation.Nonnull;
4340
import javax.annotation.Nullable;
@@ -77,7 +74,10 @@ public final class BigtableDataSettings {
7774

7875
private static final Logger LOGGER = Logger.getLogger(BigtableDataSettings.class.getName());
7976
private static final String BIGTABLE_EMULATOR_HOST_ENV_VAR = "BIGTABLE_EMULATOR_HOST";
80-
private static final AtomicBoolean BUILTIN_METRICS_REGISTERED = new AtomicBoolean(false);
77+
// This is the legacy credential override used in the deprecated enableBuiltinMetrics method to
78+
// override the default credentials set on the Bigtable client. Keeping it for backward
79+
// compatibility.
80+
@Deprecated @Nullable private static Credentials legacyMetricCredentialOverride;
8181

8282
private final EnhancedBigtableStubSettings stubSettings;
8383

@@ -197,23 +197,34 @@ public static void enableGfeOpenCensusStats() {
197197
com.google.cloud.bigtable.data.v2.stub.metrics.RpcViews.registerBigtableClientGfeViews();
198198
}
199199

200-
/** Register built in metrics. */
201-
public static void enableBuiltinMetrics() throws IOException {
202-
if (BUILTIN_METRICS_REGISTERED.compareAndSet(false, true)) {
203-
BuiltinViews.registerBigtableBuiltinViews();
204-
BigtableStackdriverStatsExporter.register(GoogleCredentials.getApplicationDefault());
205-
}
206-
}
200+
/**
201+
* Register built in metrics.
202+
*
203+
* @deprecated This is a no-op that doesn't do anything. Builtin metrics are enabled by default
204+
* now. Please refer to {@link
205+
* BigtableDataSettings.Builder#setMetricsProvider(MetricsProvider)} on how to enable or
206+
* disable built-in metrics.
207+
*/
208+
@Deprecated
209+
public static void enableBuiltinMetrics() throws IOException {}
207210

208211
/**
209212
* Register built in metrics with credentials. The credentials need to have metric write access
210213
* for all the projects you're publishing to.
214+
*
215+
* @deprecated This is a no-op that doesn't do anything. Builtin metrics are enabled by default
216+
* now. Please refer {@link BigtableDataSettings.Builder#setMetricsProvider(MetricsProvider)}
217+
* on how to enable or disable built-in metrics.
211218
*/
219+
@Deprecated
212220
public static void enableBuiltinMetrics(Credentials credentials) throws IOException {
213-
if (BUILTIN_METRICS_REGISTERED.compareAndSet(false, true)) {
214-
BuiltinViews.registerBigtableBuiltinViews();
215-
BigtableStackdriverStatsExporter.register(credentials);
216-
}
221+
BigtableDataSettings.legacyMetricCredentialOverride = credentials;
222+
}
223+
224+
/** Get the metrics credentials if it's set by {@link #enableBuiltinMetrics(Credentials)}. */
225+
@InternalApi
226+
public static Credentials getMetricsCredentials() {
227+
return legacyMetricCredentialOverride;
217228
}
218229

219230
/** Returns the target project id. */
@@ -278,6 +289,11 @@ public boolean isBulkMutationFlowControlEnabled() {
278289
return stubSettings.bulkMutateRowsSettings().isServerInitiatedFlowControlEnabled();
279290
}
280291

292+
/** Gets the {@link MetricsProvider}. * */
293+
public MetricsProvider getMetricsProvider() {
294+
return stubSettings.getMetricsProvider();
295+
}
296+
281297
/** Returns the underlying RPC settings. */
282298
public EnhancedBigtableStubSettings getStubSettings() {
283299
return stubSettings;
@@ -527,6 +543,30 @@ public boolean isBulkMutationFlowControlEnabled() {
527543
return stubSettings.bulkMutateRowsSettings().isServerInitiatedFlowControlEnabled();
528544
}
529545

546+
/**
547+
* Sets the {@link MetricsProvider}.
548+
*
549+
* <p>By default, this is set to {@link
550+
* com.google.cloud.bigtable.data.v2.stub.metrics.DefaultMetricsProvider#INSTANCE} which will
551+
* collect and export client side metrics.
552+
*
553+
* <p>To disable client side metrics, set it to {@link
554+
* com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider#INSTANCE}.
555+
*
556+
* <p>To use a custom OpenTelemetry instance, refer to {@link
557+
* com.google.cloud.bigtable.data.v2.stub.metrics.CustomOpenTelemetryMetricsProvider} on how to
558+
* set it up.
559+
*/
560+
public Builder setMetricsProvider(MetricsProvider metricsProvider) {
561+
stubSettings.setMetricsProvider(metricsProvider);
562+
return this;
563+
}
564+
565+
/** Gets the {@link MetricsProvider}. */
566+
public MetricsProvider getMetricsProvider() {
567+
return stubSettings.getMetricsProvider();
568+
}
569+
530570
/**
531571
* Returns the underlying settings for making RPC calls. The settings should be changed with
532572
* care.

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

18+
import static com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants.APP_PROFILE_KEY;
19+
import static com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants.INSTANCE_ID_KEY;
20+
import static com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants.PROJECT_ID_KEY;
21+
1822
import com.google.api.core.BetaApi;
1923
import com.google.api.core.InternalApi;
2024
import com.google.api.gax.batching.Batcher;
@@ -68,6 +72,7 @@
6872
import com.google.bigtable.v2.SampleRowKeysRequest;
6973
import com.google.bigtable.v2.SampleRowKeysResponse;
7074
import com.google.cloud.bigtable.Version;
75+
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
7176
import com.google.cloud.bigtable.data.v2.internal.JwtCredentialsWithAudience;
7277
import com.google.cloud.bigtable.data.v2.internal.RequestContext;
7378
import com.google.cloud.bigtable.data.v2.models.BulkMutation;
@@ -93,8 +98,13 @@
9398
import com.google.cloud.bigtable.data.v2.stub.metrics.BigtableTracerStreamingCallable;
9499
import com.google.cloud.bigtable.data.v2.stub.metrics.BigtableTracerUnaryCallable;
95100
import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsTracerFactory;
101+
import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsView;
96102
import com.google.cloud.bigtable.data.v2.stub.metrics.CompositeTracerFactory;
103+
import com.google.cloud.bigtable.data.v2.stub.metrics.CustomOpenTelemetryMetricsProvider;
104+
import com.google.cloud.bigtable.data.v2.stub.metrics.DefaultMetricsProvider;
105+
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsProvider;
97106
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsTracerFactory;
107+
import com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider;
98108
import com.google.cloud.bigtable.data.v2.stub.metrics.RpcMeasureConstants;
99109
import com.google.cloud.bigtable.data.v2.stub.metrics.StatsHeadersServerStreamingCallable;
100110
import com.google.cloud.bigtable.data.v2.stub.metrics.StatsHeadersUnaryCallable;
@@ -123,6 +133,11 @@
123133
import io.opencensus.tags.TagValue;
124134
import io.opencensus.tags.Tagger;
125135
import io.opencensus.tags.Tags;
136+
import io.opentelemetry.api.OpenTelemetry;
137+
import io.opentelemetry.api.common.Attributes;
138+
import io.opentelemetry.sdk.OpenTelemetrySdk;
139+
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
140+
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
126141
import java.io.IOException;
127142
import java.net.URI;
128143
import java.net.URISyntaxException;
@@ -241,7 +256,7 @@ public static ClientContext createClientContext(EnhancedBigtableStubSettings set
241256
}
242257

243258
public static ApiTracerFactory createBigtableTracerFactory(
244-
EnhancedBigtableStubSettings settings, ClientContext clientContext) {
259+
EnhancedBigtableStubSettings settings, ClientContext clientContext) throws IOException {
245260
return createBigtableTracerFactory(
246261
settings, Tags.getTagger(), Stats.getStatsRecorder(), clientContext);
247262
}
@@ -251,7 +266,8 @@ public static ApiTracerFactory createBigtableTracerFactory(
251266
EnhancedBigtableStubSettings settings,
252267
Tagger tagger,
253268
StatsRecorder stats,
254-
ClientContext clientContext) {
269+
ClientContext clientContext)
270+
throws IOException {
255271
String projectId = settings.getProjectId();
256272
String instanceId = settings.getInstanceId();
257273
String appProfileId = settings.getAppProfileId();
@@ -262,16 +278,11 @@ public static ApiTracerFactory createBigtableTracerFactory(
262278
.put(RpcMeasureConstants.BIGTABLE_INSTANCE_ID, TagValue.create(instanceId))
263279
.put(RpcMeasureConstants.BIGTABLE_APP_PROFILE_ID, TagValue.create(appProfileId))
264280
.build();
265-
ImmutableMap<String, String> builtinAttributes =
266-
ImmutableMap.<String, String>builder()
267-
.put("project_id", projectId)
268-
.put("instance", instanceId)
269-
.put("app_profile", appProfileId)
270-
.build();
271281

272282
ImmutableList.Builder<ApiTracerFactory> tracerFactories = ImmutableList.builder();
273283
tracerFactories
274284
.add(
285+
// Add OpenCensus Tracing
275286
new OpencensusTracerFactory(
276287
ImmutableMap.<String, String>builder()
277288
// Annotate traces with the same tags as metrics
@@ -285,13 +296,47 @@ public static ApiTracerFactory createBigtableTracerFactory(
285296
.build()))
286297
// Add OpenCensus Metrics
287298
.add(MetricsTracerFactory.create(tagger, stats, attributes))
288-
.add(BuiltinMetricsTracerFactory.create(builtinAttributes))
289299
// Add user configured tracer
290300
.add(settings.getTracerFactory());
291-
301+
Attributes otelAttributes =
302+
Attributes.of(
303+
PROJECT_ID_KEY, projectId, INSTANCE_ID_KEY, instanceId, APP_PROFILE_KEY, appProfileId);
304+
BuiltinMetricsTracerFactory builtinMetricsTracerFactory =
305+
createBuiltinMetricsTracerFactory(
306+
projectId, settings.getMetricsProvider(), otelAttributes, clientContext);
307+
if (builtinMetricsTracerFactory != null) {
308+
tracerFactories.add(builtinMetricsTracerFactory);
309+
}
292310
return new CompositeTracerFactory(tracerFactories.build());
293311
}
294312

313+
private static BuiltinMetricsTracerFactory createBuiltinMetricsTracerFactory(
314+
String projectId,
315+
MetricsProvider metricsProvider,
316+
Attributes attributes,
317+
ClientContext clientContext)
318+
throws IOException {
319+
if (metricsProvider instanceof CustomOpenTelemetryMetricsProvider) {
320+
CustomOpenTelemetryMetricsProvider customMetricsProvider =
321+
(CustomOpenTelemetryMetricsProvider) metricsProvider;
322+
return BuiltinMetricsTracerFactory.create(
323+
customMetricsProvider.getOpenTelemetry(), attributes);
324+
} else if (metricsProvider instanceof DefaultMetricsProvider) {
325+
SdkMeterProviderBuilder meterProvider = SdkMeterProvider.builder();
326+
Credentials credentials =
327+
BigtableDataSettings.getMetricsCredentials() != null
328+
? BigtableDataSettings.getMetricsCredentials()
329+
: clientContext.getCredentials();
330+
BuiltinMetricsView.registerBuiltinMetrics(projectId, credentials, meterProvider);
331+
OpenTelemetry openTelemetry =
332+
OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build();
333+
return BuiltinMetricsTracerFactory.create(openTelemetry, attributes);
334+
} else if (metricsProvider instanceof NoopMetricsProvider) {
335+
return null;
336+
}
337+
throw new IOException("Invalid MetricsProvider type " + metricsProvider);
338+
}
339+
295340
private static void patchCredentials(EnhancedBigtableStubSettings.Builder settings)
296341
throws IOException {
297342
int i = settings.getEndpoint().lastIndexOf(":");

0 commit comments

Comments
 (0)