Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit 5b05b98

Browse files
chore: refactor metrics to be more structured and typesafe
Change-Id: I8573fdaf6d78398fdcad9a1c2cda16445f897276 # Conflicts: # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/MetricRegistry.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/attributes/ClientInfo.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/ClientPerConnectionErrorCount.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/Constants.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/PacemakerDelay.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableApplicationBlockingLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableAttemptLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableAttemptLatency2.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableClientBlockingLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableConnectivityErrorCount.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableDebugTagCount.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableFirstResponseLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableOperationLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableRemainingDeadline.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableRetryCount.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/metrics/TableServerLatency.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/schema/ClientSchema.java # google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/schema/TableSchema.java # google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/internal/csm/attributes/ClientInfoTest.java
1 parent 5eb88e7 commit 5b05b98

11 files changed

Lines changed: 329 additions & 429 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ public BigtableDataClient createDefault() {
109109
try {
110110
BigtableClientContext ctx =
111111
sharedClientContext.createChild(
112-
sharedClientContext.getInstanceName(), sharedClientContext.getAppProfileId());
112+
sharedClientContext.getClientInfo().getInstanceName(),
113+
sharedClientContext.getClientInfo().getAppProfileId());
113114

114115
return new BigtableDataClient(new EnhancedBigtableStub(perOpSettings, ctx));
115116
} catch (IOException e) {
@@ -130,7 +131,7 @@ public BigtableDataClient createDefault() {
130131
*/
131132
public BigtableDataClient createForAppProfile(@Nonnull String appProfileId) throws IOException {
132133
BigtableClientContext ctx =
133-
sharedClientContext.createChild(sharedClientContext.getInstanceName(), appProfileId);
134+
sharedClientContext.createChild(sharedClientContext.getClientInfo().getInstanceName(), appProfileId);
134135

135136
return new BigtableDataClient(new EnhancedBigtableStub(perOpSettings, ctx));
136137
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2026 Google LLC
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+
* https://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+
package com.google.cloud.bigtable.data.v2.internal.csm.metrics;
17+
18+
import com.google.bigtable.v2.ResponseParams;
19+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
20+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.EnvInfo;
21+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.MethodInfo;
22+
import com.google.cloud.bigtable.data.v2.internal.csm.metrics.Constants.MetricLabels;
23+
import com.google.cloud.bigtable.data.v2.internal.csm.schema.TableSchema;
24+
import com.google.common.collect.ImmutableMap;
25+
import io.grpc.Status;
26+
import io.opentelemetry.api.common.Attributes;
27+
import io.opentelemetry.api.metrics.DoubleGauge;
28+
import io.opentelemetry.api.metrics.Meter;
29+
30+
public class TableBatchWriteFlowControlFactor extends MetricWrapper<TableSchema> {
31+
private static final String NAME = "bigtable.googleapis.com/internal/client/batch_write_flow_control_target_qps";
32+
33+
public TableBatchWriteFlowControlFactor() {
34+
super(TableSchema.INSTANCE, NAME);
35+
}
36+
@Override
37+
public ImmutableMap<String, String> extractMetricLabels(
38+
Attributes metricAttrs, EnvInfo envInfo, ClientInfo clientInfo) {
39+
return ImmutableMap.<String, String>builder()
40+
.putAll(super.extractMetricLabels(metricAttrs, envInfo, clientInfo))
41+
.put(MetricLabels.CLIENT_UID.getKey(), clientInfo.getUid())
42+
.build();
43+
}
44+
45+
public Recorder newRecorder(Meter meter) {
46+
return new Recorder(meter);
47+
}
48+
49+
public class Recorder {
50+
private final DoubleGauge instrument;
51+
52+
private Recorder(Meter meter) {
53+
this.instrument = meter
54+
.gaugeBuilder(NAME)
55+
.setDescription("The current target QPS of the client under batch write flow control.")
56+
.setUnit("1")
57+
.build();
58+
}
59+
60+
public void record(
61+
ClientInfo clientInfo,
62+
String tableId,
63+
MethodInfo methodInfo,
64+
ResponseParams clusterInfo,
65+
Status.Code code,
66+
boolean applied,
67+
double factor) {
68+
Attributes attributes =
69+
getSchema()
70+
.createResourceAttrs(clientInfo, tableId, clusterInfo)
71+
// To maintain backwards compat CLIENT_UID is set using sideband data in the exporter
72+
.put(MetricLabels.CLIENT_NAME, clientInfo.getClientName())
73+
.put(MetricLabels.APP_PROFILE_KEY, clientInfo.getAppProfileId())
74+
.put(MetricLabels.METHOD_KEY, methodInfo.getName())
75+
.put(MetricLabels.STATUS_KEY, code.name())
76+
.put(MetricLabels.APPLIED_KEY, applied)
77+
.build();
78+
79+
instrument.set(factor, attributes);
80+
}
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2026 Google LLC
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+
* https://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+
package com.google.cloud.bigtable.data.v2.internal.csm.metrics;
17+
18+
import com.google.bigtable.v2.ResponseParams;
19+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
20+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.EnvInfo;
21+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.MethodInfo;
22+
import com.google.cloud.bigtable.data.v2.internal.csm.metrics.Constants.MetricLabels;
23+
import com.google.cloud.bigtable.data.v2.internal.csm.schema.TableSchema;
24+
import com.google.common.collect.ImmutableMap;
25+
import io.grpc.Status;
26+
import io.opentelemetry.api.common.Attributes;
27+
import io.opentelemetry.api.metrics.DoubleGauge;
28+
import io.opentelemetry.api.metrics.Meter;
29+
30+
public class TableBatchWriteFlowControlTargetQps extends MetricWrapper<TableSchema> {
31+
private static final String NAME = "bigtable.googleapis.com/internal/client/batch_write_flow_control_target_qps";
32+
33+
public TableBatchWriteFlowControlTargetQps() {
34+
super(TableSchema.INSTANCE, NAME);
35+
}
36+
@Override
37+
public ImmutableMap<String, String> extractMetricLabels(
38+
Attributes metricAttrs, EnvInfo envInfo, ClientInfo clientInfo) {
39+
return ImmutableMap.<String, String>builder()
40+
.putAll(super.extractMetricLabels(metricAttrs, envInfo, clientInfo))
41+
.put(MetricLabels.CLIENT_UID.getKey(), clientInfo.getUid())
42+
.build();
43+
}
44+
45+
public Recorder newRecorder(Meter meter) {
46+
return new Recorder(meter);
47+
}
48+
49+
public class Recorder {
50+
private final DoubleGauge instrument;
51+
52+
private Recorder(Meter meter) {
53+
this.instrument = meter
54+
.gaugeBuilder(NAME)
55+
.setDescription("The current target QPS of the client under batch write flow control.")
56+
.setUnit("1")
57+
.build();
58+
}
59+
60+
public void record(
61+
ClientInfo clientInfo,
62+
String tableId,
63+
MethodInfo methodInfo,
64+
ResponseParams clusterInfo,
65+
double qps) {
66+
Attributes attributes =
67+
getSchema()
68+
.createResourceAttrs(clientInfo, tableId, clusterInfo)
69+
// To maintain backwards compat CLIENT_UID is set using sideband data in the exporter
70+
.put(MetricLabels.CLIENT_NAME, clientInfo.getClientName())
71+
.put(MetricLabels.APP_PROFILE_KEY, clientInfo.getAppProfileId())
72+
.put(MetricLabels.METHOD_KEY, methodInfo.getName())
73+
.build();
74+
75+
instrument.set(qps, attributes);
76+
}
77+
}
78+
}

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

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.auth.oauth2.ServiceAccountJwtAccessCredentials;
3030
import com.google.bigtable.v2.InstanceName;
3131
import com.google.cloud.bigtable.data.v2.internal.JwtCredentialsWithAudience;
32+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
3233
import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants;
3334
import com.google.cloud.bigtable.data.v2.stub.metrics.ChannelPoolMetricsTracer;
3435
import com.google.cloud.bigtable.data.v2.stub.metrics.CompositeTracerFactory;
@@ -63,8 +64,7 @@ public class BigtableClientContext {
6364
private static final Logger logger = Logger.getLogger(BigtableClientContext.class.getName());
6465

6566
private final boolean isChild;
66-
private final InstanceName instanceName;
67-
private final String appProfileId;
67+
private final ClientInfo clientInfo;
6868
private final ApiTracerFactory userTracerFactory;
6969
@Nullable private final OpenTelemetrySdk builtinOpenTelemetry;
7070
@Nullable private final OpenTelemetry userOpenTelemetry;
@@ -83,8 +83,11 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
8383
public static BigtableClientContext create(
8484
EnhancedBigtableStubSettings settings, Tagger ocTagger, StatsRecorder ocRecorder)
8585
throws IOException {
86-
InstanceName instanceName = InstanceName.of(settings.getProjectId(), settings.getInstanceId());
87-
String appProfileId = settings.getAppProfileId();
86+
87+
ClientInfo clientInfo = ClientInfo.builder()
88+
.setInstanceName(InstanceName.of(settings.getProjectId(), settings.getInstanceId()))
89+
.setAppProfileId(settings.getAppProfileId())
90+
.build();
8891

8992
EnhancedBigtableStubSettings.Builder builder = settings.toBuilder();
9093

@@ -184,8 +187,7 @@ public static BigtableClientContext create(
184187

185188
return new BigtableClientContext(
186189
false,
187-
instanceName,
188-
appProfileId,
190+
clientInfo,
189191
clientContext,
190192
userTracerFactory,
191193
builtinOtel,
@@ -224,8 +226,7 @@ private static void configureGrpcOtel(
224226

225227
private BigtableClientContext(
226228
boolean isChild,
227-
InstanceName instanceName,
228-
String appProfileId,
229+
ClientInfo clientInfo,
229230
ClientContext clientContext,
230231
ApiTracerFactory userTracerFactory,
231232
@Nullable OpenTelemetrySdk builtinOtel,
@@ -235,8 +236,7 @@ private BigtableClientContext(
235236
ExecutorProvider backgroundExecutorProvider)
236237
throws IOException {
237238
this.isChild = isChild;
238-
this.instanceName = instanceName;
239-
this.appProfileId = appProfileId;
239+
this.clientInfo = clientInfo;
240240

241241
this.userTracerFactory = userTracerFactory;
242242
this.builtinOpenTelemetry = builtinOtel;
@@ -247,15 +247,15 @@ private BigtableClientContext(
247247

248248
ImmutableList.Builder<ApiTracerFactory> tracerFactories = ImmutableList.builder();
249249
tracerFactories
250-
.add(Util.createOCTracingFactory(instanceName, appProfileId))
251-
.add(Util.createOCMetricsFactory(instanceName, appProfileId, ocTagger, ocRecorder))
250+
.add(Util.createOCTracingFactory(clientInfo))
251+
.add(Util.createOCMetricsFactory(clientInfo, ocTagger, ocRecorder))
252252
.add(userTracerFactory);
253253

254254
if (builtinOtel != null) {
255-
tracerFactories.add(Util.createOtelMetricsFactory(builtinOtel, instanceName, appProfileId));
255+
tracerFactories.add(Util.createOtelMetricsFactory(builtinOtel, clientInfo));
256256
}
257257
if (userOtel != null) {
258-
tracerFactories.add(Util.createOtelMetricsFactory(userOtel, instanceName, appProfileId));
258+
tracerFactories.add(Util.createOtelMetricsFactory(userOtel, clientInfo));
259259
}
260260

261261
this.clientContext =
@@ -264,12 +264,8 @@ private BigtableClientContext(
264264
.build();
265265
}
266266

267-
public InstanceName getInstanceName() {
268-
return instanceName;
269-
}
270-
271-
public String getAppProfileId() {
272-
return appProfileId;
267+
public ClientInfo getClientInfo() {
268+
return clientInfo;
273269
}
274270

275271
@Nullable
@@ -290,8 +286,10 @@ public BigtableClientContext createChild(InstanceName instanceName, String appPr
290286
throws IOException {
291287
return new BigtableClientContext(
292288
true,
293-
instanceName,
294-
appProfileId,
289+
clientInfo.toBuilder()
290+
.setInstanceName(instanceName)
291+
.setAppProfileId(appProfileId)
292+
.build(),
295293
clientContext,
296294
userTracerFactory,
297295
builtinOpenTelemetry,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ public EnhancedBigtableStub(
184184
this.bigtableClientContext = clientContext;
185185
this.requestContext =
186186
RequestContext.create(
187-
clientContext.getInstanceName().getProject(),
188-
clientContext.getInstanceName().getInstance(),
189-
clientContext.getAppProfileId());
187+
clientContext.getClientInfo().getInstanceName().getProject(),
188+
clientContext.getClientInfo().getInstanceName().getInstance(),
189+
clientContext.getClientInfo().getAppProfileId());
190190
this.bulkMutationFlowController =
191191
new FlowController(perOpSettings.bulkMutateRowsSettings.getDynamicFlowControlSettings());
192192
this.bulkMutationDynamicFlowControlStats = new DynamicFlowControlStats();

0 commit comments

Comments
 (0)