Skip to content

[opentelemetry-instrumentation-genai-openai] Record gen_ai.conversation.compacted on Responses spans - #900

Open
eternalcuriouslearner wants to merge 5 commits into
open-telemetry:mainfrom
eternalcuriouslearner:openai-conversation-compacted
Open

eternalcuriouslearner wants to merge 5 commits into
open-telemetry:mainfrom
eternalcuriouslearner:openai-conversation-compacted

Conversation

@eternalcuriouslearner

Copy link
Copy Markdown
Contributor

Sets gen_ai.conversation.compacted to true on OpenAI Responses API spans when the request input or the response output contains a compaction item. Covers sync, async, and streaming, and is independent of content capture. Per semconv, the attribute is left unset rather than false when no compaction is seen.

Anthropic compaction support is handled with the beta.messages instrumentation in #781, which maps compaction blocks to CompactionPart. Anthropic compaction exists only in the beta API, so the non-beta wrapper is unchanged.

Known gaps:

  • The attribute name is a string literal until opentelemetry-semantic-conventions ships the constant.
  • Compaction items are not yet recorded as CompactionPart in captured OpenAI messages; that will be a follow-up PR.

🤖 Generated with Claude Code

Set the attribute when the request input or the response output
contains a compaction item.

Assisted-by: Claude Opus 5.5
Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:43
@eternalcuriouslearner
eternalcuriouslearner requested a review from a team as a code owner October 14, 2026 23:43
Assisted-by: Claude Opus 5.5
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-10-17 01:45 UTC

Respond to 3 review items (e.g. link a commit, explain why not, ask a follow-up):

  • Inline threads: 1, 2, 3
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.
  • Should this be with reviewers? Comment /dashboard route:reviewers to route it to them.
  • Anything wrong — including the routing? Report it with what you expected; it helps us improve the dashboard.

Copilot AI 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.

🟡 Changes recommended

Streams closed or interrupted after an observed compaction item lose the compaction attribute.

1 open finding
What changed in this PR

Adds compaction detection to OpenAI Responses telemetry, independently of content capture.

Changes:

  • Sets gen_ai.conversation.compacted when request or response items contain compaction.
  • Adds extractor, sync, async, and streaming coverage with recorded responses.
  • Documents the addition in a changelog fragment.

Paths below are relative to instrumentation/opentelemetry-instrumentation-genai-openai/.

File Description
tests/​test_utils.py Adds shared compaction fixtures.
tests/​test_responses.py Tests synchronous compaction detection.
tests/​test_response_extractors.py Tests detection and unset behavior.
tests/​test_async_responses.py Tests asynchronous compaction detection.
tests/​cassettes/​test_responses_create_streaming_records_server_compaction[content_mode0].yaml Supplies streaming compaction events.
tests/​cassettes/​test_responses_create_records_server_compaction[content_mode0].yaml Supplies a compacted response.
src/​opentelemetry/​instrumentation/​genai/​openai/​response_extractors.py Detects request and response compaction items.
.changelog/​900.added Announces the telemetry addition.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

A stream closed or interrupted before the terminal response never
delivers it, so record a streamed compaction item as it arrives.

Assisted-by: Claude Opus 5.5

Copilot AI 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.

🟡 Changes recommended

Iterator-based request input can contain compaction items that detection silently misses.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced

Copilot AI 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.

🟢 Approval recommended

The additive detection logic has focused lifecycle coverage and no unresolved blocking findings.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

Comment on lines +237 to +238
if set_stream_event_attributes is not None:
set_stream_event_attributes(self._self_invocation, event)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: FetchResponseStreamWrapper inherits process_event, so a streamed responses.retrieve replay sets conversation_compacted on a FetchResponseInvocation. It has no such field.

Consider adding attribute to fetch span or separating inference from fetching response here.

_skip_if_not_latest()

response = openai_client.responses.create(
model=REASONING_MODEL,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: both compaction cassettes were recorded with gpt-5.4 (and an AsyncOpenAI user agent), but the sync/async tests send REASONING_MODEL (gpt-5.1). They only pass because VCR doesn't match on body. Maybe use gpt-5.4 here, like the conformance scenario does?

Comment on lines +463 to +466
_requires_context_management = pytest.mark.skipif(
not _has_context_management_param,
reason="openai SDK too old to support 'context_management' on Responses.create",
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: _requires_context_management is defined after the first two compaction tests, which repeat the same skipif inline. Same thing in test_async_responses.py. Maybe define it once, above those tests, and use it everywhere?

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

Development

Successfully merging this pull request may close these issues.

3 participants