Commit graph

266 commits

Author SHA1 Message Date
Josh Bonczkowski
aeffbb8320 Addressing feedback on accessing default values. Added tests for most of
these cases.
2026-03-13 15:13:39 -04:00
Josh Bonczkowski
3c7d50bef8 Updating the NR event timestamps to more accurately reflect when
the messages were generated.
2026-03-13 14:52:28 -04:00
Josh Bonczkowski
275252009c Addressing feedback.
- When an error occurs, still check if the periodic supportability metric should be emitted
- Added a check to ensure the extension is ready in the error handler to match _process_success
2026-03-13 13:58:20 -04:00
Josh Bonczkowski
babd6bef77 Addressing new feedback.
- Proper handling of time to floats. Created a util method and updated code to use it.
- added the missing guard to ensure the app is enabled
2026-03-13 13:39:52 -04:00
Josh Bonczkowski
c439ce8257 Addressing additional automated feedback.
- Removed a legacy comment about the New Relic header
- Reordered imports in one file
- Switched another file to use the import at the top of the file instead of inline when used
- Added unit tests for untested methods that were identified
2026-03-13 13:25:03 -04:00
Josh Bonczkowski
4f34b6eaae Address reviewer feedback on New Relic integration.
- Fix _record_error_metric to use app.record_custom_metric() instead of
  module-level newrelic.agent.record_custom_metric() so the call works
  outside of an active transaction context
- Remove unreachable except ImportError block in _get_trace_context
- Update stale "23 hours" comment to "27 hours" (matches 97200s threshold)
- Remove commented-out debug code from _process_success
- Fix docs typo: NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_MAX_SAMPLES_STOREDA ->
  NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_MAX_SAMPLES_STORED
