fix: normalize frozen Langfuse spans and update SDK test usage - #445
Merged
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OpenTelemetry 1.44 freezes span attributes before end callbacks, so Mobilerun's Langfuse preprocessor could fail with
TypeErrorand leave screenshot data unconverted. Normalize a private export snapshot before the Langfuse SDK processes media, preserving the original ended span for other processors.The internal tracer-provider adapter wraps the processor registered by the public Langfuse client. The SDK still owns one exporter, batching queue, and media-upload pipeline. Start-time metadata enrichment, initialization locking, registration checks, and failed-initialization guards remain in place. Tracing, flush, and shutdown delegate to the existing provider/processor. Span identity, parent, resource, timestamps, status, events, links, instrumentation metadata, and dropped-item counts are preserved.
The three OpenAI SDK regressions came from the shared usage fixture missing the newer required
cache_write_tokensfield. Supply zero when the installed schema defines that field. Keephttpx, SDK response validation, and all existing request-body, multimodal, tool-call, streaming, and token-count assertions. Production token accounting is unchanged.Follow-up to #444. No public API, dependency pins, model defaults, credential storage, package version, README, Portal mapping, or
agent-test-flowschanges. Only two production Python files and two Python test files change.Compatibility validation
Reproduced all four original failures on unchanged main
7ebede7before editing: 4 failed in 13.74s (OpenTelemetry 1.44.0, OpenAI 2.54.0, Langfuse 4.15.1). All four now pass.Four isolated Python 3.13.9 environments, all with Langfuse 4.15.1 and passing
uv pip check:Regression coverage uses real OpenTelemetry and Langfuse SDK processing with a capturing exporter and mocked upload I/O after the real media queue. Screenshot, chat, and completion spans each export once and produce one matching media-upload job. Processors before and after the wrapper receive the same unchanged original span. Additional coverage checks immutable/extended attributes, metadata and dropped counts, concurrent setup, initialization failures before/after registration, duplicate/foreign pipelines, and lifecycle delegation.
Commands:
python -m pytest tests/test_langfuse_v4.py tests/test_grok_api.py tests/test_phoenix_tracing.py tests/test_provider_defaults.py tests/test_openai_oauth_llm.py tests/test_grok_cli.py -q python -m pytest -q python -m black --check --diff . python -m ruff check mobilerun/telemetry/langfuse_processor.py mobilerun/agent/utils/tracing_setup.py tests/test_langfuse_v4.py tests/test_grok_api.py git diff --checkBlack 26.5.1: 185 files unchanged. Relevant Ruff checks and
git diff --check: passed. No test failures or warnings in the final runs.Android 16 smoke
Real
MobileAgentsession onMedium_Phone_API_36.1/emulator-5554, Android 16, Portal 0.7.25, saved Gemini OAuth, implicitgemini-3.8-flash-tiereddefault. Indexed tapping; coordinate tools disabled; maximum 15 steps / 180 seconds. Screenshot capture enabled withMOBILERUN_STREAM_SCREENSHOTS=true, Langfuse screenshots enabled, vision disabled.Passed: 4 steps, 4 tool calls, 24.18 seconds. The agent opened Settings search, typed
display, selected Display & touch, and completed. Independent device trees, dispatched actions, and the final screenshot confirmed Display & touch and Brightness level.The real Langfuse SDK exported 36 unique spans, including 5 screenshot spans with matching media references and exactly 5 mocked upload jobs, one per screenshot span. Upload bytes matched the original screenshot bytes. One client/pipeline, original spans unchanged, and no normalization warnings.
Limits: trace export was captured locally; Langfuse authentication checks and upload network I/O were mocked. This validates SDK processing and queuing, not Langfuse cloud ingestion. The initial UI run passed in 4 steps / 25.57s but omitted screenshot capture; it was excluded from media validation and repeated with capture enabled. All scripts, credentials, screenshots, trees, and logs remain outside the repository. No release was prepared or published.