Files
wehub-resource-sync 94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

234 lines
7.1 KiB
Python

"""
Test request logging for diffusion models.
Tests the --log-requests CLI flags for diffusion model serving,
verifying that request logs are correctly written to stdout and files.
"""
import json
import os
import shutil
import tempfile
import time
from pathlib import Path
import pytest
from openai import OpenAI
from sglang.multimodal_gen.test.server.test_server_utils import ServerManager
from sglang.multimodal_gen.test.test_utils import get_dynamic_server_port
# Test models and prompts
IMAGE_MODEL = "Efficient-Large-Model/Sana_600M_512px_diffusers"
IMAGE_PROMPT = "A beautiful sunset over mountains, oil painting style"
VIDEO_MODEL = "Wan-AI/Wan2.1-T2V-1.3B-Diffusers"
VIDEO_PROMPT = "A cat playing with a ball"
# Timeout settings
BASE_TIMEOUT = float(os.environ.get("SGLANG_TEST_OPENAI_REQUEST_TIMEOUT_SECS", "600"))
POLL_INTERVAL = 1.0
def _start_server(model: str, log_format: str):
"""Start server with request logging enabled."""
temp_dir = tempfile.mkdtemp()
port = get_dynamic_server_port()
extra_args = (
f"--log-requests "
f"--log-requests-level 2 "
f"--log-requests-format {log_format} "
f"--log-requests-target stdout {temp_dir} "
f"--strict-ports"
)
wait_deadline = float(os.environ.get("SGLANG_TEST_WAIT_SECS", "1200"))
manager = ServerManager(
model=model,
port=port,
wait_deadline=wait_deadline,
extra_args=extra_args,
)
ctx = manager.start()
ctx.temp_dir = temp_dir
return ctx
def _cleanup_server(ctx):
"""Cleanup server and temp directory."""
ctx.cleanup()
shutil.rmtree(ctx.temp_dir, ignore_errors=True)
def _create_client(ctx) -> OpenAI:
"""Create OpenAI client for the server."""
return OpenAI(
api_key="test",
base_url=f"http://localhost:{ctx.port}/v1",
timeout=BASE_TIMEOUT,
)
def _wait_for_video_completion(client: OpenAI, video_id: str, timeout: float):
"""Poll video job until completion."""
deadline = time.time() + timeout
while time.time() < deadline:
page = client.videos.list()
item = next((v for v in page.data if v.id == video_id), None)
status = getattr(item, "status", None) if item else None
if status == "completed":
return True
if status in ("failed", "cancelled", "deleted"):
pytest.fail(f"Video job {video_id} ended with status={status}")
time.sleep(POLL_INTERVAL)
pytest.fail(f"Video job {video_id} did not complete in {timeout}s")
def _verify_json_logs(content: str):
"""Verify JSON logs contain request.received and request.finished events."""
has_received = False
has_finished = False
for line in content.splitlines():
idx = line.find("{")
if idx == -1:
continue
try:
data = json.loads(line[idx:])
except json.JSONDecodeError:
continue
if data.get("event") == "request.received":
has_received = True
elif data.get("event") == "request.finished":
has_finished = True
assert has_received, "request.received event not found"
assert has_finished, "request.finished event not found"
def _verify_text_logs(content: str, prompt: str):
"""Verify text logs contain Receive, prompt, and Finish markers."""
assert "Receive:" in content, "'Receive:' not found"
assert prompt in content, f"Prompt '{prompt}' not found"
assert "Finish:" in content, "'Finish:' not found"
@pytest.fixture(scope="class")
def image_text_server():
"""Server with text-format logging for image model."""
ctx = _start_server(IMAGE_MODEL, "text")
yield ctx
_cleanup_server(ctx)
@pytest.fixture(scope="class")
def image_json_server():
"""Server with JSON-format logging for image model."""
ctx = _start_server(IMAGE_MODEL, "json")
yield ctx
_cleanup_server(ctx)
@pytest.fixture(scope="class")
def video_text_server():
"""Server with text-format logging for video model."""
ctx = _start_server(VIDEO_MODEL, "text")
yield ctx
_cleanup_server(ctx)
@pytest.fixture(scope="class")
def video_json_server():
"""Server with JSON-format logging for video model."""
ctx = _start_server(VIDEO_MODEL, "json")
yield ctx
_cleanup_server(ctx)
class TestImageRequestLoggerText:
"""Test text-format request logging for image models."""
def test_request_logging(self, image_text_server):
ctx = image_text_server
client = _create_client(ctx)
# Image generation is synchronous, waits for completion
client.images.generate(prompt=IMAGE_PROMPT, size="256x256", n=1)
# Verify stdout and file logs
stdout = ctx.log_tail(lines=500)
_verify_text_logs(stdout, IMAGE_PROMPT[:30])
logs = list(Path(ctx.temp_dir).glob("*.log"))
assert logs, "No log files found"
_verify_text_logs("".join(f.read_text() for f in logs), IMAGE_PROMPT[:30])
class TestImageRequestLoggerJson:
"""Test JSON-format request logging for image models."""
def test_request_logging(self, image_json_server):
ctx = image_json_server
client = _create_client(ctx)
# Image generation is synchronous, waits for completion
client.images.generate(prompt=IMAGE_PROMPT, size="256x256", n=1)
# Verify stdout and file logs
stdout = ctx.log_tail(lines=500)
_verify_json_logs(stdout)
logs = list(Path(ctx.temp_dir).glob("*.log"))
assert logs, "No log files found"
_verify_json_logs("".join(f.read_text() for f in logs))
class TestVideoRequestLoggerText:
"""Test text-format request logging for video models."""
def test_request_logging(self, video_text_server):
ctx = video_text_server
client = _create_client(ctx)
# Video generation is async - create job and poll until completion
job = client.videos.create(
prompt=VIDEO_PROMPT,
size="832x480",
extra_body={"num_frames": 5, "num_inference_steps": 10},
)
_wait_for_video_completion(client, job.id, BASE_TIMEOUT * 2)
# Verify stdout and file logs
stdout = ctx.log_tail(lines=500)
_verify_text_logs(stdout, VIDEO_PROMPT[:20])
logs = list(Path(ctx.temp_dir).glob("*.log"))
assert logs, "No log files found"
_verify_text_logs("".join(f.read_text() for f in logs), VIDEO_PROMPT[:20])
class TestVideoRequestLoggerJson:
"""Test JSON-format request logging for video models."""
def test_request_logging(self, video_json_server):
ctx = video_json_server
client = _create_client(ctx)
# Video generation is async - create job and poll until completion
job = client.videos.create(
prompt=VIDEO_PROMPT,
size="832x480",
extra_body={"num_frames": 5, "num_inference_steps": 10},
)
_wait_for_video_completion(client, job.id, BASE_TIMEOUT * 2)
# Verify stdout and file logs
stdout = ctx.log_tail(lines=500)
_verify_json_logs(stdout)
logs = list(Path(ctx.temp_dir).glob("*.log"))
assert logs, "No log files found"
_verify_json_logs("".join(f.read_text() for f in logs))