Skip to content

Record error.type for HTTP error responses and status codes on successful exports - #5898

Open
kshitizj03 wants to merge 2 commits into
open-telemetry:mainfrom
kshitizj03:fix/5889-exporter-metrics-status-codes
Open

kshitizj03 wants to merge 2 commits into
open-telemetry:mainfrom
kshitizj03:fix/5889-exporter-metrics-status-codes

Conversation

@kshitizj03

@kshitizj03 kshitizj03 commented Nov 7, 2026 •

Copy link
Copy Markdown

Description

HTTP exports that received a 4xx/5xx response without raising an exception were recorded on the
exporter self-observability metrics without error.type, so they looked like successful exports.
ExporterMetrics.export_operation only derived error.type from an exception. Also,
http.response.status_code and rpc.response.status_code were only recorded on failed exports.

Changes:

  • ExportResult gets an error_type field for failures without an exception. The OTLP HTTP span,
    log and metric exporters set it to the response status code (e.g. "503"), so it is recorded on
    both otel.sdk.exporter.{span,log,metric_data_point}.exported and
    otel.sdk.exporter.operation.duration.
  • ExportResult.error_attrs is renamed to response_attrs (private module) and is now set whenever a
    response is received, so http.response.status_code (2xx) and rpc.response.status_code (OK)
    are recorded on otel.sdk.exporter.operation.duration for successful exports too.

Fixes #5889

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • I am a human and not a bot
  • I have run tox -e precommit (ran ruff check + ruff format --check on changed files)
  • I have run tox -e typecheck (ran pyright 1.1.405 on the changed packages: no errors in changed files)
  • I have run the relevant tests and linting tox environments (pytest for otlp-common,
    otlp-proto-http, otlp-proto-grpc: all pass; new tests fail without the fix)

I used AI assistance (Claude) for this change and reviewed it myself.

🤖 Generated with Claude Code

…sful exports

HTTP exports that got a 4xx/5xx response without a Python exception
were recorded on the exporter self-observability metrics without
`error.type`, the same as a successful export, because
`ExporterMetrics.export_operation` only derived `error.type` from an
exception. `http.response.status_code` and `rpc.response.status_code`
were also only recorded on failed exports.

`ExportResult` now has an `error_type` field for failures without an
exception, which the OTLP HTTP exporters set to the response status
code (e.g. "503"). `error_attrs` is renamed to `response_attrs` and is
set whenever a response is received, so the status code is recorded on
`otel.sdk.exporter.operation.duration` for successful HTTP (2xx) and
gRPC (OK) exports as well.

Fixes open-telemetry#5889

Assisted-by: Claude Opus 5.5
@kshitizj03
kshitizj03 requested a review from a team as a code owner November 7, 2026 17:06
Assisted-by: Claude Opus 5.5
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-11-09 10:28 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@chrikrah chrikrah left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kshitizj03 as far as I can see this can be merged: with the five source files reverted to 66ec883, the new tests fail (7 failures across the two runs below).

non-blocking: one failure still counts as exported. When a shutdown interrupts a retry, http.py:239 returns _ExportResult(False, None, None, None), so error_type stays None. Returning the last status_code and export_error there would give that batch the 503 that started the retry. A separate PR fits it best.

$ OTEL_PYTHON_SDK_INTERNAL_METRICS_ENABLED=true python ot_probe.py   # 7ef7b64; OTLPSpanExporter with _client.export patched to return _ExportResult(False, None, None, None)
export -> SpanExportResult.FAILURE
otel.sdk.exporter.span.exported {'otel.component.type': 'otlp_http_span_exporter', 'otel.component.name': 'otlp_http_span_exporter/0', 'server.address': 'localhost', 'server.port': 4318} 1

$ pytest exporter/opentelemetry-exporter-otlp-proto-http/tests -q   # 7ef7b64, Python 3.13.5
121 passed, 139 subtests passed in 2.28s
$ pytest exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py -q
27 passed in 13.21s

$ (same two runs, the five changed source files from 66ec883, head tests)
6 failed, 115 passed, 139 subtests passed in 1.86s
1 failed, 26 passed in 13.63s     # KeyError: 'rpc.response.status_code'
# not run: tox, the other exporter packages

Want me to send that follow-up once this lands?

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

Status: No status

Development

Successfully merging this pull request may close these issues.

OTLP exporters record HTTP 4xx/5xx failures without error.type and omit response status code attributes on successful HTTP and gRPC exports

2 participants