Skip to content

fix(google-api-core): align HTTP T3 and T4 OpenTelemetry span status and attributes - #18868

Draft
chalmerlowe wants to merge 1 commit into
test/showcase-client-timeout-compliancefrom
fix/otel-http-t3-t4-attributes
Draft

chalmerlowe wants to merge 1 commit into
test/showcase-client-timeout-compliancefrom
fix/otel-http-t3-t4-attributes

Conversation

@chalmerlowe

Copy link
Copy Markdown
Contributor

Summary

Stacked on #18867.

Aligns HTTP Tier 3 (GAPIC client) and Tier 4 (wire attempt) OpenTelemetry span statuses and semantic attributes in google-api-core with the OpenTelemetry HTTP semantic conventions and the Cloud SDK Observability specification.

HTTP Tier 4 (Wire Attempt) Spans

  • Set rpc.system.name = "http": Includes "rpc.system.name": "http" in _TraceContext._build_http_span_attributes so HTTP attempt spans consistently identify the underlying transport system alongside Tier 3 spans.
  • Keep 2xx Span Status UNSET: Removes the explicit StatusCode.OK assignment on < 400 HTTP responses in _TraceContext.record_response so successful client spans remain UNSET per OpenTelemetry semantic conventions (matching gRPC Tier 4 and Tier 3 spans).
  • Populate error.type and status.message on 4xx/5xx Responses: Records error.type as the HTTP status code string (e.g., "400", "503") and extracts status.message from the error response payload when _TraceContext.record_response processes a >= 400 response, ensuring intermediate retry failures (where the exception does not escape _TraceContext.__exit__) still capture full diagnostic metadata.

HTTP Tier 3 (GAPIC Client) Spans

  • Propagate url.template and http.response.status_code to Parent Tier 3 Spans: Captures the active recording parent Tier 3 span in _TraceContext.__enter__ and propagates url.template from the first HTTP attempt and http.response.status_code from the most recent HTTP response.

Files Modified

  • packages/google-api-core/google/api_core/_observability.py
  • packages/google-api-core/tests/unit/test_observability.py
  • packages/gapic-generator/tests/system/telemetry_requirements_matrix.csv

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +634 to +637
for attr in ("text", "reason"):
val = getattr(response, attr, None)
if isinstance(val, str) and val.strip():
return val.strip()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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
  1. Avoid broad except Exception: blocks that silently return None or ignore exceptions. Instead, log the exception (e.g., using logger.warning) to aid in debugging and prevent masking underlying issues.

Comment on lines +788 to +790
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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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
  1. Avoid broad except Exception: blocks that silently return None or ignore exceptions. Instead, log the exception (e.g., using logger.warning) to aid in debugging and prevent masking underlying issues.

@chalmerlowe
chalmerlowe force-pushed the fix/otel-http-t3-t4-attributes branch from f636b0e to a8fbedc Compare October 27, 2026 20:37
@chalmerlowe
chalmerlowe force-pushed the test/showcase-client-timeout-compliance branch 2 times, most recently from 1e109a0 to 08d3f68 Compare October 27, 2026 23:03
@chalmerlowe
chalmerlowe force-pushed the fix/otel-http-t3-t4-attributes branch 2 times, most recently from fd9c5ba to 6855304 Compare October 28, 2026 09:27
@chalmerlowe
chalmerlowe force-pushed the test/showcase-client-timeout-compliance branch 2 times, most recently from 2f1ae8f to 7d82d40 Compare October 28, 2026 09:39
@chalmerlowe
chalmerlowe force-pushed the fix/otel-http-t3-t4-attributes branch from 6855304 to 64d36b7 Compare October 28, 2026 09:39
@chalmerlowe
chalmerlowe force-pushed the test/showcase-client-timeout-compliance branch from 7d82d40 to a0e4ee6 Compare October 28, 2026 21:03
@chalmerlowe
chalmerlowe force-pushed the fix/otel-http-t3-t4-attributes branch from 64d36b7 to 3cac2f0 Compare October 28, 2026 21:03

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant