Skip to content

OpenAI v2: completion hook support and minor fixes#4315

Merged
lzchen merged 9 commits into
open-telemetry:mainfrom
lmolkova:openai-v2-hook-and-fixes
Apr 30, 2026
Merged

OpenAI v2: completion hook support and minor fixes#4315
lzchen merged 9 commits into
open-telemetry:mainfrom
lmolkova:openai-v2-hook-and-fixes

Conversation

@lmolkova

@lmolkova lmolkova commented Mar 7, 2026

Copy link
Copy Markdown
Member

From spec: https://github.com/open-telemetry/semantic-conventions/blob/v1.40.0/docs/gen-ai/gen-ai-spans.md#uploading-content-to-external-storage

  • Call completion hook in telemetry handler (if passed in constructor)
  • Add should_capture_content method to handler (so that instrumentations don't need to implement their own)
  • Test against latest OpenAI and fix issues (new Omit type for values that were not provided)

@lmolkova lmolkova marked this pull request as ready for review March 7, 2026 23:43
@lmolkova lmolkova requested a review from a team as a code owner March 7, 2026 23:43
@lmolkova lmolkova changed the title OpenAI v2 completion hook support and minor fixes OpenAI v2: completion hook support and minor fixes Mar 7, 2026
Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Outdated
Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Outdated

@MikeGoldsmith MikeGoldsmith left a comment

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.

Sorry for delay getting this reviewed. It got lost and wasn't added to the PR review board.

Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Outdated
Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/span_utils.py Outdated
@github-project-automation github-project-automation Bot moved this to Approved PRs in Python PR digest Apr 13, 2026
@lmolkova lmolkova marked this pull request as draft April 14, 2026 23:09
@lmolkova

Copy link
Copy Markdown
Member Author

I'm going to put it on hold and rebase on top of #4315 given the amount of conflicts it's going to introduce.

@Nik-Reddy Nik-Reddy 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.

Reviewed thoroughly - this is a clean and well-structured refactor. A few observations:

What I like:

  • Moving should_capture_content() into TelemetryHandler is the right call. Individual instrumentations (like the Cohere one I'm adding in #4418) shouldn't need to manage content capture logic themselves - this centralizes it properly.
  • The _maybe_build_llm_event_record rename (from _maybe_emit_llm_event) is a good separation of concerns - building the record vs emitting it lets the completion hook inspect it first.
  • Handling openai.Omit in value_is_set() is a nice forward-compatibility fix for newer OpenAI SDK versions.
  • _openai_response_format_to_output_type correctly maps json_object/json_schema to json.

One question:
In the TelemetryHandler.__init__ content capture logic (lines ~164-177), the fallback for non-experimental mode checks OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT == "true" only. Should this also handle the newer span_only/event_only/span_and_event values for consistency, or is that intentionally left as experimental-only?

Note: This PR supersedes my #4417 (content capture fix) - I'll close that one and reference this instead. Happy to help test once merged.

LGTM overall.

Nik-Reddy
Nik-Reddy approved these changes Apr 15, 2026
@lmolkova lmolkova force-pushed the openai-v2-hook-and-fixes branch from 0ddc569 to 6d21ce7 Compare April 16, 2026 00:05
@lmolkova lmolkova marked this pull request as ready for review April 16, 2026 00:06
@lmolkova

Copy link
Copy Markdown
Member Author

In the TelemetryHandler.init content capture logic (lines ~164-177), the fallback for non-experimental mode checks OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT == "true" only. Should this also handle the newer span_only/event_only/span_and_event values for consistency, or is that intentionally left as experimental-only?

@Nik-Reddy it makes sense, update the PR to support new valued on legacy path

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

Pull request overview

Adds completion hook support to the GenAI telemetry utilities and wires it into the OpenAI v2 instrumentation so consumers can capture inputs/outputs (and optionally stamp log records) after an invocation completes.

Changes:

  • Add completion_hook plumbing to TelemetryHandler and pass it through all invocation types; call the hook on inference/workflow completion.
  • Introduce TelemetryHandler.should_capture_content() to centralize content-capture decisions for instrumentations.
  • Update OpenAI v2 instrumentation/tests for the hook, latest OpenAI SDK (openai==2.26.0), Omit handling, and response_format mapping.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
util/opentelemetry-util-genai/tests/test_handler_completion_hook.py New unit tests for hook invocation, log_record passing, and should_capture_content() behavior.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Adds completion_hook param, computes capture policy, and exposes should_capture_content().
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py Calls completion hook and passes created log record before emission.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py Calls completion hook when workflows finish.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_invocation.py Threads completion_hook through base invocation class.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_tool_invocation.py Plumbs completion_hook through tool invocation construction.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_embedding_invocation.py Plumbs completion_hook through embedding invocation construction.
util/opentelemetry-util-genai/CHANGELOG.md Documents completion hook support in util package.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_completion_hook.py New integration tests verifying hook invocation and content routing.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/requirements.latest.txt Bumps OpenAI SDK used in “latest” tests to 2.26.0.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/conftest.py Minor formatting-only fixture signature change.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py Handles openai.Omit and normalizes response_format output types.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py Uses handler.should_capture_content() in v2 wrappers.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/init.py Loads hook (explicit kwarg preferred, else entry point) and passes into TelemetryHandler.
instrumentation-genai/opentelemetry-instrumentation-openai-v2/CHANGELOG.md Documents hook support and OpenAI v2 fixes.
instrumentation-genai/AGENTS.md Adds guidance on initializing TelemetryHandler with completion hooks.

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

@MikeGoldsmith MikeGoldsmith left a comment

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.

Looks good - I think we need to address a couple of the copilot points:

  • _call_completion_hook() is called inside _apply_finish(), we should add a try/except
  • use GenAiOutputTypeValues.JSON.value instead of "json" in utils.py

@lmolkova lmolkova force-pushed the openai-v2-hook-and-fixes branch from 852a965 to 616f0d0 Compare April 30, 2026 00:37
@lmolkova

lmolkova commented Apr 30, 2026

Copy link
Copy Markdown
Member Author

@MikeGoldsmith thanks! I think completion hook should take care of exceptions - if it comes straight from user, we should be wrapping it into exception handling and then using here. We're going to call it a lot, it's easier to wrap once inside than make every caller handle errors. I can look into this in a separate PR.

UPDATE: Follow up: #4506

Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py Outdated
Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py Outdated

@lzchen lzchen 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.

Overall LGTM but just some questions :)

@github-project-automation github-project-automation Bot moved this from Approved PRs to Reviewed PRs that need fixes in Python PR digest Apr 30, 2026
@github-project-automation github-project-automation Bot moved this from Reviewed PRs that need fixes to Approved PRs in Python PR digest Apr 30, 2026
@lzchen lzchen merged commit 0d1f70b into open-telemetry:main Apr 30, 2026
1496 of 1498 checks passed
@github-project-automation github-project-automation Bot moved this from Approved PRs to Done in Python PR digest Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

8 participants