Skip to content

Commit d938f30

Browse files
committed
feat(metrics): add support for AFE server timings
1 parent 30e3122 commit d938f30

5 files changed

Lines changed: 42 additions & 14 deletions

File tree

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import inspect
1818
import logging
19+
import os
1920
import re
2021
from typing import Any, Dict
2122

@@ -133,6 +134,12 @@ def intercept(self, invoked_method, request_or_iterator, call_details):
133134

134135
tracer.set_method(method_name)
135136
tracer.record_attempt_start()
137+
138+
if os.environ.get("SPANNER_DISABLE_AFE_SERVER_TIMING", "").lower() != "true":
139+
metadata = list(call_details.metadata or [])
140+
metadata.append(("x-goog-spanner-enable-afe-server-timing", "true"))
141+
call_details = call_details._replace(metadata=metadata)
142+
136143
response = invoked_method(request_or_iterator, call_details)
137144

138145
return _wrap_response(response, tracer)
@@ -215,8 +222,13 @@ async def _async_intercept(
215222

216223
tracer.set_method(method_name)
217224
tracer.record_attempt_start()
218-
response = await continuation(call_details, request_or_iterator)
219225

226+
if os.environ.get("SPANNER_DISABLE_AFE_SERVER_TIMING", "").lower() != "true":
227+
metadata = list(call_details.metadata or [])
228+
metadata.append(("x-goog-spanner-enable-afe-server-timing", "true"))
229+
call_details = call_details._replace(metadata=metadata)
230+
231+
response = await continuation(call_details, request_or_iterator)
220232
if hasattr(response, "__anext__"):
221233
return _AsyncStreamingResponseWrapper(response, tracer)
222234
else:

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
while the helper classes provide additional functionality and context for the metrics being traced.
2020
"""
2121

22+
import os
2223
import re
2324
from datetime import datetime
2425
from typing import Any, Dict, Optional
@@ -425,7 +426,7 @@ def record_gfe_latency(self, latency: int) -> None:
425426
):
426427
return
427428
self._instrument_gfe_latency.record(
428-
amount=latency, attributes=self.client_attributes
429+
amount=latency, attributes=self._create_attempt_otel_attributes()
429430
)
430431

431432
def record_gfe_connectivity_error_count(self) -> None:
@@ -439,7 +440,7 @@ def record_gfe_connectivity_error_count(self) -> None:
439440
):
440441
return
441442
self._instrument_gfe_connectivity_error_count.add(
442-
amount=1, attributes=self.client_attributes
443+
amount=1, attributes=self._create_attempt_otel_attributes()
443444
)
444445

445446
def record_afe_latency(self, latency: int) -> None:
@@ -453,10 +454,11 @@ def record_afe_latency(self, latency: int) -> None:
453454
not self.enabled
454455
or not HAS_OPENTELEMETRY_INSTALLED
455456
or not getattr(self, "_instrument_afe_latency", None)
457+
or os.environ.get("SPANNER_DISABLE_AFE_SERVER_TIMING", "").lower() == "true"
456458
):
457459
return
458460
self._instrument_afe_latency.record(
459-
amount=latency, attributes=self.client_attributes
461+
amount=latency, attributes=self._create_attempt_otel_attributes()
460462
)
461463

462464
def record_afe_connectivity_error_count(self) -> None:
@@ -467,10 +469,11 @@ def record_afe_connectivity_error_count(self) -> None:
467469
not self.enabled
468470
or not HAS_OPENTELEMETRY_INSTALLED
469471
or not getattr(self, "_instrument_afe_connectivity_error_count", None)
472+
or os.environ.get("SPANNER_DISABLE_AFE_SERVER_TIMING", "").lower() == "true"
470473
):
471474
return
472475
self._instrument_afe_connectivity_error_count.add(
473-
amount=1, attributes=self.client_attributes
476+
amount=1, attributes=self._create_attempt_otel_attributes()
474477
)
475478

476479
@staticmethod

packages/google-cloud-spanner/tests/mockserver_tests/test_frontend_metrics.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,20 @@ def test_gfe_missing_header_count_exported(self):
202202
}
203203

204204
self.assertIn(
205-
"gfe_missing_header_count", metrics, f"Metrics: {list(metrics.keys())}"
205+
"gfe_connectivity_error_count",
206+
metrics,
207+
f"Metrics: {list(metrics.keys())}",
206208
)
207-
missing_metric = metrics["gfe_missing_header_count"]
209+
missing_metric = metrics["gfe_connectivity_error_count"]
208210
point = next(iter(missing_metric.data.data_points))
209211
self.assertGreaterEqual(point.value, 1)
210212

211213
self.assertIn(
212-
"afe_missing_header_count", metrics, f"Metrics: {list(metrics.keys())}"
214+
"afe_connectivity_error_count",
215+
metrics,
216+
f"Metrics: {list(metrics.keys())}",
213217
)
214-
afe_missing_metric = metrics["afe_missing_header_count"]
218+
afe_missing_metric = metrics["afe_connectivity_error_count"]
215219
afe_point = next(iter(afe_missing_metric.data.data_points))
216220
self.assertGreaterEqual(afe_point.value, 1)
217221
finally:

packages/google-cloud-spanner/tests/unit/test_metrics_interceptor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,10 @@ def test_intercept_with_tracer(interceptor, mock_tracer_ctx):
113113
],
114114
)
115115

116+
replaced_call_details = call_details._replace.return_value
116117
response = interceptor.intercept(mock_invoked_method, "request", call_details)
117118
assert response == invoked_response
118119
mock_tracer_ctx.record_attempt_start.assert_called()
119120
mock_tracer_ctx.record_attempt_completion.assert_called_once()
120121
mock_tracer_ctx.record_front_end_metrics.assert_called_once()
121-
mock_invoked_method.assert_called_once_with("request", call_details)
122+
mock_invoked_method.assert_called_once_with("request", replaced_call_details)

packages/google-cloud-spanner/tests/unit/test_metrics_tracer.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ def test_record_gfe_latency(metrics_tracer):
243243
assert mock_gfe_latency.record.call_args[1]["amount"] == 100
244244
assert (
245245
mock_gfe_latency.record.call_args[1]["attributes"]
246-
== metrics_tracer.client_attributes
246+
== metrics_tracer._create_attempt_otel_attributes()
247247
)
248248

249249
# Test when tracing is disabled
@@ -266,7 +266,7 @@ def test_record_gfe_connectivity_error_count(metrics_tracer):
266266
assert mock_gfe_connectivity_error_count.add.call_args[1]["amount"] == 1
267267
assert (
268268
mock_gfe_connectivity_error_count.add.call_args[1]["attributes"]
269-
== metrics_tracer.client_attributes
269+
== metrics_tracer._create_attempt_otel_attributes()
270270
)
271271

272272
# Test when tracing is disabled
@@ -336,9 +336,13 @@ def test_record_afe_latency(metrics_tracer):
336336
assert mock_afe_latency.record.call_args[1]["amount"] == 100
337337
assert (
338338
mock_afe_latency.record.call_args[1]["attributes"]
339-
== metrics_tracer.client_attributes
339+
== metrics_tracer._create_attempt_otel_attributes()
340340
)
341341

342+
with mock.patch.dict("os.environ", {"SPANNER_DISABLE_AFE_SERVER_TIMING": "true"}):
343+
metrics_tracer.record_afe_latency(300)
344+
assert mock_afe_latency.record.call_count == 1
345+
342346
metrics_tracer.enabled = False
343347
metrics_tracer.record_afe_latency(200)
344348
assert mock_afe_latency.record.call_count == 1
@@ -355,9 +359,13 @@ def test_record_afe_connectivity_error_count(metrics_tracer):
355359
assert mock_afe_missing.add.call_args[1]["amount"] == 1
356360
assert (
357361
mock_afe_missing.add.call_args[1]["attributes"]
358-
== metrics_tracer.client_attributes
362+
== metrics_tracer._create_attempt_otel_attributes()
359363
)
360364

365+
with mock.patch.dict("os.environ", {"SPANNER_DISABLE_AFE_SERVER_TIMING": "true"}):
366+
metrics_tracer.record_afe_connectivity_error_count()
367+
assert mock_afe_missing.add.call_count == 1
368+
361369
metrics_tracer.enabled = False
362370
metrics_tracer.record_afe_connectivity_error_count()
363371
assert mock_afe_missing.add.call_count == 1

0 commit comments

Comments
 (0)