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.
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
f396cf3 to
37c22d1
Compare
eae240a to
0709089
Compare
37c22d1 to
9db5284
Compare
0709089 to
c64a257
Compare
9db5284 to
0b0e1a9
Compare
c64a257 to
5a89260
Compare
0b0e1a9 to
ea2203b
Compare
5a89260 to
0fdb7d0
Compare
ea2203b to
e05cd41
Compare
0fdb7d0 to
6062724
Compare
e05cd41 to
b275232
Compare
| return method_str, service, method | ||
|
|
||
|
|
||
| def _extract_error_attributes(exc: Optional[BaseException]) -> dict[str, Any]: |
There was a problem hiding this comment.
NOTE: To reviewer: we are moving the _extract_error_attributes() function out of method.py and into _observability.py because it is primarily focused on building out span attributes. The new function is renamed: build_telemetry_error_attributes()
b275232 to
6ed950e
Compare
6ed950e to
030828f
Compare
…t builders in _observability - Move error attribute extraction from gapic_v1.method into _observability.build_telemetry_error_attributes with single-pass exception unwrapping, rpc.response.status_code resolution, native GoogleAPICallError property access, raw gRPC RpcError trailing_metadata parsing, and optional exception.* fields. - Update gapic_v1.method and tests to call _observability.build_telemetry_error_attributes directly without separate _extract_status_code calls. - Add has_opentelemetry() (with module-level caching) and extract_trace_context() in _observability. - Add unit tests achieving 100% statement and branch coverage.
030828f to
6fcf1d7
Compare
6062724 to
d573011
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.method, bypassedGoogleAPICallError's public properties, and required callers to invokeexceptions._extract_status_codeseparately (unwrapping exceptions multiple times per failed RPC). 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 unwrap chained exceptions once, resolverpc.response.status_codeviaexceptions._extract_status_code, and extracterror.type,status.message,gcp.errors.domain,gcp.errors.metadata.*, and optionalexception.*fields usingGoogleAPICallErrorproperties or raw gRPCRpcErrortrailing metadata (google.rpc.status_pb2.Status).google/api_core/gapic_v1/method.py:_extract_error_attributesimplementation and separate_extract_status_codecall with a single call to_observability.build_telemetry_error_attributes.tests/unit/gapic/test_method.pyand added unit tests intests/unit/test_observability.pyachieving 100% line and branch coverage across all new helpers.