Skip to content

Commit abf1178

Browse files
authored
fix(metrics): fix GFE and AFE metrics publishing (#17561)
## Description This PR enables and properly extracts Spanner Google Front End (GFE) and Application Front End (AFE) latency metrics. ### Key Changes: - **Fix Metadata Extraction Logic**: Modified MetricsInterceptor and AsyncMetricsInterceptor to strictly extract server-timing data from initial_metadata(). - **Add AFE Metrics Publishing**: Extended MetricsTracer to parse AFE latency (afe;\s*dur=) from the server-timing header alongside GFE metrics. Two new OpenTelemetry instruments (afe_latency and afe_missing_header_count) have been introduced to publish these. - **Support for Streaming RPCs**: Removed the manual toggle in SpannerMetricsTracerFactory. GFE and AFE metrics capture is now always-on whenever OpenTelemetry tracing is enabled. - **Enable Frontend Metrics by Default**: Removed the `gfe_enabled` toggle in `SpannerMetricsTracerFactory`. GFE metrics capture is now always-on whenever OpenTelemetry tracing is enabled. - **Testing**: Added unit tests and a new mockserver test (test_frontend_metrics.py) to ensure both GFE and AFE metrics are correctly published end-to-end. - Local Testing Screenshot: https://screenshot.googleplex.com/image/4tmjwuPjzdttcjW.png
1 parent 562537a commit abf1178

13 files changed

Lines changed: 919 additions & 69 deletions

File tree

packages/google-cloud-spanner/google/cloud/spanner_v1/_helpers.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import logging
2121
import math
2222
import operator
23+
import os
2324
import threading
2425
import time
2526
import uuid
@@ -69,6 +70,11 @@
6970
import random
7071
from typing import List, Tuple
7172

73+
ENABLE_AFE_SERVER_TIMING = (
74+
os.environ.get("SPANNER_DISABLE_AFE_SERVER_TIMING", "").lower() != "true"
75+
and os.environ.get("SPANNER_DISABLE_BUILTIN_METRICS", "").lower() != "true"
76+
)
77+
7278
# Validation error messages
7379
NUMERIC_MAX_SCALE_ERR_MSG = (
7480
"Max scale for a numeric is 9. The requested numeric has scale {}"
@@ -707,6 +713,13 @@ def __init__(self, session):
707713
self._session = session
708714

709715

716+
def _append_routing_headers(metadata):
717+
"""Appends routing and backend-specific headers to the metadata."""
718+
if ENABLE_AFE_SERVER_TIMING:
719+
metadata.append(("x-goog-spanner-enable-afe-server-timing", "true"))
720+
return metadata
721+
722+
710723
def _metadata_with_prefix(prefix, **kw):
711724
"""Create RPC metadata containing a prefix.
712725
@@ -716,7 +729,8 @@ def _metadata_with_prefix(prefix, **kw):
716729
Returns:
717730
List[Tuple[str, str]]: RPC metadata with supplied prefix
718731
"""
719-
return [("google-cloud-resource-prefix", prefix)]
732+
metadata = [("google-cloud-resource-prefix", prefix)]
733+
return _append_routing_headers(metadata)
720734

721735

722736
def _retry_on_aborted_exception(

packages/google-cloud-spanner/google/cloud/spanner_v1/metrics/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Custom Metric Exporter
1+
# Custom Metric Exporter
22
The custom metric exporter, as defined in [metrics_exporter.py](./metrics_exporter.py), is designed to work in conjunction with OpenTelemetry and the Spanner client. It converts data into its protobuf equivalent and sends it to Google Cloud Monitoring.
33

44
## Filtering Criteria
@@ -10,8 +10,10 @@ The exporter filters metrics based on the following conditions, utilizing values
1010
* `attempt_count`
1111
* `operation_latencies`
1212
* `operation_count`
13-
* `gfe_latency`
14-
* `gfe_missing_header_count`
13+
* `gfe_latencies`
14+
* `gfe_connectivity_error_count`
15+
* `afe_latencies`
16+
* `afe_connectivity_error_count`
1517

1618
## Service Endpoint
1719
The exporter sends metrics to the Google Cloud Monitoring [service endpoint](https://cloud.google.com/python/docs/reference/monitoring/latest/google.cloud.monitoring_v3.services.metric_service.MetricServiceClient#google_cloud_monitoring_v3_services_metric_service_MetricServiceClient_create_service_time_series), distinct from the regular client endpoint. This service endpoint operates under a different quota limit than the user endpoint and features an additional server-side filter that only permits a predefined set of metrics to pass through.

packages/google-cloud-spanner/google/cloud/spanner_v1/metrics/constants.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,19 @@
5858
METRIC_NAME_ATTEMPT_LATENCIES = "attempt_latencies"
5959
METRIC_NAME_OPERATION_COUNT = "operation_count"
6060
METRIC_NAME_ATTEMPT_COUNT = "attempt_count"
61-
METRIC_NAME_GFE_LATENCY = "gfe_latency"
62-
METRIC_NAME_GFE_MISSING_HEADER_COUNT = "gfe_missing_header_count"
61+
METRIC_NAME_GFE_LATENCY = "gfe_latencies"
62+
METRIC_NAME_GFE_CONNECTIVITY_ERROR_COUNT = "gfe_connectivity_error_count"
63+
METRIC_NAME_AFE_LATENCY = "afe_latencies"
64+
METRIC_NAME_AFE_CONNECTIVITY_ERROR_COUNT = "afe_connectivity_error_count"
6365
METRIC_NAMES = [
6466
METRIC_NAME_OPERATION_LATENCIES,
6567
METRIC_NAME_ATTEMPT_LATENCIES,
6668
METRIC_NAME_OPERATION_COUNT,
6769
METRIC_NAME_ATTEMPT_COUNT,
70+
METRIC_NAME_GFE_LATENCY,
71+
METRIC_NAME_GFE_CONNECTIVITY_ERROR_COUNT,
72+
METRIC_NAME_AFE_LATENCY,
73+
METRIC_NAME_AFE_CONNECTIVITY_ERROR_COUNT,
6874
]
6975

7076
METRIC_EXPORT_INTERVAL_MS = 60000 # 1 Minute

0 commit comments

Comments
 (0)