- Update TestRecordErrorMetric to verify app.record_custom_metric call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:09:15 -04:00
Josh Bonczkowski
852a25d471 Updating linting and the unit tests that are not running in the CI environment. 2026-03-11 17:44:47 -04:00
Josh Bonczkowski
c6a40767c5 Adding unit tests for the New Relic extension. 2026-03-11 15:53:06 -04:00
Sameer Kankute
3dab62023c Merge branch 'main' into litellm_oss_staging_03_04_2026 2026-03-11 18:31:20 +05:30
mubashir1osmani
6a59ec5ddf
fix: anthropic prompt caching returns a string instead of an int
fix: anthropic prompt caching returns a string instead of an int
2026-03-10 13:51:17 -04:00
milan-berri
336fb0cfeb
fix(security): strip secret_fields from guardrail logging response (#23162)
When guardrails return the full data dict (e.g. guardrails_ai), the
guardrail response logged to spend logs and OTEL traces could contain
data["secret_fields"].raw_headers with plaintext Authorization headers.

This adds a pop("secret_fields") in the guardrail logging path,
matching the existing pattern used by Langfuse and Arize integrations.

Tested: Verified fix removes secret_fields/raw_headers/authorization
from both /spend/logs/ui responses and OTEL trace span attributes.
2026-03-10 08:58:18 -07:00
Chesars
a6cb510703 merge: resolve conflicts between main and litellm_oss_staging_03_04_2026
Resolved 14 file conflicts:
- image_edits.md: combined OpenRouter + Black Forest Labs providers
- utils.py: kept staging's message-level cache_control check
- networking.tsx: kept export on 4 tool interfaces
- tool_management_endpoints.py: kept ToolOutputPolicy import
- Accepted main's version for: schema.prisma, a2a_protocol, mcp_server,
  _types.py, auth_checks.py, db_spend_update_writer, endpoints.py,
  spend_tracking_utils, a2a_endpoints, model_prices backup
2026-03-10 10:45:04 -03:00
mubashir1osmani
23cf360be7 fix: explicit type conversion for prompt caching 2026-03-09 23:53:55 -04:00
Harshit28j
0b67b642cb Fix OTEL span redundancy, orphaned guardrail traces, and missing response IDs
Addresses 4 critical OpenTelemetry span issues in LiteLLM:

Issue #3: Remove redundant attributes from raw_gen_ai_request spans
- Removed self.set_attributes() call that was duplicating all parent span
  attributes (gen_ai.*, metadata.*) onto the raw span
- Raw span now only contains provider-specific llm.{provider}.* attributes
- Reduces storage and eliminates search confusion from duplicate data

Issue #4: Prevent attribute duplication on litellm_proxy_request parent span
- When litellm_request child span exists, removed redundant
  set_attributes() call on the parent proxy span
- Child span already carries all attributes; parent duplication doubles
  storage and complicates search

Issue #5: Fix orphaned guardrail traces
- Guardrail spans were created with context=None when no parent proxy span
  existed, resulting in orphaned root spans (separate trace_id)
- Added _resolve_guardrail_context() helper to ensure guardrails always
  have a valid parent (litellm_request or proxy span)
- Applied fix to both _handle_success and _handle_failure paths

Issue #8: Add gen_ai.response.id for embeddings and image generation
- EmbeddingResponse and ImageResponse types don't have provider response IDs
- Added fallback to standard_logging_payload["id"] (litellm call ID) for
  correlation across LiteLLM UI, Phoenix traces, and provider logs
- Completions still use provider ID (e.g. "chatcmpl-xxx") when available

Tests added:
- TestRawSpanAttributeIsolation: Verify raw span has no gen_ai/metadata attrs
- TestNoParentSpanDuplication: Verify parent span doesn't get duplicated attrs
- TestGuardrailSpanParenting: Verify guardrails are children (not orphaned)
- TestResponseIdFallback: Verify response ID set for all call types

All existing OTEL tests pass (73 passed, 14 pre-existing protocol failures).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-07 04:32:23 +05:30
giulio-leone
7b0ed0ff91 fix: replace sk-fake with safe test key to avoid secret scanner
Replace 'sk-fake' with 'fake-key-for-testing' in websearch interception
tests to prevent false-positive secret scanner triggers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-05 18:29:28 +01:00
giulio-leone
12691dcce3 fix: WebSearch interception fails with thinking enabled + SpendLimit constraint 2026-03-04 22:44:52 +01:00
Aarish Alam
ce54c39051
Bug Fix: auto-inject prompt caching support for Gemini models (#21881)
* add explicit caching to litellm proxy for gemini models via injection

* fix: add missing `supports_function_calling` for deepinfra models

All 55 deepinfra models that had `supports_tool_choice: true` were
missing the `supports_function_calling` flag, causing
`litellm.supports_function_calling()` to incorrectly return False.

Fixes #22619

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Managed batches - Address PR bot comments from #22464

* feat(togetherai): add support for TogetherAI Qwen3.5-397B-A17B model

* Agent Tracing - support context_id based trace id propogation + nested llm calls  (#22626)

* style(ui/): distinguish agent calls from llm calls on ui

* feat: initial grouping working

* feat: set stable contextid for a2a calls - allows for easily passing to downstream llm/mcp calls

* feat(a2a_endpoints.py): fix tracing to avoid recreating logging objects for the same call

allows stable trace id usage

* fix(guardrail_endpoints): handle string ui_type values in _build_field_dict

_build_field_dict unconditionally called .value on ui_type, which crashes
for guardrail configs that use plain strings (e.g. BlockCodeExecutionGuardrailConfigModel
uses "multiselect" and "percentage"). Now checks with hasattr before calling .value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: propagate trace/session id from headers in MCP server calls

Cherry-picked mcp_server/server.py fixes from 6feb9bab: adds
get_chain_id_from_headers to extract x-litellm-trace-id /
x-litellm-session-id from raw headers, and uses it in call_tool
and list_tools to keep spend logs and tracing consistent with A2A.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* [Feat] UI - Add Open in New Tab on leftnav Bar (#22731)

* Add minimal dev_config.yaml for proxy development

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* feat(ui): wrap left nav items in <a> tags for open-in-new-tab support

Nav items are now rendered as <a> elements with proper href attributes,
enabling right-click → 'Open in new tab', Ctrl/Cmd+click, and
middle-click to open any sidebar page in a new browser tab.

Normal clicks continue to use SPA navigation (no full page reload).

Applied to both leftnav.tsx (query-param routing) and Sidebar2.tsx
(Next.js file-based routing).

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* [Feat] Add Tool Policies for AI Gateway  (#22732)

* fix: fix ui render

* fix: fix minor bugs

* refactor: use prisma functions instead of raw sql (safer)

* fix(add-new-tiles-to-tool-policies): allow developer to see what's available

* feat: ensure tool allowlist runs correctly for tool names + mcp's

* refactor: more ui improvements

* feat: working key tool blocking

* feat(tools): show tool logs

* refactor: backend code improvements

* refactor: improve log viewer for tools

* fix: address PR review feedback for tool access control

- Add missing blocked_tools column to root schema.prisma (schema drift)
- Invalidate ToolPolicyRegistry after policy mutations so changes take effect immediately
- Remove dead code: unused get_effective_policies, get_tool_policies_cached, and helpers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: race condition in permission resolution and remove duplicate allowlist check

- Use atomic update_many with object_permission_id=None to prevent concurrent
  requests from creating orphaned permission rows and losing tool blocks
- Remove duplicate allowed_tools enforcement from guardrail (already enforced
  in auth layer via check_tools_allowlist)
- Move inline uuid import to module level

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* update to account for  userAgent

* UI - Add ToolDetails

* input/output policy

* LiteLLM_PolicyAttachmentTable

* LiteLLM_PolicyAttachmentTable

* fix: add _enqueue_tool_registry_upsert

* fix: tool mgmt endpoints

* tool mgmt endpoints

* Update tests/test_litellm/proxy/db/test_tool_registry_writer.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update tests/test_litellm/proxy/db/test_tool_registry_writer.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update tests/test_litellm/proxy/db/test_tool_registry_writer.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: sync root schema.prisma and fix test_tool_registry_writer for input/output policy

- Migrate root schema.prisma LiteLLM_ToolTable from call_policy to
  input_policy/output_policy, add missing user_agent and last_used_at columns
  (now consistent with litellm/proxy/schema.prisma and litellm-proxy-extras)
- Fix SpendLogToolIndex comment across all three schema files
- Fix all call_policy references in test_tool_registry_writer.py:
  swapped update_tool_policy arguments, wrong get_tools_by_names return type
  assertions, _mock_tool_row setting call_policy instead of input_policy

Addresses Greptile review feedback on PR #22732.

Made-with: Cursor

---------

Co-authored-by: Krrish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* feat(proxy): add key_alias, key_hash, requested_model DD APM span tags (#22710)

* feat(proxy): add key_alias, key_hash, requested_model tags to DD APM spans

* refactor(proxy): consolidate DD APM tag helpers into DDSpanTagger class

* refactor(proxy): move DDSpanTagger to its own file litellm/proxy/dd_span_tagger.py

---------

Co-authored-by: liweiguang <codingpunk@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ephrim Stanley <ephrim.stanley@point72.com>
Co-authored-by: Varad Khonde <varadkhonde@gmail.com>
Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-03 20:25:35 -08:00
Harshit Jain
bfdea4227a
Merge pull request #22103 from Harshit28j/litellm_feat_datadog_metrics
feat: ability to trace metrics datadog
2026-02-28 17:25:23 +05:30
Harshit Jain
24aa8bac09
fix req changes test case 2026-02-28 16:31:05 +05:30
Harshit Jain
b6a53fb174
Update tests/test_litellm/integrations/datadog/test_datadog_metrics.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 16:28:48 +05:30
Harshit Jain
04fda9ec4a
Update tests/test_litellm/integrations/datadog/test_datadog_metrics.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 16:28:33 +05:30
Harshit Jain
44dd139941
Update tests/test_litellm/integrations/datadog/test_datadog_metrics.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 16:21:58 +05:30
Harshit Jain
8dc8e826ba
Update tests/test_litellm/integrations/datadog/test_datadog_metrics.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 16:21:41 +05:30
Harshit Jain
9e4cf0e4df
Update tests/test_litellm/integrations/datadog/test_datadog_metrics.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 15:59:36 +05:30
yuneng-jiang
28c77b48c9 fix +Inf user budget metric when metadata max_budget is None
Same bug as team budget: _assemble_user_object fetched user info from DB
but only used budget_reset_at, discarding max_budget. When the key cache
has a stale None for user_max_budget, _safe_get_remaining_budget returns
+Inf. Now falls back to DB max_budget when metadata value is None.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 16:57:31 -08:00
yuneng-jiang
f4e3e016a1 fixing inf budget 2026-02-26 16:30:41 -08:00
Sameer Kankute
1790a6bf82
Merge pull request #21604 from michelligabriele/fix/websearch-thinking-blocks
fix(websearch_interception): preserve thinking blocks in agentic loop follow-up messages
2026-02-26 22:26:38 +05:30
Sameer Kankute
ecbefc0735
Merge pull request #22169 from mubashir1osmani/fix/arize-phoenix-nested-traces
fix: arize phoenix nested traces
2026-02-26 16:24:20 +05:30
mubashir1osmani
96bcee0b0a fix(arize-phoenix): enable nested traces coexistence with otel callback
- ArizePhoenixLogger now creates spans on its own dedicated TracerProvider
  instead of trying to reuse parent spans from the global otel TracerProvider
  (which were invisible in Phoenix since they go to a different exporter)
- Auto-initialize ArizePhoenixLogger when otel callback is configured and
  Phoenix env vars (PHOENIX_API_KEY, PHOENIX_COLLECTOR_*) are detected
- Use exact type check in get_custom_logger_compatible_class to prevent
  ArizePhoenixLogger (subclass) from being returned when looking up otel
- Fix tool_permission guardrail to check non-function tools like
  code_interpreter (previously skipped with `type != "function"`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-26 04:59:17 -05:00
Harshit Jain
10e769a5e4
feat: ability to trace metrics 2026-02-25 22:03:51 +05:30
Ishaan Jaff
e44b9b6b35
feat(prometheus): add opt-in stream label to litellm_proxy_total_requests_metric (#22023)
Set prometheus_emit_stream_label: true in litellm_settings to emit a
stream label (True/False/None) on litellm_proxy_total_requests_metric.

Opt-in to avoid breaking cardinality on existing deployments.
2026-02-24 11:51:42 -08:00
Sameer Kankute
c7aafdf794
Merge pull request #21926 from BerriAI/main
merge main in oss 21 02
2026-02-23 18:17:30 +05:30
Harshit Jain
304862175e
Merge branch 'main' into litellm_fix_langfuse_otel_trace_v2 2026-02-22 19:54:05 +05:30
Harshit28j
1cc185eb16 fix: update opentelemetry with greptile review 2026-02-22 19:53:18 +05:30
Krish Dholakia
9fc6fd647c
Agent Builder - support new experimental agent builder, to ensure agents pass compliance checks (#21817)
* fix: feat: add litellm_system_prompt support

* feat: support new 'litellm_agent' model provider

* feat: ui/ - new agent builder ui

* fix(anthropic/chat/transformation.py): normalize max_tokens if decimal

* feat(agentbuilderview.tsx): run compliance datasets against litellm agent
2026-02-21 15:32:47 -08:00
Darien Kindlund
ca5c109a92
feat: add optional digest mode for Slack alert types (#21683)
Adds per-alert-type digest mode that aggregates duplicate alerts
within a configurable time window and emits a single summary message
with count, start/end timestamps.

Configuration via general_settings.alert_type_config:
  alert_type_config:
    llm_requests_hanging:
      digest: true
      digest_interval: 86400

Digest key: (alert_type, request_model, api_base)
Default interval: 24 hours
Window type: fixed interval

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-21 15:19:17 -08:00
michelligabriele
4630793fb0 fix(websearch_interception): preserve thinking blocks in agentic loop follow-up messages
When extended thinking is enabled, the websearch interception agentic loop
builds a follow-up assistant message with only tool_use blocks. Anthropic's
API requires assistant messages to start with thinking/redacted_thinking
blocks when thinking is enabled, causing a 400 Bad Request.

Extract thinking blocks from the model's initial response, thread them
through the agentic loop, and prepend them to the follow-up assistant
message — matching the pattern used by anthropic_messages_pt in factory.py.

Fixes the error: "Expected 'thinking' or 'redacted_thinking', but found
'tool_use'"
2026-02-19 21:51:00 +01:00
michelligabriele
053ee4826f
fix(websearch_interception): fix pre_call_deployment_hook not triggering via proxy router (#21433)
* fix(websearch_interception): fix pre_call_deployment_hook not triggering via proxy router

Fix provider lookup (check top-level kwargs + fallback to get_llm_provider),
return full kwargs dict instead of partial, and use OpenAI-format tool definition.

* remove unnecessary inline import
2026-02-19 06:38:45 -08:00
Julio Quinteros Pro
db615cd721 chore: resolve merge conflict with main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 19:10:36 -03:00
Julio Quinteros Pro
5fe1dd3ec8 fix(tests): restore initialized_langfuse_clients counter after test
Save and restore litellm.initialized_langfuse_clients around
test_max_langfuse_clients_limit to prevent ordering-dependent failures
in other tests that rely on the counter's value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 19:09:35 -03:00
Julio Quinteros Pro
7b6ffbb52a fix(tests): wrap callbacks cleanup in try/finally and resolve merge conflict
- test_litellm_pre_call_utils.py: wrap test body in try/finally so
  litellm.callbacks is always restored even when an assertion fails,
  addressing greptile review comment
- test_langfuse_otel.py: resolve trivial merge conflict in comment
  ("unpatched" vs "unpatch-ed"), keeping correct spelling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 18:50:17 -03:00
Ishaan Jaff
e8ab773ac4
fix: guard against None metadata in prometheus metrics (#21489)
* fix: guard against None metadata in prometheus metrics

Use get_litellm_metadata_from_kwargs and get_metadata_variable_name_from_kwargs
helpers to properly resolve metadata from both 'metadata' and 'litellm_metadata'
keys, with None safety.

* test: add test for None metadata in prometheus metrics
2026-02-18 12:40:45 -08:00
Harshit Jain
c760318c79
Merge pull request #21449 from Harshit28j/litellm_feat_dataDog_tags
feat(datadog): add 'team' tag to logs, metrics, and cost management
2026-02-18 20:05:32 +05:30
Sameer Kankute
bd0c80406f
Merge pull request #21326 from BerriAI/litellm_oss_staging_02_16_2026
Litellm oss staging 02 16 2026
2026-02-18 17:47:57 +05:30
Sameer Kankute
4bbd15fe41 Fix test_async_post_call_success_hook_includes_client_ip_user_agent 2026-02-18 17:37:23 +05:30
Julio Quinteros Pro
dc003e2a94 fix: prevent sys.modules["langfuse"] import failures in langfuse unit tests
Three test failures caused by the real langfuse SDK import being triggered
at test time:

1. test_langfuse_prompt_management.py: Both tests create LangfusePromptManagement()
   which calls `import langfuse`. Since earlier TestLangfuseUsageDetails tests
   remove sys.modules["langfuse"] via patch.dict teardown, the real langfuse
   import runs and fails on Python 3.14 (pydantic v1 incompatibility).
   Fix: add setup_method/teardown_method to mock sys.modules["langfuse"].

2. test_langfuse.py::test_max_langfuse_clients_limit: Same root cause — creates
   LangFuseLogger() without mocking sys.modules["langfuse"].
   Fix: wrap test body with patch.dict("sys.modules", {"langfuse": mock}).

3. test_langfuse_otel.py::test_extract_langfuse_metadata_with_header_enrichment:
   Replaces sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
   without restoring it, causing patch() in later tests to target the stub
   instead of the real module.
   Fix: use monkeypatch.setitem() which auto-restores after the test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 08:22:23 -03:00
Harshit Jain
954e8d25c6
Add relevant test case 2026-02-18 09:31:44 +05:30
Julio Quinteros Pro
81827be215 fix: prevent sys.modules["langfuse"] import failures in langfuse unit tests
Three test failures caused by the real langfuse SDK import being triggered
at test time:

1. test_langfuse_prompt_management.py: Both tests create LangfusePromptManagement()
   which calls `import langfuse`. Since earlier TestLangfuseUsageDetails tests
   remove sys.modules["langfuse"] via patch.dict teardown, the real langfuse
   import runs and fails on Python 3.14 (pydantic v1 incompatibility).
   Fix: add setup_method/teardown_method to mock sys.modules["langfuse"].

2. test_langfuse.py::test_max_langfuse_clients_limit: Same root cause — creates
   LangFuseLogger() without mocking sys.modules["langfuse"].
   Fix: wrap test body with patch.dict("sys.modules", {"langfuse": mock}).

3. test_langfuse_otel.py::test_extract_langfuse_metadata_with_header_enrichment:
   Replaces sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
   without restoring it, causing patch() in later tests to target the stub
   instead of the real module.
   Fix: use monkeypatch.setitem() which auto-restores after the test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-17 22:33:06 -03:00
Julio Quinteros Pro
32922449a3 fix: restore sys.modules after stub injection in langfuse otel test
test_extract_langfuse_metadata_with_header_enrichment replaced
sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
module but never restored it. This caused subsequent tests using
patch("litellm.integrations.langfuse.langfuse._add_prompt_to_generation_params")
to patch the stub instead of the real module, while _log_langfuse_v2
executed from the real module's globals (unpatched), triggering
ModuleNotFoundError and assertion failures.

Fix: use monkeypatch.setitem() so pytest automatically restores the
original module after the test completes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-17 22:01:21 -03:00
Julio Quinteros Pro
703f02bf99 fix(test): prevent flaky failure in test_log_langfuse_v2_handles_null_usage_values
This test has failed repeatedly in CI with:
  'Expected _add_prompt_to_generation_params to have been called once. Called 0 times.'

Root cause: _add_prompt_to_generation_params is only called when _supports_prompt()
returns True. Under cross-test state contamination in CI (parallel workers),
langfuse_sdk_version can be in an unexpected state, causing _supports_prompt() to
return False and silently skip the call (exception swallowed by the outer try/except).

Fixes:
- Use reset_mock(side_effect=True) so setUp's trace side_effect is cleared and the
  explicit return_value assignment actually takes effect
- Patch _supports_prompt on the logger instance to always return True, making the
  _add_prompt_to_generation_params assertion independent of SDK version state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-17 19:18:12 -03:00