diff --git a/tests/test_litellm/integrations/test_opentelemetry.py b/tests/test_litellm/integrations/test_opentelemetry.py index 496136b3aea..68ca7bb1ecb 100644 --- a/tests/test_litellm/integrations/test_opentelemetry.py +++ b/tests/test_litellm/integrations/test_opentelemetry.py @@ -526,113 +526,7 @@ class TestOpenTelemetry(unittest.TestCase): # But other attributes from OTEL_RESOURCE_ATTRIBUTES should still be present self.assertEqual(attributes.get("extra.attr"), "extra-value") - def test_handle_success_generates_spans_metrics_and_events(self): - # force both metrics & events on - os.environ["LITELLM_OTEL_INTEGRATION_ENABLE_EVENTS"] = "true" - os.environ["LITELLM_OTEL_INTEGRATION_ENABLE_METRICS"] = "true" - # ─── build in‐memory OTEL providers/exporters ───────────────────────────── - span_exporter = InMemorySpanExporter() - tracer_provider = TracerProvider() - tracer_provider.add_span_processor(SimpleSpanProcessor(span_exporter)) - - log_exporter = InMemoryLogExporter() - logger_provider = OTLoggerProvider() - logger_provider.add_log_record_processor(SimpleLogRecordProcessor(log_exporter)) - - metric_reader = InMemoryMetricReader() - meter_provider = MeterProvider(metric_readers=[metric_reader]) - - # ─── instantiate our OpenTelemetry logger with test providers ─────────── - otel = OpenTelemetry( - tracer_provider=tracer_provider, - meter_provider=meter_provider, - logger_provider=logger_provider, - ) - - # OpenTelemetry attempts to set a global tracer provider, which can be set only once. - # so we hack here to set a local tracer deriver from the provider we created. - otel.tracer = tracer_provider.get_tracer(__name__) - - # ─── minimal input / output for a chat call ────────────────────────────── - start = datetime.utcnow() - end = start + timedelta(seconds=1) - - with open( - os.path.join(self.HERE, "open_telemetry", "data", "captured_kwargs.json") - ) as f: - kwargs = json.load(f) - with open( - os.path.join(self.HERE, "open_telemetry", "data", "captured_response.json") - ) as f: - response_obj = json.load(f) - - # ─── exercise the hook ─────────────────────────────────────────────────── - otel._handle_success(kwargs, response_obj, start, end) - - # ─── assert spans ──────────────────────────────────────────────────────── - spans = self.wait_for_spans(span_exporter, "gen_ai.") - self.assertTrue(spans, "Expected at least one gen_ai span") - - # verify our top‐level litellm_request span is present - names = [s.name for s in spans] - self.assertIn("litellm_request", names) - - # ─── assert metrics ────────────────────────────────────────────────────── - duration_metric = self.wait_for_metric( - metric_reader, "gen_ai.client.operation.duration" - ) - self.assertIsNotNone(duration_metric, "duration histogram was not recorded") - - # check that our model attribute made it onto at least one data point - found_dp = False - if ( - duration_metric - and hasattr(duration_metric, "data") - and hasattr(duration_metric.data, "data_points") - ): - found_dp = any( - dp.attributes.get("gen_ai.request.model") == self.MODEL - for dp in duration_metric.data.data_points - ) - self.assertTrue( - found_dp, "expected gen_ai.request.model attribute on a data point" - ) - - # ─── assert logs ─────────────────────────────────────────────────────── - logs = [] - logs = self.wait_for_log(log_exporter, "gen_ai.") - self.assertTrue(logs, "Expected at least one gen_ai log") - - user_logs = [ - log - for log in logs - if log.log_record.attributes.get("event_name") == "gen_ai.content.prompt" - ] - self.assertTrue(user_logs, "did not see a gen_ai.content.prompt log") - # check log bodies - user_prompt = user_logs[0].log_record.attributes.get("gen_ai.prompt") - self.assertEqual( - "What is the capital of France?", - user_prompt, - "did not see a prompt message", - ) - - choice_logs = [ - log - for log in logs - if log.log_record.attributes.get("event_name") - == "gen_ai.content.completion" - ] - self.assertTrue(choice_logs, "did not see a gen_ai.content.completion event") - - choice_response = choice_logs[0].log_record.body - self.assertIsNotNone(choice_response, "did not see a response message") - self.assertEqual( - "stop", - choice_response.get("finish_reason"), - "did not see expected finish reason", - ) def test_handle_success_spans_only(self): # make sure neither events nor metrics is on