Repository navigation
feat(spanner): report built-in channel pool metrics - #15019
uditdasari wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces built-in metrics for the gRPC-GCP channel pool in the Cloud Spanner Java client, including channel count and channel load metrics, along with corresponding configuration options and metadata attributes. The review feedback correctly identifies a compilation error in SpannerMetadataProvider.java due to missing imports for Cache and CacheBuilder. Additionally, it suggests refactoring the cache to use LoadingCache and CacheLoader, which simplifies the retrieval logic and eliminates the need for manual exception handling via getUnchecked.
| @@ -23,12 +24,15 @@ | |||
| import com.google.common.collect.ImmutableMap; | |||
There was a problem hiding this comment.
The classes Cache and CacheBuilder are used in this file but are not imported, which will cause a compilation error. Additionally, we can use LoadingCache and CacheLoader to simplify the cache retrieval and avoid unnecessary exception handling.
| import com.google.common.collect.ImmutableMap; | |
| import com.google.common.cache.CacheBuilder; | |
| import com.google.common.cache.CacheLoader; | |
| import com.google.common.cache.LoadingCache; | |
| import com.google.common.collect.ImmutableMap; |
| private final Cache<String, Attributes> builtInMetricsAttributesCache = | ||
| CacheBuilder.newBuilder().maximumSize(100).build(); |
There was a problem hiding this comment.
Instead of a generic Cache with a manual load callable on every get call, we can define a LoadingCache with a CacheLoader. This allows us to use getUnchecked and avoids having to handle checked ExecutionExceptions.
| private final Cache<String, Attributes> builtInMetricsAttributesCache = | |
| CacheBuilder.newBuilder().maximumSize(100).build(); | |
| private final LoadingCache<String, Attributes> builtInMetricsAttributesCache = | |
| CacheBuilder.newBuilder() | |
| .maximumSize(100) | |
| .build( | |
| new CacheLoader<String, Attributes>() { | |
| @Override | |
| public Attributes load(String resource) { | |
| return createBuiltInMetricsAttributes(resource); | |
| } | |
| }); |
| Attributes newBuiltInMetricsAttributes(@Nullable String resource) { | ||
| if (Strings.isNullOrEmpty(resource)) { | ||
| return Attributes.empty(); | ||
| } | ||
| try { | ||
| return builtInMetricsAttributesCache.get( | ||
| resource, () -> createBuiltInMetricsAttributes(resource)); | ||
| } catch (ExecutionException executionException) { | ||
| // This should never happen. | ||
| throw SpannerExceptionFactory.asSpannerException(executionException.getCause()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Using LoadingCache.getUnchecked simplifies the implementation by removing the try-catch block for ExecutionException, which is guaranteed not to be thrown since createBuiltInMetricsAttributes does not throw any checked exceptions.
Attributes newBuiltInMetricsAttributes(@Nullable String resource) {
if (Strings.isNullOrEmpty(resource)) {
return Attributes.empty();
}
return builtInMetricsAttributesCache.getUnchecked(resource);
}
This turns on the two channel pool metrics that grpc-gcp gained in #14947 and #14985 and sends them to Cloud Monitoring as Spanner built-in metrics.
What is reported
channel_pool/channel_count: the number of channels in the data pool per state (active,draining), with the labelslane,pool_modeandpool_index. The instance is reported asunknownbecause one pool serves many databases and instances, the same as the existing eef metrics. The project is the built-in metrics fallback project.channel_pool/channel_load: for each call, the number of calls that are open on the chosen channel, as a histogram with the boundaries 1, 2, 3, 5, 8, 12, 16, 20, 25, 30, 40, 50, 75, 100, 150, 200.project_id,instance_idanddatabasecome from the resource name of the request,laneandpool_modecome from the pool.Which pools report
pool_indexand are told apart bylane.lane, because its channels switch between the two paths.When nothing is reported
SPANNER_DISABLE_CHANNEL_POOL_BUILTIN_METRICS=true.CallContextConfigurators of the application.Cost
channel_countadds nothing per call.channel_loadadds one cached lookup of the resource name per call and carries the labels in the call options. Carrying the labels through grpc-gcp was measured in feat(grpc-gcp): add built-in channel_load metric for client library pools #14985 at about 58 ns and 24 bytes per call.Testing
GapicSpannerRpcTestandSpannerMetadataProviderTestfor the options and the resource name parsing.ChannelPoolBuiltInMetricsTestruns a client against the mock server and checks that only the data pool reports, the lanes of the DirectPath fallback pools, the fallback recovery layout withoutlane, the switches that turn the metrics off, that application settings cannot change the metrics, and the labels and boundaries ofchannel_load.pool_index1 and 2), two databases, and the long-term series.