mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-12 03:48:56 +00:00
Moves 58 legacy nodes (cyberark, logging callback manager, langfuse handler and helpers, SQS, app crypto, bedrock nova and invoke, cloudflare, litellm_proxy, nvidia nim, replicate, triton, convert_dict_to_response, get_model_info, vcr live-call probe) into the tests/unit files that mirror the modules they exercise. Calls that reached huggingface.co, langfuse or 0.0.0.0 are refused at the HTTP boundary with respx. Tests that need credentials, a license, a spawned server, sleeps, a subprocess, or assert nothing stay in their legacy files
61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
from litellm.litellm_core_utils.litellm_logging import DynamicLoggingCache
|
|
|
|
|
|
def test_langfuse_e2e_sync(monkeypatch):
|
|
"""A sync completion must reach langfuse over the wire, not just build a span.
|
|
|
|
v4 exports OTLP over ``requests`` rather than the v2 ingestion endpoint over
|
|
httpx, so this stands up a real receiver and asserts langfuse posted to it.
|
|
"""
|
|
import threading
|
|
import time
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
|
import litellm
|
|
from litellm import completion
|
|
from litellm.integrations.langfuse.langfuse import LangFuseLogger
|
|
from litellm.integrations.langfuse.langfuse_prompt_management import langfuse_client_init
|
|
from litellm.litellm_core_utils import litellm_logging
|
|
|
|
received_paths = []
|
|
|
|
class _Receiver(BaseHTTPRequestHandler):
|
|
def do_POST(self):
|
|
received_paths.append(self.path)
|
|
self.rfile.read(int(self.headers.get("Content-Length") or 0))
|
|
self.send_response(200)
|
|
self.send_header("Content-Length", "0")
|
|
self.end_headers()
|
|
|
|
def log_message(self, *args):
|
|
pass
|
|
|
|
server = HTTPServer(("127.0.0.1", 0), _Receiver)
|
|
threading.Thread(target=server.serve_forever, daemon=True).start()
|
|
monkeypatch.setenv("LANGFUSE_HOST", f"http://127.0.0.1:{server.server_port}")
|
|
monkeypatch.setenv("LANGFUSE_PUBLIC_KEY", "pk-e2e-sync")
|
|
monkeypatch.setenv("LANGFUSE_SECRET_KEY", "sk-e2e-sync")
|
|
monkeypatch.setattr(litellm, "success_callback", ["langfuse"])
|
|
monkeypatch.setattr(litellm_logging, "langFuseLogger", None)
|
|
monkeypatch.setattr(litellm_logging, "in_memory_dynamic_logger_cache", DynamicLoggingCache())
|
|
monkeypatch.setattr(litellm_logging, "_in_memory_loggers", [])
|
|
langfuse_client_init.cache_clear()
|
|
|
|
try:
|
|
completion(
|
|
model="openai/my-fake-endpoint",
|
|
messages=[{"role": "user", "content": "hello from litellm"}],
|
|
stream=False,
|
|
mock_response="Hello from litellm 2",
|
|
)
|
|
for logger in litellm.logging_callback_manager.get_all_callbacks():
|
|
if isinstance(logger, LangFuseLogger):
|
|
logger.flush()
|
|
deadline = time.time() + 10
|
|
while not received_paths and time.time() < deadline:
|
|
time.sleep(0.1)
|
|
finally:
|
|
server.shutdown()
|
|
|
|
assert received_paths, "langfuse exported nothing"
|
|
assert all(path.endswith("/api/public/otel/v1/traces") for path in received_paths)
|