Repository navigation
feat(google-api-core): centralize telemetry error attribute and trace context builders in _observability - #18893
chalmerlowe wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request centralizes and enhances telemetry and error attribute extraction by introducing has_opentelemetry, extract_trace_context, and _build_telemetry_error_attributes helpers in _observability.py, replacing the redundant _extract_error_attributes implementation in method.py, and adding comprehensive unit tests. However, a critical issue was identified in _observability.py where exceptions._extract_status_code is called with an unsupported default keyword argument, which will cause a TypeError at runtime; this should be resolved using a logical or fallback instead.
| # a low-cardinality error.type. Use canonical status code name, fallback status_code, or exception class name. | ||
| from google.api_core import exceptions | ||
|
|
||
| resolved_code = exceptions._extract_status_code(target_exc, default=status_code) |
There was a problem hiding this comment.
The helper function exceptions._extract_status_code does not accept a default keyword argument in google-api-core. Calling it with default=status_code will raise a TypeError at runtime. You can safely achieve the same fallback behavior by using the or operator.
| resolved_code = exceptions._extract_status_code(target_exc, default=status_code) | |
| resolved_code = exceptions._extract_status_code(target_exc) or status_code |
5659093 to
25b8205
Compare
f4d9d6a to
3240601
Compare
25b8205 to
d05a1be
Compare
3240601 to
7fad61b
Compare
d05a1be to
703466a
Compare
7fad61b to
858b5dc
Compare
703466a to
915abfc
Compare
858b5dc to
f6ab8ea
Compare
915abfc to
4f0a450
Compare
f6ab8ea to
024c8b8
Compare
4f0a450 to
9d4a85f
Compare
024c8b8 to
b1c49d0
Compare
9d4a85f to
59e1573
Compare
b1c49d0 to
95e34e8
Compare
59e1573 to
f396cf3
Compare
95e34e8 to
eae240a
Compare
…t builders in _observability
f396cf3 to
37c22d1
Compare
eae240a to
0709089
Compare
Problem / Context
To emit consistent error metadata and trace correlation across both GAPIC method wrappers (
gapic_v1.method) and transport-level interceptors (_observability),google-api-coreneeds shared helpers that work identically on wrappedGoogleAPICallErrorexceptions and raw gRPCRpcErrorexceptions (beforegapic_v1.method'swrap_errorsruns):_extract_error_attributespreviously lived insidegoogle.api_core.gapic_v1.methodand only inspected wrappedGoogleAPICallErrorproperties (.reason,.domain,.metadata,.message). At the L4 gRPC interceptor boundary, failures are still rawgrpc.RpcError/grpc.aio.AioRpcErrorinstances whoseErrorInfodetails live intrailing_metadata()(grpc-status-details-bin) and whose message comes fromexc.details().logging.googleapis.com/trace,logging.googleapis.com/spanId,logging.googleapis.com/trace_sampled) extracted from an active OpenTelemetry span without raising if OpenTelemetry is not installed or the span is non-recording.Solution
google/api_core/_observability.py:has_opentelemetry()with module-level caching to check whetheropentelemetry.traceis importable.extract_trace_context(span=None)to extracttrace_id(32-char lowercase hex),span_id(16-char lowercase hex), andtrace_sampled(bool) from an explicit or active OpenTelemetry span._build_telemetry_error_attributes(exc, status_code=None, status_message=None, include_exception=False)to extracterror.type,status.message,gcp.errors.domain,gcp.errors.metadata, and optionalexception.*fields from bothGoogleAPICallErrorand raw gRPCRpcErrortrailing metadata (google.rpc.status_pb2.Status).google/api_core/gapic_v1/method.py:_extract_error_attributes = _observability._build_telemetry_error_attributes, removing 73 lines of duplicated error-attribute extraction logic.tests/unit/test_observability.pyachieving 100% line and branch coverage across all new helpers.