diff --git a/litellm/integrations/langfuse/langfuse.py b/litellm/integrations/langfuse/langfuse.py index 81855c76854..3ea5a809096 100644 --- a/litellm/integrations/langfuse/langfuse.py +++ b/litellm/integrations/langfuse/langfuse.py @@ -695,9 +695,6 @@ class LangFuseLogger: if output is not None and isinstance(output, str) and level == "ERROR": generation_params["status_message"] = output - if self._supports_completion_start_time(): - generation_params["completion_start_time"] = kwargs.get("completion_start_time", None) - from langfuse import propagate_attributes trace_id_value = trace_params.get("id") @@ -723,8 +720,6 @@ class LangFuseLogger: propagated_trace_name = ( trace_name_value if isinstance(trace_name_value, str) and trace_name_value else trace_name ) - end_time_ns = int(end_time.timestamp() * 1_000_000_000) if end_time is not None else None - with propagate_attributes( user_id=propagated_user_id, session_id=propagated_session_id, @@ -749,8 +744,8 @@ class LangFuseLogger: standard_logging_object=standard_logging_object, ) generation_client = trace.start_observation(**generation_params) - generation_client.end(end_time=end_time_ns) - trace.end(end_time=end_time_ns) + generation_client.end() + trace.end() return trace_context["trace_id"], generation_client.id except Exception: diff --git a/tests/logging_callback_tests/test_langfuse_unit_tests.py b/tests/logging_callback_tests/test_langfuse_unit_tests.py index cbdad0d1061..267088ecc86 100644 --- a/tests/logging_callback_tests/test_langfuse_unit_tests.py +++ b/tests/logging_callback_tests/test_langfuse_unit_tests.py @@ -1,5 +1,6 @@ import os import sys +from datetime import datetime, timedelta sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system-path @@ -339,6 +340,45 @@ def test_langfuse_v4_observations_propagate_trace_attributes(): assert span.attributes["langfuse.trace.metadata.request_type"] == "completion" +def test_langfuse_v4_observations_do_not_use_historical_end_times(): + span_exporter = InMemorySpanExporter() + langfuse_client = Langfuse( + public_key="test-timing-public-key", + secret_key="test-secret-key", + host="https://cloud.langfuse.com", + span_exporter=span_exporter, + ) + logger = object.__new__(LangFuseLogger) + logger.Langfuse = langfuse_client + logger.langfuse_sdk_version = "4.7.0" + end_time = datetime.now() - timedelta(seconds=10) + + logger._log_langfuse_v2( + user_id=None, + metadata={"trace_id": "a" * 32}, + litellm_params={"metadata": {}}, + output={"role": "assistant", "content": "Hello"}, + start_time=end_time - timedelta(seconds=1), + end_time=end_time, + kwargs={ + "model": "openai/test-model", + "call_type": "completion", + "completion_start_time": end_time - timedelta(milliseconds=500), + "standard_logging_object": None, + }, + optional_params={}, + input={"messages": [{"role": "user", "content": "Hello"}]}, + response_obj=None, + level="DEFAULT", + litellm_call_id="call-123", + ) + + langfuse_client.flush() + spans = span_exporter.get_finished_spans() + assert len(spans) == 2 + assert all(span.end_time >= span.start_time for span in spans) + + def test_get_chat_content_for_langfuse(): """ Test that _get_chat_content_for_langfuse correctly extracts content from chat completion responses