Repository navigation
feat(google-api-core): extend ErrorInfo dict accessors, centralize status code extraction, and update StructuredLogFormatter - #18884
Conversation
There was a problem hiding this comment.
Code Review
This pull request enhances client logging and exception handling in google-api-core. It expands recognized logging fields, optimizes field extraction using pre-compiled allowlists, and updates StructuredLogFormatter to unpack record.json_fields and extract allowed fields from vars(record). Additionally, it updates exception properties to support dictionary-based error info and centralizes the _extract_status_code utility. The review feedback suggests reversing the processing order in StructuredLogFormatter so that custom fields in json_fields take precedence over automatically extracted attributes from vars(record).
e4c70cf to
f4d9d6a
Compare
7568958 to
781a900
Compare
f4d9d6a to
3240601
Compare
781a900 to
aeacfb7
Compare
3240601 to
7fad61b
Compare
aeacfb7 to
813aa30
Compare
7fad61b to
858b5dc
Compare
813aa30 to
91cde6b
Compare
858b5dc to
f6ab8ea
Compare
91cde6b to
d6f0e97
Compare
f6ab8ea to
024c8b8
Compare
d6f0e97 to
9bca1d0
Compare
024c8b8 to
b1c49d0
Compare
9bca1d0 to
07e6fa4
Compare
b1c49d0 to
95e34e8
Compare
07e6fa4 to
81e79e2
Compare
0709089 to
c64a257
Compare
| return method_str, service, method | ||
|
|
||
|
|
||
| def _extract_status_code(exc: Optional[BaseException]) -> str: |
There was a problem hiding this comment.
NOTE: To reviewer: we are moving this function out of method.py and into exceptions.py because it is primarily focused on error code extraction.
5a89260 to
0fdb7d0
Compare
a44b814 to
ee5b3cd
Compare
0fdb7d0 to
6062724
Compare
ee5b3cd to
dd50ca8
Compare
|
|
||
|
|
||
| def test_extract_status_code_variations(): | ||
| """Proves that _extract_status_code handles grpc status, callable/non-callable codes, ints, and exceptions.""" |
There was a problem hiding this comment.
This test stack has been improved and moved to test_exceptions.py to align with the movement of the _extract_status_code() method to exceptions.py.
…de extraction, and update StructuredLogFormatter
6062724 to
d573011
Compare
Problem / Context
Internal issue: b/479827845
To support uniform structured error logging and OpenTelemetry telemetry across both gRPC and REST transports in
google-api-core, several foundational utilities need to handle both transport formats consistently:ErrorInfoAccessors:GoogleAPICallError.reason,.domain, and.metadatapreviously assumedself._error_infowas always a protobufErrorInfomessage (as returned by gRPCgoogle.rpc.status_pb2.Status). For REST JSON error payloads,ErrorInfoentries inerror["details"]are parsed as standard Pythondictobjects, causing attribute access (self._error_info.reason) to fail or returnNone.GoogleAPICallErrorand rawgrpc.RpcErrorinstances (_extract_status_code) lived insidegoogle.api_core.gapic_v1.method, preventing reuse by transport-level observability helpers.StructuredLogFormatteronly recognized legacy camelCase fields and matched fields via exact set membership (in _recognized_logging_fields). It did not unpackrecord.json_fieldsor support OpenTelemetry semantic conventions (such asrpc.*,http.*,url.*,server.*,error.type,exception.*, and dynamicgcp.errors.metadata.*keys).Solution
google/api_core/exceptions.py:GoogleAPICallError.reason,.domain, and.metadatato inspectisinstance(self._error_info, dict)first before falling back to protobuf attribute access._extract_status_code(exc, default=None)togoogle.api_core.exceptionsas the single source of truth so bothgapic_v1.methodand transport observability helpers share one status code normalization implementation.google/api_core/gapic_v1/method.py:exceptions._extract_status_codedirectly and removed duplicate status code extraction logic and unit tests frommethod.py/test_method.py.google/api_core/client_logging.py:_recognized_logging_fieldswith OpenTelemetry semantic convention attributes, Google Cloud error domain/metadata fields (gcp.errors.domain,gcp.errors.metadata,gcp.errors.metadata.*), and trace correlation keys (logging.googleapis.com/trace,logging.googleapis.com/spanId,logging.googleapis.com/trace_sampled)._EXACT_FIELDS(frozenset) and_PREFIX_FIELDS(tuple) at module import time and updatedStructuredLogFormatter.formatto extract exact fields viagetattr()(supporting@propertyand class-level attributes), extract dynamic wildcard prefix fields viavars(record), and unpackrecord.json_fieldslast so explicit user-provided structured fields take precedence.tests/unit/test_exceptions.pyandtests/unit/test_client_logging.pyachieving 100% line and branch coverage on modified modules.