[diffusion] UX: suppress excessive logging from httpx and httpcore (#20452)
This commit is contained in:
@@ -11,6 +11,7 @@ in a functional manner, reducing the need for explicit parameter passing.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import pprint
|
import pprint
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
@@ -21,11 +22,11 @@ import PIL.Image
|
|||||||
import torch
|
import torch
|
||||||
|
|
||||||
from sglang.multimodal_gen.configs.sample.sampling_params import SamplingParams
|
from sglang.multimodal_gen.configs.sample.sampling_params import SamplingParams
|
||||||
from sglang.multimodal_gen.runtime.server_args import (
|
from sglang.multimodal_gen.runtime.server_args import ServerArgs
|
||||||
ServerArgs,
|
from sglang.multimodal_gen.runtime.utils.logging_utils import (
|
||||||
_sanitize_for_logging,
|
_sanitize_for_logging,
|
||||||
|
init_logger,
|
||||||
)
|
)
|
||||||
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
|
||||||
from sglang.multimodal_gen.runtime.utils.perf_logger import RequestMetrics
|
from sglang.multimodal_gen.runtime.utils.perf_logger import RequestMetrics
|
||||||
from sglang.multimodal_gen.utils import align_to
|
from sglang.multimodal_gen.utils import align_to
|
||||||
|
|
||||||
@@ -288,20 +289,22 @@ class Req:
|
|||||||
else:
|
else:
|
||||||
target_width = -1
|
target_width = -1
|
||||||
|
|
||||||
# sanitize prompts for info-level logging
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
sanitized_prompt = _sanitize_for_logging(self.prompt, key_hint="prompt")
|
display_prompt = self.prompt
|
||||||
sanitized_neg_prompt = _sanitize_for_logging(
|
display_neg_prompt = self.negative_prompt
|
||||||
self.negative_prompt, key_hint="negative_prompt"
|
else:
|
||||||
)
|
display_prompt = _sanitize_for_logging(self.prompt, key_hint="prompt")
|
||||||
|
display_neg_prompt = _sanitize_for_logging(
|
||||||
|
self.negative_prompt, key_hint="negative_prompt"
|
||||||
|
)
|
||||||
|
|
||||||
# Log sampling parameters
|
|
||||||
debug_str = f"""Sampling params:
|
debug_str = f"""Sampling params:
|
||||||
width: {target_width}
|
width: {target_width}
|
||||||
height: {target_height}
|
height: {target_height}
|
||||||
num_frames: {self.num_frames}
|
num_frames: {self.num_frames}
|
||||||
fps: {self.fps}
|
fps: {self.fps}
|
||||||
prompt: {sanitized_prompt}
|
prompt: {display_prompt}
|
||||||
neg_prompt: {sanitized_neg_prompt}
|
neg_prompt: {display_neg_prompt}
|
||||||
seed: {self.seed}
|
seed: {self.seed}
|
||||||
infer_steps: {self.num_inference_steps}
|
infer_steps: {self.num_inference_steps}
|
||||||
num_outputs_per_prompt: {self.num_outputs_per_prompt}
|
num_outputs_per_prompt: {self.num_outputs_per_prompt}
|
||||||
@@ -313,7 +316,7 @@ class Req:
|
|||||||
save_output: {self.save_output}
|
save_output: {self.save_output}
|
||||||
output_file_path: {self.output_file_path()}
|
output_file_path: {self.output_file_path()}
|
||||||
""" # type: ignore[attr-defined]
|
""" # type: ignore[attr-defined]
|
||||||
logger.debug(debug_str)
|
logger.info(debug_str)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import inspect
|
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
@@ -37,6 +36,7 @@ from sglang.multimodal_gen.runtime.utils.common import (
|
|||||||
is_valid_ipv6_address,
|
is_valid_ipv6_address,
|
||||||
)
|
)
|
||||||
from sglang.multimodal_gen.runtime.utils.logging_utils import (
|
from sglang.multimodal_gen.runtime.utils.logging_utils import (
|
||||||
|
_sanitize_for_logging,
|
||||||
configure_logger,
|
configure_logger,
|
||||||
init_logger,
|
init_logger,
|
||||||
)
|
)
|
||||||
@@ -49,119 +49,6 @@ from sglang.multimodal_gen.utils import (
|
|||||||
logger = init_logger(__name__)
|
logger = init_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _is_torch_tensor(obj: Any) -> tuple[bool, Any]:
|
|
||||||
"""Return (is_tensor, torch_module_or_None) without importing torch at module import time."""
|
|
||||||
try:
|
|
||||||
import torch # type: ignore
|
|
||||||
|
|
||||||
return isinstance(obj, torch.Tensor), torch
|
|
||||||
except Exception:
|
|
||||||
return False, None
|
|
||||||
|
|
||||||
|
|
||||||
def _sanitize_for_logging(obj: Any, key_hint: str | None = None) -> Any:
|
|
||||||
"""Recursively convert objects to JSON-serializable forms for concise logging.
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
- Drop any field/dict key named 'param_names_mapping'.
|
|
||||||
- Render Enums using their value.
|
|
||||||
- Render torch.Tensor as a compact summary; if key name is 'scaling_factor', include stats.
|
|
||||||
- Dataclasses are expanded to dicts and sanitized recursively.
|
|
||||||
- Callables/functions are rendered as their qualified name.
|
|
||||||
- Redact sensitive fields like 'prompt' and 'negative_prompt' (only show length).
|
|
||||||
- Fallback to str(...) for unknown types.
|
|
||||||
"""
|
|
||||||
# Handle simple types quickly
|
|
||||||
if obj is None or isinstance(obj, (str, int, float, bool)):
|
|
||||||
# redact sensitive prompt fields
|
|
||||||
if key_hint in ("prompt", "negative_prompt"):
|
|
||||||
if isinstance(obj, str):
|
|
||||||
return f"<redacted, len={len(obj)}>"
|
|
||||||
return obj
|
|
||||||
|
|
||||||
# Enum -> value for readability
|
|
||||||
if isinstance(obj, Enum):
|
|
||||||
return obj.value
|
|
||||||
|
|
||||||
# torch.Tensor handling (lazy import)
|
|
||||||
is_tensor, torch_mod = _is_torch_tensor(obj)
|
|
||||||
if is_tensor:
|
|
||||||
try:
|
|
||||||
ten = obj.detach().cpu()
|
|
||||||
if key_hint == "scaling_factor":
|
|
||||||
# Provide a compact, single-line summary for scaling_factor
|
|
||||||
stats = {
|
|
||||||
"shape": list(ten.shape),
|
|
||||||
"dtype": str(ten.dtype),
|
|
||||||
}
|
|
||||||
# Stats might fail for some dtypes; guard individually
|
|
||||||
try:
|
|
||||||
stats["min"] = float(ten.min().item())
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
stats["max"] = float(ten.max().item())
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
stats["mean"] = float(ten.float().mean().item())
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return {"tensor": "scaling_factor", **stats}
|
|
||||||
# Generic tensor summary
|
|
||||||
return {"tensor": True, "shape": list(ten.shape), "dtype": str(ten.dtype)}
|
|
||||||
except Exception:
|
|
||||||
return "<tensor>"
|
|
||||||
|
|
||||||
# Dataclasses -> dict
|
|
||||||
if dataclasses.is_dataclass(obj):
|
|
||||||
result: dict[str, Any] = {}
|
|
||||||
for f in dataclasses.fields(obj):
|
|
||||||
if not f.repr:
|
|
||||||
continue
|
|
||||||
name = f.name
|
|
||||||
if "names_mapping" in name: # drop noisy mappings
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
value = getattr(obj, name)
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
result[name] = _sanitize_for_logging(value, key_hint=name)
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Dicts -> sanitize keys/values; drop 'param_names_mapping'
|
|
||||||
if isinstance(obj, dict):
|
|
||||||
result_dict: dict[str, Any] = {}
|
|
||||||
for k, v in obj.items():
|
|
||||||
try:
|
|
||||||
key_str = str(k)
|
|
||||||
except Exception:
|
|
||||||
key_str = "<key>"
|
|
||||||
if key_str == "param_names_mapping":
|
|
||||||
continue
|
|
||||||
result_dict[key_str] = _sanitize_for_logging(v, key_hint=key_str)
|
|
||||||
return result_dict
|
|
||||||
|
|
||||||
# Sequences/Sets -> list
|
|
||||||
if isinstance(obj, (list, tuple, set)):
|
|
||||||
return [_sanitize_for_logging(x, key_hint=key_hint) for x in obj]
|
|
||||||
|
|
||||||
# Functions / Callables -> qualified name
|
|
||||||
try:
|
|
||||||
if inspect.isroutine(obj) or inspect.isclass(obj):
|
|
||||||
module = getattr(obj, "__module__", "")
|
|
||||||
qn = getattr(obj, "__qualname__", getattr(obj, "__name__", "<callable>"))
|
|
||||||
return f"{module}.{qn}" if module else qn
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Fallback: string representation
|
|
||||||
try:
|
|
||||||
return str(obj)
|
|
||||||
except Exception:
|
|
||||||
return "<unserializable>"
|
|
||||||
|
|
||||||
|
|
||||||
class Backend(str, Enum):
|
class Backend(str, Enum):
|
||||||
"""
|
"""
|
||||||
Enumeration for different model backends.
|
Enumeration for different model backends.
|
||||||
|
|||||||
@@ -6,12 +6,15 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import dataclasses
|
||||||
import datetime
|
import datetime
|
||||||
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from enum import Enum
|
||||||
from functools import lru_cache, partial
|
from functools import lru_cache, partial
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
from types import MethodType
|
from types import MethodType
|
||||||
@@ -281,6 +284,107 @@ def init_logger(name: str) -> _SGLDiffusionLogger:
|
|||||||
logger = init_logger(__name__)
|
logger = init_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_torch_tensor(obj: Any) -> tuple[bool, Any]:
|
||||||
|
"""Return (is_tensor, torch_module_or_None) without importing torch at module import time."""
|
||||||
|
try:
|
||||||
|
import torch # type: ignore
|
||||||
|
|
||||||
|
return isinstance(obj, torch.Tensor), torch
|
||||||
|
except Exception:
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_for_logging(obj: Any, key_hint: str | None = None) -> Any:
|
||||||
|
"""Recursively convert objects to JSON-serializable forms for concise logging.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- Drop any field/dict key named 'param_names_mapping'.
|
||||||
|
- Render Enums using their value.
|
||||||
|
- Render torch.Tensor as a compact summary; if key name is 'scaling_factor', include stats.
|
||||||
|
- Dataclasses are expanded to dicts and sanitized recursively.
|
||||||
|
- Callables/functions are rendered as their qualified name.
|
||||||
|
- Redact sensitive fields like 'prompt' and 'negative_prompt' (only show length).
|
||||||
|
- Fallback to str(...) for unknown types.
|
||||||
|
"""
|
||||||
|
if obj is None or isinstance(obj, (str, int, float, bool)):
|
||||||
|
if key_hint in ("prompt", "negative_prompt"):
|
||||||
|
if isinstance(obj, str):
|
||||||
|
return f"<redacted, len={len(obj)}>"
|
||||||
|
return obj
|
||||||
|
|
||||||
|
if isinstance(obj, Enum):
|
||||||
|
return obj.value
|
||||||
|
|
||||||
|
is_tensor, torch_mod = _is_torch_tensor(obj)
|
||||||
|
if is_tensor:
|
||||||
|
try:
|
||||||
|
ten = obj.detach().cpu()
|
||||||
|
if key_hint == "scaling_factor":
|
||||||
|
stats = {
|
||||||
|
"shape": list(ten.shape),
|
||||||
|
"dtype": str(ten.dtype),
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
stats["min"] = float(ten.min().item())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
stats["max"] = float(ten.max().item())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
stats["mean"] = float(ten.float().mean().item())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return {"tensor": "scaling_factor", **stats}
|
||||||
|
return {"tensor": True, "shape": list(ten.shape), "dtype": str(ten.dtype)}
|
||||||
|
except Exception:
|
||||||
|
return "<tensor>"
|
||||||
|
|
||||||
|
if dataclasses.is_dataclass(obj):
|
||||||
|
result: dict[str, Any] = {}
|
||||||
|
for f in dataclasses.fields(obj):
|
||||||
|
if not f.repr:
|
||||||
|
continue
|
||||||
|
name = f.name
|
||||||
|
if "names_mapping" in name:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
value = getattr(obj, name)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
result[name] = _sanitize_for_logging(value, key_hint=name)
|
||||||
|
return result
|
||||||
|
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
result_dict: dict[str, Any] = {}
|
||||||
|
for k, v in obj.items():
|
||||||
|
try:
|
||||||
|
key_str = str(k)
|
||||||
|
except Exception:
|
||||||
|
key_str = "<key>"
|
||||||
|
if key_str == "param_names_mapping":
|
||||||
|
continue
|
||||||
|
result_dict[key_str] = _sanitize_for_logging(v, key_hint=key_str)
|
||||||
|
return result_dict
|
||||||
|
|
||||||
|
if isinstance(obj, (list, tuple, set)):
|
||||||
|
return [_sanitize_for_logging(x, key_hint=key_hint) for x in obj]
|
||||||
|
|
||||||
|
try:
|
||||||
|
if inspect.isroutine(obj) or inspect.isclass(obj):
|
||||||
|
module = getattr(obj, "__module__", "")
|
||||||
|
qn = getattr(obj, "__qualname__", getattr(obj, "__name__", "<callable>"))
|
||||||
|
return f"{module}.{qn}" if module else qn
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
return str(obj)
|
||||||
|
except Exception:
|
||||||
|
return "<unserializable>"
|
||||||
|
|
||||||
|
|
||||||
def _trace_calls(log_path, root_dir, frame, event, arg=None):
|
def _trace_calls(log_path, root_dir, frame, event, arg=None):
|
||||||
if event in ["call", "return"]:
|
if event in ["call", "return"]:
|
||||||
# Extract the filename, line number, function name, and the code object
|
# Extract the filename, line number, function name, and the code object
|
||||||
@@ -403,6 +507,8 @@ def globally_suppress_loggers():
|
|||||||
"python_multipart.multipart",
|
"python_multipart.multipart",
|
||||||
"filelock",
|
"filelock",
|
||||||
"urllib3",
|
"urllib3",
|
||||||
|
"httpx",
|
||||||
|
"httpcore",
|
||||||
]
|
]
|
||||||
|
|
||||||
for name in target_names:
|
for name in target_names:
|
||||||
@@ -457,7 +563,7 @@ def log_generation_timer(
|
|||||||
"Processing prompt %d/%d: %s",
|
"Processing prompt %d/%d: %s",
|
||||||
request_idx,
|
request_idx,
|
||||||
total_requests,
|
total_requests,
|
||||||
prompt[:100],
|
_sanitize_for_logging(prompt, key_hint="prompt"),
|
||||||
)
|
)
|
||||||
|
|
||||||
timer = GenerationTimer()
|
timer = GenerationTimer()
|
||||||
|
|||||||
Reference in New Issue
Block a user