chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from ray._common.filters import CoreContextFilter
|
||||
|
||||
|
||||
def _setup_logger(logger_name: str):
|
||||
"""Setup logger given the logger name.
|
||||
|
||||
This function is idempotent and won't set up the same logger multiple times. It will
|
||||
also skip the setup if logger is already setup and has handlers.
|
||||
|
||||
Args:
|
||||
logger_name: logger name used to get the logger.
|
||||
"""
|
||||
logger = logging.getLogger(logger_name)
|
||||
llm_logger = logging.getLogger("ray.llm")
|
||||
|
||||
# Skip setup if the logger already has handlers setup or if the parent (Data
|
||||
# logger) has handlers.
|
||||
if not (logger.handlers or llm_logger.handlers):
|
||||
# Set up stream handler, which logs to console as plaintext.
|
||||
stream_handler = logging.StreamHandler()
|
||||
stream_handler.addFilter(CoreContextFilter())
|
||||
logger.addHandler(stream_handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.propagate = False
|
||||
|
||||
|
||||
def get_logger(name: Optional[str] = None):
|
||||
"""Get a structured logger inherited from the Ray Data logger.
|
||||
|
||||
Loggers by default are logging to stdout, and are expected to be scraped by an
|
||||
external process.
|
||||
"""
|
||||
logger_name = f"ray.llm.{name}"
|
||||
_setup_logger(logger_name)
|
||||
return logging.getLogger(logger_name)
|
||||
@@ -0,0 +1,26 @@
|
||||
import logging
|
||||
|
||||
from ray._private.ray_logging.filters import CoreContextFilter
|
||||
from ray._private.ray_logging.formatters import JSONFormatter
|
||||
|
||||
|
||||
def _configure_stdlib_logging():
|
||||
"""Configures stdlib root logger to make sure stdlib loggers (created as
|
||||
`logging.getLogger(...)`) are using Ray's `JSONFormatter` with Core and Serve
|
||||
context filters.
|
||||
"""
|
||||
|
||||
handler = logging.StreamHandler()
|
||||
handler.addFilter(CoreContextFilter())
|
||||
handler.setFormatter(JSONFormatter())
|
||||
|
||||
root_logger = logging.getLogger()
|
||||
# NOTE: It's crucial we reset all the handlers of the root logger,
|
||||
# to make sure that logs aren't emitted twice
|
||||
root_logger.handlers = []
|
||||
root_logger.addHandler(handler)
|
||||
root_logger.setLevel(logging.INFO)
|
||||
|
||||
|
||||
def setup_logging():
|
||||
_configure_stdlib_logging()
|
||||
@@ -0,0 +1,48 @@
|
||||
"""Utilities for logging."""
|
||||
|
||||
import logging
|
||||
|
||||
import ray
|
||||
|
||||
|
||||
def disable_vllm_custom_ops_logger_on_cpu_nodes():
|
||||
"""This disables a log line in the "vllm._custom_ops" logger on CPU nodes.
|
||||
|
||||
vllm._custom_ops is automatically imported when vllm is imported. It checks
|
||||
for CUDA binaries that don't exist in CPU-only nodes. This makes rayllm
|
||||
raise a scary-looking (but harmless) warning when imported on CPU nodes,
|
||||
such as when running the generate_config.py script or running the
|
||||
build-app task.
|
||||
"""
|
||||
|
||||
class SkipVLLMWarningFilter(logging.Filter):
|
||||
def filter(self, record: logging.LogRecord):
|
||||
"""Only allow CRITICAL logs from the datasets/config.py file."""
|
||||
|
||||
log_fragment = "Failed to import from vllm._C with"
|
||||
|
||||
return log_fragment not in record.getMessage()
|
||||
|
||||
if not ray.is_initialized() or len(ray.get_gpu_ids()) == 0:
|
||||
logging.getLogger("vllm._custom_ops").addFilter(SkipVLLMWarningFilter())
|
||||
|
||||
|
||||
def disable_datasets_logger():
|
||||
"""This disables "datasets" logs from its "config.py" file.
|
||||
|
||||
Upon import, rayllm imports vllm which calls datasets. The datasets package
|
||||
emits a log from its config.py file.
|
||||
|
||||
The file that emits this log uses the root "datasets" logger, so we use a
|
||||
filter to prevent logs from only the config.py file.
|
||||
"""
|
||||
|
||||
class SkipDatasetsConfigLogFilter(logging.Filter):
|
||||
def filter(self, record: logging.LogRecord):
|
||||
"""Only allow CRITICAL logs from the datasets/config.py file."""
|
||||
return (
|
||||
record.levelno >= logging.CRITICAL
|
||||
or "datasets/config.py" not in record.pathname
|
||||
)
|
||||
|
||||
logging.getLogger("datasets").addFilter(SkipDatasetsConfigLogFilter())
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Utilities for telemetry."""
|
||||
|
||||
from threading import Lock
|
||||
from typing import Callable
|
||||
|
||||
DEFAULT_GPU_TYPE = "UNSPECIFIED"
|
||||
|
||||
|
||||
class Once:
|
||||
"""Execute a function exactly once and block all callers until the function returns
|
||||
|
||||
Same as golang's `sync.Once <https://pkg.go.dev/sync#Once>`_
|
||||
|
||||
Took this directly from OpenTelemetry's Python SDK:
|
||||
Ref: https://github.com/open-telemetry/opentelemetry-python/blob
|
||||
/c6fab7d4c339dc5bf9eb9ef2723caad09d69bfca/opentelemetry-api/src/opentelemetry
|
||||
/util/_once.py
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._lock = Lock()
|
||||
self._done = False
|
||||
|
||||
def do_once(self, func: Callable[[], None]) -> bool:
|
||||
"""Execute ``func`` if it hasn't been executed or return.
|
||||
|
||||
Will block until ``func`` has been called by one thread.
|
||||
|
||||
Args:
|
||||
func: The function to execute exactly once.
|
||||
|
||||
Returns:
|
||||
Whether or not ``func`` was executed in this call
|
||||
"""
|
||||
|
||||
# fast path, try to avoid locking
|
||||
if self._done:
|
||||
return False
|
||||
|
||||
with self._lock:
|
||||
if not self._done:
|
||||
func()
|
||||
self._done = True
|
||||
return True
|
||||
return False
|
||||
Reference in New Issue
Block a user