main
py 105 lines 4.09 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 # ruff: noqa
4 # type: ignore
5 import pytest
6 import time
7 from opentelemetry.sdk.environment_variables import OTEL_EXPORTER_OTLP_TRACES_INSECURE
8
9 from vllm import LLM, SamplingParams
10 from vllm.distributed import cleanup_dist_env_and_memory
11 from vllm.platforms import current_platform
12 from vllm.tracing import SpanAttributes
13
14 # Import shared fixtures from the tracing conftest
15 from tests.tracing.conftest import ( # noqa: F401
16 FAKE_TRACE_SERVER_ADDRESS,
17 FakeTraceService,
18 trace_service,
19 )
20
21
22 def test_traces(
23 monkeypatch: pytest.MonkeyPatch,
24 trace_service: FakeTraceService,
25 ):
26 with monkeypatch.context() as m:
27 m.setenv(OTEL_EXPORTER_OTLP_TRACES_INSECURE, "true")
28 # The fake OTLP server starts gRPC worker threads before the engine
29 # core is launched. gRPC's C-core is not fork-safe and can segfault
30 # if forked.
31 m.setenv("VLLM_WORKER_MULTIPROC_METHOD", "spawn")
32
33 sampling_params = SamplingParams(
34 temperature=0.01,
35 top_p=0.1,
36 max_tokens=256,
37 )
38 model = "facebook/opt-125m"
39 llm = None
40 try:
41 llm = LLM(
42 model=model,
43 otlp_traces_endpoint=FAKE_TRACE_SERVER_ADDRESS,
44 gpu_memory_utilization=0.3,
45 disable_log_stats=False,
46 )
47 prompts = ["This is a short prompt"]
48 outputs = llm.generate(prompts, sampling_params=sampling_params)
49 print(f"test_traces outputs is : {outputs}")
50
51 # Wait for the "llm_request" span to be exported.
52 # The BatchSpanProcessor batches spans and exports them periodically,
53 # so we need to wait specifically for the llm_request span to appear.
54 timeout = 15
55 deadline = time.time() + timeout
56 llm_request_spans = []
57 while time.time() < deadline:
58 all_spans = trace_service.get_all_spans()
59 llm_request_spans = [s for s in all_spans if s["name"] == "llm_request"]
60 if llm_request_spans:
61 break
62 time.sleep(0.5)
63
64 assert len(llm_request_spans) == 1, (
65 f"Expected exactly 1 'llm_request' span, but got "
66 f"{len(llm_request_spans)}. "
67 f"All span names: {[s['name'] for s in all_spans]}"
68 )
69
70 attributes = llm_request_spans[0]["attributes"]
71 # assert attributes.get(SpanAttributes.GEN_AI_RESPONSE_MODEL) == model
72 assert (
73 attributes.get(SpanAttributes.GEN_AI_REQUEST_ID)
74 == outputs[0].request_id
75 )
76 assert (
77 attributes.get(SpanAttributes.GEN_AI_REQUEST_TEMPERATURE)
78 == sampling_params.temperature
79 )
80 assert (
81 attributes.get(SpanAttributes.GEN_AI_REQUEST_TOP_P)
82 == sampling_params.top_p
83 )
84 assert (
85 attributes.get(SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS)
86 == sampling_params.max_tokens
87 )
88 assert attributes.get(SpanAttributes.GEN_AI_REQUEST_N) == sampling_params.n
89 assert attributes.get(SpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS) == len(
90 outputs[0].prompt_token_ids
91 )
92 completion_tokens = sum(len(o.token_ids) for o in outputs[0].outputs)
93 assert (
94 attributes.get(SpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS)
95 == completion_tokens
96 )
97
98 assert attributes.get(SpanAttributes.GEN_AI_LATENCY_TIME_IN_QUEUE) > 0
99 assert attributes.get(SpanAttributes.GEN_AI_LATENCY_TIME_TO_FIRST_TOKEN) > 0
100 assert attributes.get(SpanAttributes.GEN_AI_LATENCY_E2E) > 0
101 finally:
102 if llm is not None:
103 shutdown_timeout = 60.0 if current_platform.is_rocm() else 5.0
104 llm.llm_engine.engine_core.shutdown(timeout=shutdown_timeout)
105 cleanup_dist_env_and_memory()