fix(otel): surface successful-response span rejections - #188
Conversation
fercor-cisco
left a comment
There was a problem hiding this comment.
🤖 This review was generated by the Astra agent (claude-opus-4-8). It may contain mistakes.
Verdict: approve — Well-structured, thoroughly tested change with no correctness bugs found; only minor design observations remain.
Follow-ups
Suggested follow-up work that could be tracked as Jira tickets:
src/splunk_ao/exporter/diagnostics.py:209-231: Rejection detection covers Splunk's JSONvalid/invalidschema and protobufpartial_success.rejected_spans, but not a standard OTLP JSON-encoded partial-success response (partialSuccess.rejectedSpans). This is currently safe becauseOTLPSpanExporteralways sends protobuf and the backend responds in protobuf, so the JSON path only sees Splunk's custom schema. If the exporter is ever configured to negotiate JSON encoding, JSON-encoded OTLP partial-success rejections would be silently missed. Consider handlingpartialSuccess/rejectedSpansin_classify_json_acknowledgementfor completeness.
| deployment = DeploymentMode.O11Y if auth_header[0].lower() == "x-sf-token" else DeploymentMode.STANDALONE | ||
| if _exporter_factory is OTLPSpanExporter: | ||
| delegate: SpanExporter = DiagnosticOTLPSpanExporter( | ||
| endpoint=config.endpoint, headers=config.headers, deployment=deployment, **exporter_kwargs | ||
| ) |
There was a problem hiding this comment.
🟡 minor (design): Deployment mode is re-derived here by string-matching the auth header (auth_header[0].lower() == "x-sf-token"). This is fragile: both build_o11y_exporter and build_standalone_exporter already know the concrete DeploymentMode, so the value could be threaded through build_exporter explicitly instead of inferred from a header name. If the o11y auth header string ever changes, the diagnostic log would silently mislabel the deployment. Consider passing deployment as an explicit parameter.
🤖 Generated by the Astra agent
| if result != SpanExportResult.SUCCESS: | ||
| self._health_tracker.record_unknown() | ||
| return result |
There was a problem hiding this comment.
🟡 minor (design): On any non-SUCCESS result (e.g. HTTP 401/500 or transport error) export_health.healthy is reset to None (UNKNOWN) rather than False. This means a consumer polling export_health cannot distinguish "never exported / transport failing" from "healthy" — only 2xx-acknowledged span rejections flip it to False. This appears intentional (the PR preserves standard OTel handling for non-2xx), but the healthy tri-state semantics (None vs True vs False) are subtle and undocumented on the public ExportHealth dataclass. Worth a docstring note so downstream consumers don't treat healthy is not False as "all good".
🤖 Generated by the Astra agent
|
Thanks for the thorough change — the automated review looks solid and I agree there are no correctness issues. Before I approve, could you address the two minor items below, and make a call on the third? Please fix1. Thread
|
Addressed all three items:
|
fercor-cisco
left a comment
There was a problem hiding this comment.
🤖 This review was generated by the Astra agent (claude-opus-4-8). It may contain mistakes.
Verdict: approve — Correct, well-tested diagnostics that surface 2xx span rejections without failing apps; both prior review threads are resolved in the current code.
Follow-ups
Suggested follow-up work that could be tracked as Shortcut stories:
src/splunk_ao/exporter/diagnostics.py:245-253:_positive_json_integeraccepts onlyintand decimalstrforpartialSuccess.rejectedSpans. Standard OTLP JSON int64 fields are encoded as either a number or a string, so a float-encoded count (e.g.3.0) would be silently ignored and the rejection missed. Not reachable today (the exporter negotiates protobuf), but worth hardening if JSON encoding is ever enabled — e.g. accept an integral float.
Summary
Surface OTLP rejection responses that otherwise appear successful for standalone and O11y exports.
What changed
Tests
2,091 tests passed; Ruff and mypy passed.