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

Commit 6aa1b91

Browse files
chore: merge main into generate-libraries-main
2 parents 6bdc421 + ed4ad83 commit 6aa1b91

30 files changed

Lines changed: 667 additions & 778 deletions

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

Lines changed: 4 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,8 @@ 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(
135+
sharedClientContext.getClientInfo().getInstanceName(), appProfileId);
134136

135137
return new BigtableDataClient(new EnhancedBigtableStub(perOpSettings, ctx));
136138
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import com.google.api.core.InternalApi;
1919
import com.google.auto.value.AutoValue;
20+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
2021
import java.io.Serializable;
2122

2223
/**
@@ -33,6 +34,13 @@
3334
@AutoValue
3435
public abstract class RequestContext implements Serializable {
3536

37+
public static RequestContext create(ClientInfo clientInfo) {
38+
return create(
39+
clientInfo.getInstanceName().getProject(),
40+
clientInfo.getInstanceName().getInstance(),
41+
clientInfo.getAppProfileId());
42+
}
43+
3644
/** Creates a new instance of the {@link RequestContext}. */
3745
public static RequestContext create(String projectId, String instanceId, String appProfileId) {
3846
return new AutoValue_RequestContext(projectId, instanceId, appProfileId);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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;
17+
18+
import com.google.api.gax.tracing.ApiTracerFactory;
19+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
20+
import com.google.cloud.bigtable.data.v2.stub.metrics.ChannelPoolMetricsTracer;
21+
import io.grpc.ManagedChannelBuilder;
22+
import java.io.Closeable;
23+
import java.io.IOException;
24+
import javax.annotation.Nullable;
25+
26+
public interface Metrics extends Closeable {
27+
ApiTracerFactory createTracerFactory(ClientInfo clientInfo) throws IOException;
28+
29+
<T extends ManagedChannelBuilder<?>> T configureGrpcChannel(T channelBuilder);
30+
31+
@Nullable
32+
ChannelPoolMetricsTracer getChannelPoolMetricsTracer();
33+
34+
void start();
35+
36+
@Override
37+
void close();
38+
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
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;
17+
18+
import com.google.api.gax.grpc.GaxGrpcProperties;
19+
import com.google.api.gax.tracing.ApiTracerFactory;
20+
import com.google.api.gax.tracing.OpencensusTracerFactory;
21+
import com.google.auth.Credentials;
22+
import com.google.cloud.bigtable.Version;
23+
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
24+
import com.google.cloud.bigtable.data.v2.internal.csm.MetricRegistry.RecorderRegistry;
25+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
26+
import com.google.cloud.bigtable.data.v2.stub.metrics.BigtableCloudMonitoringExporter;
27+
import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsConstants;
28+
import com.google.cloud.bigtable.data.v2.stub.metrics.BuiltinMetricsTracerFactory;
29+
import com.google.cloud.bigtable.data.v2.stub.metrics.ChannelPoolMetricsTracer;
30+
import com.google.cloud.bigtable.data.v2.stub.metrics.CompositeTracerFactory;
31+
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsTracerFactory;
32+
import com.google.cloud.bigtable.data.v2.stub.metrics.RpcMeasureConstants;
33+
import com.google.common.base.Preconditions;
34+
import com.google.common.collect.ImmutableList;
35+
import com.google.common.collect.ImmutableMap;
36+
import io.grpc.ManagedChannelBuilder;
37+
import io.grpc.opentelemetry.GrpcOpenTelemetry;
38+
import io.opencensus.stats.StatsRecorder;
39+
import io.opencensus.tags.TagKey;
40+
import io.opencensus.tags.TagValue;
41+
import io.opencensus.tags.Tagger;
42+
import io.opentelemetry.api.OpenTelemetry;
43+
import io.opentelemetry.sdk.OpenTelemetrySdk;
44+
import io.opentelemetry.sdk.metrics.InstrumentSelector;
45+
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
46+
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
47+
import io.opentelemetry.sdk.metrics.View;
48+
import io.opentelemetry.sdk.metrics.export.MetricExporter;
49+
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
50+
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReaderBuilder;
51+
import java.io.Closeable;
52+
import java.io.IOException;
53+
import java.util.ArrayList;
54+
import java.util.List;
55+
import java.util.Map;
56+
import java.util.concurrent.ScheduledExecutorService;
57+
import java.util.concurrent.ScheduledFuture;
58+
import javax.annotation.Nullable;
59+
60+
public class MetricsImpl implements Metrics, Closeable {
61+
private final MetricRegistry metricRegistry;
62+
63+
private final ApiTracerFactory userTracerFactory;
64+
private final @Nullable OpenTelemetrySdk internalOtel;
65+
private final @Nullable OpenTelemetry userOtel;
66+
private final ScheduledExecutorService executor;
67+
private final Tagger ocTagger;
68+
private final StatsRecorder ocRecorder;
69+
70+
@Nullable private final GrpcOpenTelemetry grpcOtel;
71+
@Nullable private final ChannelPoolMetricsTracer channelPoolMetricsTracer;
72+
private final List<ScheduledFuture<?>> tasks = new ArrayList<>();
73+
74+
public MetricsImpl(
75+
ClientInfo clientInfo,
76+
ApiTracerFactory userTracerFactory,
77+
@Nullable OpenTelemetrySdk internalOtel,
78+
@Nullable OpenTelemetry userOtel,
79+
Tagger ocTagger,
80+
StatsRecorder ocRecorder,
81+
ScheduledExecutorService executor) {
82+
metricRegistry = new MetricRegistry();
83+
this.userTracerFactory = Preconditions.checkNotNull(userTracerFactory);
84+
85+
this.internalOtel = internalOtel;
86+
this.userOtel = userOtel;
87+
88+
this.ocTagger = ocTagger;
89+
this.ocRecorder = ocRecorder;
90+
91+
this.executor = executor;
92+
93+
if (internalOtel != null) {
94+
this.grpcOtel =
95+
GrpcOpenTelemetry.newBuilder()
96+
.sdk(internalOtel)
97+
.addOptionalLabel("grpc.lb.locality")
98+
// Disable default grpc metrics
99+
.disableAllMetrics()
100+
// Enable specific grpc metrics
101+
.enableMetrics(BuiltinMetricsConstants.GRPC_METRICS.keySet())
102+
.build();
103+
} else {
104+
this.grpcOtel = null;
105+
}
106+
107+
if (internalOtel != null) {
108+
this.channelPoolMetricsTracer =
109+
new ChannelPoolMetricsTracer(
110+
metricRegistry.newRecorderRegistry(internalOtel.getMeterProvider()), clientInfo);
111+
} else {
112+
this.channelPoolMetricsTracer = null;
113+
}
114+
}
115+
116+
@Override
117+
public void close() {
118+
for (ScheduledFuture<?> task : tasks) {
119+
task.cancel(false);
120+
}
121+
if (internalOtel != null) {
122+
internalOtel.close();
123+
}
124+
}
125+
126+
@Override
127+
public void start() {
128+
if (channelPoolMetricsTracer != null) {
129+
tasks.add(channelPoolMetricsTracer.start(executor));
130+
}
131+
}
132+
133+
@Override
134+
public <T extends ManagedChannelBuilder<?>> T configureGrpcChannel(T channelBuilder) {
135+
if (grpcOtel == null) {
136+
return channelBuilder;
137+
}
138+
grpcOtel.configureChannelBuilder(channelBuilder);
139+
return channelBuilder;
140+
}
141+
142+
@Override
143+
public ApiTracerFactory createTracerFactory(ClientInfo clientInfo) {
144+
ImmutableList.Builder<ApiTracerFactory> tracerFactories = ImmutableList.builder();
145+
tracerFactories
146+
.add(createOCTracingFactory(clientInfo))
147+
.add(createOCMetricsFactory(clientInfo, ocTagger, ocRecorder))
148+
.add(userTracerFactory);
149+
150+
if (internalOtel != null) {
151+
tracerFactories.add(
152+
createOtelMetricsFactory(
153+
metricRegistry.newRecorderRegistry(internalOtel.getMeterProvider()), clientInfo));
154+
}
155+
if (userOtel != null) {
156+
tracerFactories.add(
157+
createOtelMetricsFactory(
158+
metricRegistry.newRecorderRegistry(userOtel.getMeterProvider()), clientInfo));
159+
}
160+
161+
return new CompositeTracerFactory(tracerFactories.build());
162+
}
163+
164+
@Override
165+
@Nullable
166+
public ChannelPoolMetricsTracer getChannelPoolMetricsTracer() {
167+
return channelPoolMetricsTracer;
168+
}
169+
170+
public static OpenTelemetrySdk createBuiltinOtel(
171+
ClientInfo clientInfo,
172+
@Nullable Credentials defaultCredentials,
173+
@Nullable String metricsEndpoint,
174+
String universeDomain,
175+
ScheduledExecutorService executor)
176+
throws IOException {
177+
178+
Credentials credentials =
179+
BigtableDataSettings.getMetricsCredentials() != null
180+
? BigtableDataSettings.getMetricsCredentials()
181+
: defaultCredentials;
182+
183+
SdkMeterProviderBuilder meterProvider = SdkMeterProvider.builder();
184+
185+
for (Map.Entry<InstrumentSelector, View> entry :
186+
BuiltinMetricsConstants.getAllViews().entrySet()) {
187+
meterProvider.registerView(entry.getKey(), entry.getValue());
188+
}
189+
190+
for (Map.Entry<InstrumentSelector, View> e :
191+
BuiltinMetricsConstants.getInternalViews().entrySet()) {
192+
meterProvider.registerView(e.getKey(), e.getValue());
193+
}
194+
195+
MetricExporter publicExporter =
196+
BigtableCloudMonitoringExporter.create(
197+
clientInfo, credentials, metricsEndpoint, universeDomain, executor);
198+
PeriodicMetricReaderBuilder readerBuilder =
199+
PeriodicMetricReader.builder(publicExporter).setExecutor(executor);
200+
meterProvider.registerMetricReader(readerBuilder.build());
201+
202+
return OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build();
203+
}
204+
205+
private static ApiTracerFactory createOCTracingFactory(ClientInfo clientInfo) {
206+
return new OpencensusTracerFactory(
207+
ImmutableMap.<String, String>builder()
208+
// Annotate traces with the same tags as metrics
209+
.put(
210+
RpcMeasureConstants.BIGTABLE_PROJECT_ID.getName(),
211+
clientInfo.getInstanceName().getProject())
212+
.put(
213+
RpcMeasureConstants.BIGTABLE_INSTANCE_ID.getName(),
214+
clientInfo.getInstanceName().getInstance())
215+
.put(
216+
RpcMeasureConstants.BIGTABLE_APP_PROFILE_ID.getName(), clientInfo.getAppProfileId())
217+
// Also annotate traces with library versions
218+
.put("gax", GaxGrpcProperties.getGaxGrpcVersion())
219+
.put("grpc", GaxGrpcProperties.getGrpcVersion())
220+
.put("gapic", Version.VERSION)
221+
.build());
222+
}
223+
224+
private static ApiTracerFactory createOCMetricsFactory(
225+
ClientInfo clientInfo, Tagger tagger, StatsRecorder stats) {
226+
227+
ImmutableMap<TagKey, TagValue> attributes =
228+
ImmutableMap.<TagKey, TagValue>builder()
229+
.put(
230+
RpcMeasureConstants.BIGTABLE_PROJECT_ID,
231+
TagValue.create(clientInfo.getInstanceName().getProject()))
232+
.put(
233+
RpcMeasureConstants.BIGTABLE_INSTANCE_ID,
234+
TagValue.create(clientInfo.getInstanceName().getInstance()))
235+
.put(
236+
RpcMeasureConstants.BIGTABLE_APP_PROFILE_ID,
237+
TagValue.create(clientInfo.getAppProfileId()))
238+
.build();
239+
return MetricsTracerFactory.create(tagger, stats, attributes);
240+
}
241+
242+
private static BuiltinMetricsTracerFactory createOtelMetricsFactory(
243+
RecorderRegistry recorder, ClientInfo clientInfo) {
244+
245+
return BuiltinMetricsTracerFactory.create(recorder, clientInfo);
246+
}
247+
}

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/csm/attributes/Util.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,56 @@
1616

1717
package com.google.cloud.bigtable.data.v2.internal.csm.attributes;
1818

19+
import com.google.bigtable.v2.PeerInfo;
1920
import com.google.bigtable.v2.PeerInfo.TransportType;
20-
import com.google.common.base.Preconditions;
21+
import com.google.bigtable.v2.ResponseParams;
2122
import java.util.Locale;
23+
import java.util.Optional;
24+
import javax.annotation.Nullable;
2225

2326
public class Util {
2427
static final String TRANSPORT_TYPE_PREFIX = "TRANSPORT_TYPE_";
2528

26-
public static String transportTypeToString(TransportType transportType) {
29+
public static String formatTransportZone(@Nullable PeerInfo peerInfo) {
30+
return Optional.ofNullable(peerInfo).map(PeerInfo::getApplicationFrontendZone).orElse("");
31+
}
2732

28-
Preconditions.checkArgument(
29-
transportType.name().startsWith(TRANSPORT_TYPE_PREFIX)
30-
|| transportType == TransportType.UNRECOGNIZED,
31-
"TransportType values must start with %s",
32-
TRANSPORT_TYPE_PREFIX);
33+
public static String formatTransportSubzone(@Nullable PeerInfo peerInfo) {
34+
return Optional.ofNullable(peerInfo).map(PeerInfo::getApplicationFrontendSubzone).orElse("");
35+
}
36+
37+
public static String formatTransportType(@Nullable PeerInfo peerInfo) {
38+
return transportTypeToString(
39+
Optional.ofNullable(peerInfo)
40+
.map(PeerInfo::getTransportType)
41+
.orElse(TransportType.TRANSPORT_TYPE_UNKNOWN));
42+
}
3343

44+
public static String transportTypeToString(TransportType transportType) {
3445
if (transportType == TransportType.TRANSPORT_TYPE_UNKNOWN) {
35-
return "session_none";
46+
return "none";
3647
}
3748
if (transportType == TransportType.UNRECOGNIZED) {
38-
return "session_unrecognized";
49+
return "unrecognized";
3950
}
4051

4152
return transportType
4253
.name()
4354
.substring(TRANSPORT_TYPE_PREFIX.length())
4455
.toLowerCase(Locale.ENGLISH);
4556
}
57+
58+
public static String formatClusterIdMetricLabel(@Nullable ResponseParams clusterInfo) {
59+
return Optional.ofNullable(clusterInfo)
60+
.map(ResponseParams::getClusterId)
61+
.filter(s -> !s.isEmpty())
62+
.orElse("<unspecified>");
63+
}
64+
65+
public static String formatZoneIdMetricLabel(@Nullable ResponseParams clusterInfo) {
66+
return Optional.ofNullable(clusterInfo)
67+
.map(ResponseParams::getZoneId)
68+
.filter(s -> !s.isEmpty())
69+
.orElse("global");
70+
}
4671
}

0 commit comments

Comments
 (0)