Repository navigation
fix(google-api-core): align HTTP T3 and T4 OpenTelemetry span status and attributes - #18868
chalmerlowe wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request enhances HTTP telemetry tracking by adding rpc.system.name to HTTP spans, extracting detailed error messages from HTTP responses, and propagating status codes and URL templates to parent spans. Unit tests and system requirements matrices have been updated accordingly. The review feedback suggests wrapping the extraction of response attributes (text and reason) and the access of parent span attributes in try-except blocks with warning logging to prevent potential runtime exceptions from crashing the main application flow.
| for attr in ("text", "reason"): | ||
| val = getattr(response, attr, None) | ||
| if isinstance(val, str) and val.strip(): | ||
| return val.strip() |
There was a problem hiding this comment.
Accessing properties like response.text or response.reason can raise exceptions (such as RuntimeError or ConnectionError) if the underlying connection is closed, the stream is exhausted, or during lazy decoding. Since telemetry should never crash the main application flow, we should wrap these attribute accesses in a try-except block. To avoid silently masking underlying issues, we should log the exception as a warning instead of silently passing.
for attr in ("text", "reason"):
try:
val = getattr(response, attr, None)
if isinstance(val, str) and val.strip():
return val.strip()
except Exception as e:
logger.warning("Failed to access response attribute %s: %s", attr, e)References
- Avoid broad
except Exception:blocks that silently returnNoneor ignore exceptions. Instead, log the exception (e.g., usinglogger.warning) to aid in debugging and prevent masking underlying issues.
| parent_attrs = getattr(parent_span, "attributes", None) | ||
| if parent_attrs is None or "url.template" not in parent_attrs: | ||
| parent_span.set_attribute("url.template", self._url_template) |
There was a problem hiding this comment.
Accessing parent_span.attributes and performing a membership check ("url.template" not in parent_attrs) relies on internal implementation details of the OpenTelemetry SDK Span class. If parent_span is a custom span implementation, a mock, or if a future version of the SDK changes this attribute's type, this check could raise a TypeError or other exceptions and crash the application. We should wrap this check in a try-except block to ensure telemetry remains safe and non-blocking, and log any exceptions to prevent silently masking issues.
parent_attrs = getattr(parent_span, "attributes", None)
try:
has_template = parent_attrs is not None and "url.template" in parent_attrs
except Exception as e:
logger.warning("Failed to check url.template in parent span attributes: %s", e)
has_template = False
if not has_template:
parent_span.set_attribute("url.template", self._url_template)References
- Avoid broad
except Exception:blocks that silently returnNoneor ignore exceptions. Instead, log the exception (e.g., usinglogger.warning) to aid in debugging and prevent masking underlying issues.
f636b0e to
a8fbedc
Compare
1e109a0 to
08d3f68
Compare
fd9c5ba to
6855304
Compare
2f1ae8f to
7d82d40
Compare
6855304 to
64d36b7
Compare
7d82d40 to
a0e4ee6
Compare
64d36b7 to
3cac2f0
Compare
Summary
Stacked on #18867.
Aligns HTTP Tier 3 (GAPIC client) and Tier 4 (wire attempt) OpenTelemetry span statuses and semantic attributes in
google-api-corewith the OpenTelemetry HTTP semantic conventions and the Cloud SDK Observability specification.HTTP Tier 4 (Wire Attempt) Spans
rpc.system.name = "http": Includes"rpc.system.name": "http"in_TraceContext._build_http_span_attributesso HTTP attempt spans consistently identify the underlying transport system alongside Tier 3 spans.UNSET: Removes the explicitStatusCode.OKassignment on< 400HTTP responses in_TraceContext.record_responseso successful client spans remainUNSETper OpenTelemetry semantic conventions (matching gRPC Tier 4 and Tier 3 spans).error.typeandstatus.messageon 4xx/5xx Responses: Recordserror.typeas the HTTP status code string (e.g.,"400","503") and extractsstatus.messagefrom the error response payload when_TraceContext.record_responseprocesses a>= 400response, ensuring intermediate retry failures (where the exception does not escape_TraceContext.__exit__) still capture full diagnostic metadata.HTTP Tier 3 (GAPIC Client) Spans
url.templateandhttp.response.status_codeto Parent Tier 3 Spans: Captures the active recording parent Tier 3 span in_TraceContext.__enter__and propagatesurl.templatefrom the first HTTP attempt andhttp.response.status_codefrom the most recent HTTP response.Files Modified
packages/google-api-core/google/api_core/_observability.pypackages/google-api-core/tests/unit/test_observability.pypackages/gapic-generator/tests/system/telemetry_requirements_matrix.csv