From defce0d446d17a4e46008d09a2de4967849cb5c7 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Thu, 5 Feb 2026 07:41:48 +0000 Subject: [PATCH 1/3] feat: Add gRPC A66/A94 metrics. This change adds the `grpc.client.attempt.started` metric in the [A66](https://github.com/grpc/proposal/blob/master/A66-otel-stats.md) proposal and all the subchannel metrics in the [A94](https://github.com/grpc/proposal/blob/master/A94-subchannel-otel-metrics.md) proposal. Metric-specific attributes were also added. The change also updates the metric exporter to use the same timestamp for start and end time for GAUGE type data point. This is required by the StackDriver or otherwise the export will fail. --- .../cloud/spanner/BuiltInMetricsConstant.java | 23 +++++++++++++------ .../SpannerCloudMonitoringExporterUtils.java | 9 ++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java index d210bd85b79..41a16967f45 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java @@ -70,6 +70,11 @@ public class BuiltInMetricsConstant { static final Collection GRPC_METRICS_TO_ENABLE = ImmutableList.of( + "grpc.client.attempt.started", + "grpc.subchannel.open_connections", + "grpc.subchannel.disconnections", + "grpc.subchannel.connection_attempts_succeeded", + "grpc.subchannel.connection_attempts_failed", "grpc.lb.rls.default_target_picks", "grpc.lb.rls.target_picks", "grpc.xds_client.server_failure", @@ -100,8 +105,6 @@ public class BuiltInMetricsConstant { AttributeKey.stringKey("directpath_used"); public static final AttributeKey REQUEST_ID_KEY = AttributeKey.stringKey(REQUEST_ID_HEADER_NAME); - public static final AttributeKey GRPC_XDS_RESOURCE_TYPE_KEY = - AttributeKey.stringKey("grpc.xds.resource_type"); public static Set ALLOWED_EXEMPLARS_ATTRIBUTES = new HashSet<>(Arrays.asList(REQUEST_ID_HEADER_NAME)); @@ -124,8 +127,16 @@ public class BuiltInMetricsConstant { DIRECT_PATH_ENABLED_KEY, DIRECT_PATH_USED_KEY); - static final Set GRPC_LB_RLS_ATTRIBUTES = - ImmutableSet.of("grpc.lb.rls.data_plane_target", "grpc.lb.pick_result"); + static final Set GRPC_ATTRIBUTES = + ImmutableSet.of( + "grpc.disconnect_error", + "grpc.method", + "grpc.target", + "grpc.lb.backend_service", + "grpc.lb.locality", + "grpc.lb.pick_result", + "grpc.lb.rls.data_plane_target", + "grpc.xds.resource_type"); static List BUCKET_BOUNDARIES = ImmutableList.of( @@ -140,7 +151,6 @@ public class BuiltInMetricsConstant { ImmutableList.of( "grpc.client.attempt.sent_total_compressed_message_size", "grpc.client.attempt.rcvd_total_compressed_message_size", - "grpc.client.attempt.started", "grpc.client.attempt.duration", "grpc.client.call.duration"); @@ -235,8 +245,7 @@ private static void defineGRPCView(ImmutableMap.Builder Date: Thu, 5 Feb 2026 08:47:57 +0000 Subject: [PATCH 2/3] Enable different attributes in different gRPC metrics --- .../cloud/spanner/BuiltInMetricsConstant.java | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java index 41a16967f45..4bb87217f0e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java @@ -68,6 +68,34 @@ public class BuiltInMetricsConstant { .map(m -> METER_NAME + '/' + m) .collect(Collectors.toSet()); + static final Set GRPC_LB_RLS_ATTRIBUTES = + ImmutableSet.of("grpc.lb.rls.data_plane_target", "grpc.lb.pick_result"); + static final Set GRPC_CLIENT_ATTEMPT_STARTED_ATTRIBUTES = + ImmutableSet.of("grpc.method", "grpc.target"); + static final Set GRPC_SUBCHANNEL_DEFAULT_ATTRIBUTES = + ImmutableSet.of("grpc.target", "grpc.lb.locality", "grpc.lb.backend_service"); + static final Set GRPC_SUBCHANNEL_DISCONNECTION_ATTRIBUTES = + ImmutableSet.of( + "grpc.target", "grpc.lb.locality", "grpc.lb.backend_service", "grpc.disconnect_error"); + static final Set GRPC_XDS_CLIENT_RESOURCE_UPDATE_ATTRIBUTES = + ImmutableSet.of("grpc.xds.resource_type"); + + // Additional gRPC attributes to enable. + static final Map> GRPC_METRIC_ADDITIONAL_ATTRIBUTES = + ImmutableMap.>builder() + .put("grpc.client.attempt.started", GRPC_CLIENT_ATTEMPT_STARTED_ATTRIBUTES) + .put("grpc.subchannel.open_connections", GRPC_SUBCHANNEL_DEFAULT_ATTRIBUTES) + .put("grpc.subchannel.disconnections", GRPC_SUBCHANNEL_DISCONNECTION_ATTRIBUTES) + .put("grpc.subchannel.connection_attempts_succeeded", GRPC_SUBCHANNEL_DEFAULT_ATTRIBUTES) + .put("grpc.subchannel.connection_attempts_failed", GRPC_SUBCHANNEL_DEFAULT_ATTRIBUTES) + .put("grpc.lb.rls.default_target_picks", GRPC_LB_RLS_ATTRIBUTES) + .put("grpc.lb.rls.target_picks", GRPC_LB_RLS_ATTRIBUTES) + .put( + "grpc.xds_client.resource_updates_invalid", + GRPC_XDS_CLIENT_RESOURCE_UPDATE_ATTRIBUTES) + .put("grpc.xds_client.resource_updates_valid", GRPC_XDS_CLIENT_RESOURCE_UPDATE_ATTRIBUTES) + .build(); + static final Collection GRPC_METRICS_TO_ENABLE = ImmutableList.of( "grpc.client.attempt.started", @@ -127,17 +155,6 @@ public class BuiltInMetricsConstant { DIRECT_PATH_ENABLED_KEY, DIRECT_PATH_USED_KEY); - static final Set GRPC_ATTRIBUTES = - ImmutableSet.of( - "grpc.disconnect_error", - "grpc.method", - "grpc.target", - "grpc.lb.backend_service", - "grpc.lb.locality", - "grpc.lb.pick_result", - "grpc.lb.rls.data_plane_target", - "grpc.xds.resource_type"); - static List BUCKET_BOUNDARIES = ImmutableList.of( 0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, @@ -245,7 +262,8 @@ private static void defineGRPCView(ImmutableMap.Builder Date: Fri, 6 Feb 2026 08:21:30 +0000 Subject: [PATCH 3/3] Enable optional labels --- .../google/cloud/spanner/BuiltInMetricsConstant.java | 12 ++++++++++-- .../google/cloud/spanner/BuiltInMetricsProvider.java | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java index 4bb87217f0e..56fd6d28eb8 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java @@ -68,15 +68,23 @@ public class BuiltInMetricsConstant { .map(m -> METER_NAME + '/' + m) .collect(Collectors.toSet()); + // The following attributes are optional and need to be enabled explicitly. + public static final String GRPC_LB_BACKEND_SERVICE_ATTRIBUTE = "grpc.lb.backend_service"; + public static final String GRPC_LB_LOCALITY_ATTRIBUTE = "grpc.lb.locality"; + public static final String GRPC_DISCONNECT_ERROR_ATTRIBUTE = "grpc.disconnect_error"; + static final Set GRPC_LB_RLS_ATTRIBUTES = ImmutableSet.of("grpc.lb.rls.data_plane_target", "grpc.lb.pick_result"); static final Set GRPC_CLIENT_ATTEMPT_STARTED_ATTRIBUTES = ImmutableSet.of("grpc.method", "grpc.target"); static final Set GRPC_SUBCHANNEL_DEFAULT_ATTRIBUTES = - ImmutableSet.of("grpc.target", "grpc.lb.locality", "grpc.lb.backend_service"); + ImmutableSet.of("grpc.target", GRPC_LB_BACKEND_SERVICE_ATTRIBUTE, GRPC_LB_LOCALITY_ATTRIBUTE); static final Set GRPC_SUBCHANNEL_DISCONNECTION_ATTRIBUTES = ImmutableSet.of( - "grpc.target", "grpc.lb.locality", "grpc.lb.backend_service", "grpc.disconnect_error"); + "grpc.target", + GRPC_LB_BACKEND_SERVICE_ATTRIBUTE, + GRPC_LB_LOCALITY_ATTRIBUTE, + GRPC_DISCONNECT_ERROR_ATTRIBUTE); static final Set GRPC_XDS_CLIENT_RESOURCE_UPDATE_ATTRIBUTES = ImmutableSet.of("grpc.xds.resource_type"); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java index f1c520e10fa..0a51ebfae26 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java @@ -150,6 +150,9 @@ void enableGrpcMetrics( .enableMetrics(BuiltInMetricsConstant.GRPC_METRICS_TO_ENABLE) // Disable gRPCs default metrics as they are not needed for Spanner. .disableMetrics(BuiltInMetricsConstant.GRPC_METRICS_ENABLED_BY_DEFAULT) + .addOptionalLabel(BuiltInMetricsConstant.GRPC_LB_BACKEND_SERVICE_ATTRIBUTE) + .addOptionalLabel(BuiltInMetricsConstant.GRPC_LB_LOCALITY_ATTRIBUTE) + .addOptionalLabel(BuiltInMetricsConstant.GRPC_DISCONNECT_ERROR_ATTRIBUTE) .build(); ApiFunction channelConfigurator = channelProviderBuilder.getChannelConfigurator();