Skip to content

[google-genai] Restore caller context between stream reads - #899

Open
JacksonWeber wants to merge 7 commits into
open-telemetry:mainfrom
JacksonWeber:jacksonweber-next-genai-issue
Open

JacksonWeber wants to merge 7 commits into
open-telemetry:mainfrom
JacksonWeber:jacksonweber-next-genai-issue

Conversation

@JacksonWeber

@JacksonWeber JacksonWeber commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Description

Move invocation suspension into the shared SyncStreamWrapper and AsyncStreamWrapper constructors, removing duplicate Google GenAI and tool-wrapper calls. Keep spans current only during stream reads and cleanup, with shared sync/async regressions and 24 Google GenAI API cases covering generation, Interactions model/agent calls, and fetch streams.

Part of #872. This shared fix also applies to other invocation-backed stream wrappers. The separate stream-timing metrics fix is not included.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How has this been tested?

Dependencies were restored with pip after uv TLS failures. The Python 3.10 environment was manually pinned to the declared dependency floors, including Google GenAI 1.32.0. Disabling suspension makes all eight shared constructor regression cases fail.

  • Package tests, focused lower-bound regressions, utility typechecking, API compatibility, and pre-commit checks passed
# Passed: 1261 tests, 240 skipped, 27 subtests
.\.venv\Scripts\python.exe -m pytest util\opentelemetry-util-genai\tests instrumentation\opentelemetry-instrumentation-google-genai\tests --ignore=instrumentation\opentelemetry-instrumentation-google-genai\tests\test_conformance.py --import-mode=importlib --vcr-record=none -o addopts= -o log_cli=false -q --tb=short

# Passed: 134 tests, 18 skipped because Interactions is unavailable
.\.tox\py310-test-instrumentation-google-genai-oldest\Scripts\python.exe -m pytest instrumentation\opentelemetry-instrumentation-google-genai\tests\test_stream_context.py util\opentelemetry-util-genai\tests\test_stream.py --import-mode=importlib --vcr-record=none -o addopts= -o log_cli=false -q --tb=short

# Passed: 0 errors
python -m pyright --pythonpath .venv\Scripts\python.exe util\opentelemetry-util-genai\src

# Passed
python -m tox -e check-util-api --runner virtualenv

# Passed
python -m tox -e precommit --runner virtualenv

Full-repository typechecking and conformance were not rerun for this follow-up.

Checklist

See CONTRIBUTING.md
for the style guide, changelog guidance, and more.

  • Followed the style guidelines of this project
  • Changelog updated if the change requires an entry
  • Unit tests added
  • Documentation updated

Suspend streamed invocations between reads and cover lifecycle context isolation across supported SDK versions.

Assisted-by: GPT-6 Astra

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d301755c-099c-497f-87d9-8f86611e71ff
@JacksonWeber
JacksonWeber requested a review from a team as a code owner October 14, 2026 23:12
Copilot AI balanced review requested due to automatic review settings October 14, 2026 23:12
@opentelemetry-pr-dashboard

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

Copy link
Copy Markdown

Pull request dashboard status

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

Merge when ready.

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.

Assisted-by: GPT-6 Astra

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d301755c-099c-497f-87d9-8f86611e71ff

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 focused changes follow the shared stream lifecycle contract and include comprehensive regression coverage, with no identified blockers.

0 open findings

What changed in this PR

Restores caller context between Google GenAI stream reads while preserving invocation context during iteration and cleanup.

Changes:

  • Suspends invocations in all six sync/async stream wrappers.
  • Adds 72 lifecycle regression cases and includes them in the SDK v2 test environment.
  • Documents the fix in a changelog fragment.
File Description
tox.ini Runs context regression tests against SDK v2.
instrumentation/​opentelemetry-instrumentation-google-genai/​tests/​test_stream_context.py Covers context restoration across stream lifecycle paths.
instrumentation/​opentelemetry-instrumentation-google-genai/​src/​opentelemetry/​instrumentation/​google_genai/​interactions.py Suspends Interactions and fetch stream invocations.
instrumentation/​opentelemetry-instrumentation-google-genai/​src/​opentelemetry/​instrumentation/​google_genai/​generate_content.py Suspends sync/async generation stream invocations.
instrumentation/​opentelemetry-instrumentation-google-genai/​.changelog/​899.fixed Records the context-restoration fix.

🧠 Review effort: Balanced


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

],
)
async def test_stream_context(
monkeypatch: pytest.MonkeyPatch,

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.

why does simply calling invocation.suspend in the initializer of these stream wrappers require such a massive test ? Can we have a simpler test or can you explain why this is necessary ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I’ve trimmed it to context restoration for sync and async calls. Tests should be simpler now, let me know if they look good now

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.

its better but i dont love all the branching logic.. maybe split it in 2 1 for sync 1 with async ? I think that'd get rid of a lot of it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Split it into separate sync and async tests, should remove the branching logic

JacksonWeber and others added 2 commits October 15, 2026 09:30
Assisted-by: GPT-6 Astra
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 503e6eda-a2b7-4bfe-a357-70d47b0e7aa1
Keep context restoration checks for sync and async APIs on completion and caller or stream errors. Leave generic stream lifecycle edge cases to the shared wrapper tests.

Assisted-by: GPT-6 Astra
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 503e6eda-a2b7-4bfe-a357-70d47b0e7aa1
JacksonWeber and others added 3 commits October 15, 2026 13:41
Assisted-by: GPT-6 Astra

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 76e8b89b-ab68-42de-abed-7045507fb0d5
Keep synchronous and asynchronous stream lifecycle tests separate while preserving operation, error, and context assertions.

Assisted-by: GPT-6 Astra

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d301755c-099c-497f-87d9-8f86611e71ff

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.

4 participants