-
Notifications
You must be signed in to change notification settings - Fork 105
feat(bigtable): classic direct access checker and it's implementation #2840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bf0003b
a6910b2
60bc8f4
547f461
30c17d5
f69837e
1ca692c
cc306bc
d8cf0e8
819444e
ceaea99
23fbcd2
04ea584
209b606
a1bd39a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| /* | ||
| * Copyright 2026 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.internal.csm.tracers; | ||
|
|
||
| import com.google.api.core.InternalApi; | ||
| import com.google.cloud.bigtable.data.v2.internal.csm.MetricRegistry; | ||
| import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo; | ||
|
|
||
| @InternalApi | ||
| public class DefaultDirectPathCompatibleTracer implements DirectPathCompatibleTracer { | ||
| private final ClientInfo clientInfo; | ||
| private final MetricRegistry.RecorderRegistry recorder; | ||
|
|
||
| public DefaultDirectPathCompatibleTracer( | ||
| ClientInfo clientInfo, MetricRegistry.RecorderRegistry recorder) { | ||
| this.clientInfo = clientInfo; | ||
| this.recorder = recorder; | ||
| } | ||
|
|
||
| @Override | ||
| public void recordSuccess(String ipPreference) { | ||
| recorder.dpCompatGuage.recordSuccess(clientInfo, ipPreference); | ||
| } | ||
|
|
||
| @Override | ||
| public void recordFailure(String reason) { | ||
| recorder.dpCompatGuage.recordFailure(clientInfo, reason); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| * Copyright 2026 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.internal.csm.tracers; | ||
|
|
||
| import com.google.api.core.InternalApi; | ||
|
|
||
| /** Interface for recording DirectPath/DirectAccess eligibility metrics. */ | ||
| @InternalApi | ||
| public interface DirectPathCompatibleTracer { | ||
|
|
||
| /** | ||
| * Records that the environment is eligible and successfully connected via DirectPath. | ||
| * | ||
| * @param ipPreference The IP preference used (e.g., "ipv6"). | ||
| */ | ||
| void recordSuccess(String ipPreference); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you defined an for this...why not use it? |
||
|
|
||
| /** | ||
| * Records that the environment is not eligible or failed to connect via DirectPath. | ||
| * | ||
| * @param reason The reason for the failure (e.g., "routing_check_failed"). | ||
| */ | ||
| void recordFailure(String reason); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| * Copyright 2026 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.internal.csm.tracers; | ||
|
|
||
| import com.google.api.core.InternalApi; | ||
|
|
||
| @InternalApi | ||
| public class NoopDirectPathCompatibleTracer implements DirectPathCompatibleTracer { | ||
|
|
||
| public static final NoopDirectPathCompatibleTracer INSTANCE = | ||
| new NoopDirectPathCompatibleTracer(); | ||
|
|
||
| private NoopDirectPathCompatibleTracer() {} | ||
|
|
||
| @Override | ||
| public void recordSuccess(String ipPreference) { | ||
| // No-op | ||
| } | ||
|
|
||
| @Override | ||
| public void recordFailure(String reason) { | ||
| // No-op | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| /* | ||
| * Copyright 2026 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.internal.dp; | ||
|
|
||
| import com.google.api.core.InternalApi; | ||
| import com.google.bigtable.v2.PeerInfo; | ||
| import com.google.cloud.bigtable.data.v2.internal.csm.tracers.DirectPathCompatibleTracer; | ||
| import com.google.cloud.bigtable.data.v2.stub.MetadataExtractorInterceptor; | ||
| import com.google.cloud.bigtable.gaxx.grpc.ChannelPrimer; | ||
| import com.google.common.annotations.VisibleForTesting; | ||
| import io.grpc.Channel; | ||
| import io.grpc.ClientInterceptors; | ||
| import io.grpc.ManagedChannel; | ||
| import java.util.Optional; | ||
| import java.util.function.Supplier; | ||
| import java.util.logging.Level; | ||
| import java.util.logging.Logger; | ||
|
|
||
| /** | ||
| * Evaluates whether a given channel has Direct Access (DirectPath) routing by executing a RPC and | ||
| * inspecting the response headers. | ||
| */ | ||
| @InternalApi | ||
| public class ClassicDirectAccessChecker implements DirectAccessChecker { | ||
| private static final Logger LOG = Logger.getLogger(ClassicDirectAccessChecker.class.getName()); | ||
| private final DirectPathCompatibleTracer tracer; | ||
| private final ChannelPrimer channelPrimer; | ||
|
|
||
| public ClassicDirectAccessChecker( | ||
| DirectPathCompatibleTracer tracer, ChannelPrimer channelPrimer) { | ||
| this.tracer = tracer; | ||
| this.channelPrimer = channelPrimer; | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| MetadataExtractorInterceptor createInterceptor() { | ||
| return new MetadataExtractorInterceptor(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean check(Supplier<ManagedChannel> supplier) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Im confused why this has to be abstracted to a supplier? why cant this just be a Channel? |
||
| ManagedChannel channel = null; | ||
| try { | ||
| channel = supplier.get(); | ||
| MetadataExtractorInterceptor interceptor = createInterceptor(); | ||
| Channel interceptedChannel = ClientInterceptors.intercept(channel, interceptor); | ||
| channelPrimer.primeChannel(interceptedChannel); | ||
|
|
||
| // Extract the sideband data populated by the interceptor | ||
| MetadataExtractorInterceptor.SidebandData sidebandData = interceptor.getSidebandData(); | ||
|
|
||
| boolean isEligible = | ||
| Optional.ofNullable(sidebandData) | ||
| .map(MetadataExtractorInterceptor.SidebandData::getPeerInfo) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getPeerInfo is marked Nullable, so this could cause an npe |
||
| .map(PeerInfo::getTransportType) | ||
| .map(type -> type == PeerInfo.TransportType.TRANSPORT_TYPE_DIRECT_ACCESS) | ||
| .orElse(false); | ||
|
|
||
| if (isEligible) { | ||
| String ipProtocolStr = | ||
| sidebandData.getIpProtocol() != null | ||
| ? sidebandData.getIpProtocol().toString().toLowerCase() | ||
| : "unknown"; | ||
|
Comment on lines
+74
to
+76
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this formatting move to com.google.cloud.bigtable.data.v2.internal.csm.attributes.Util? |
||
| tracer.recordSuccess(ipProtocolStr); | ||
| } | ||
|
|
||
| return isEligible; | ||
|
|
||
| } catch (Exception e) { | ||
| LOG.log(Level.FINE, "Failed to evaluate direct access eligibility.", e); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably a WARN if it threw an exception |
||
| return false; | ||
| } finally { | ||
| if (channel != null) { | ||
| channel.shutdownNow(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright 2026 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.internal.dp; | ||
|
|
||
| import com.google.api.core.InternalApi; | ||
| import io.grpc.ManagedChannel; | ||
| import java.util.function.Supplier; | ||
|
|
||
| @InternalApi | ||
| /* Evaluates whether a given channel supports Direct Access. */ | ||
| public interface DirectAccessChecker { | ||
| /** | ||
| * Evaluates if Direct Access is available by creating a test channel. | ||
| * | ||
| * @param supplier A supplier to create maybe direct access channel | ||
| * @return true if the channel is eligible for Direct Access | ||
| */ | ||
| boolean check(Supplier<ManagedChannel> supplier); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| * Copyright 2026 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.InternalApi; | ||
| import io.grpc.ManagedChannel; | ||
| import java.util.function.Supplier; | ||
|
|
||
| @InternalApi | ||
| public interface BigtableChannelSupplier extends Supplier<ManagedChannel> {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, can this be an enum?