"vllm/vscode:/vscode.git/clone" did not exist on "26d041930978aa0d06d565d3e1f1e41686ad0c90"
logger.py 4.86 KB
Newer Older
1
2
3
# Adapted from
# https://github.com/skypilot-org/skypilot/blob/86dc0f6283a335e4aa37b3c10716f90999f48ab6/sky/sky_logging.py
"""Logging configuration for vLLM."""
4
import datetime
Woosuk Kwon's avatar
Woosuk Kwon committed
5
import logging
6
import os
7
import sys
8
from functools import partial
9
from typing import Optional
Woosuk Kwon's avatar
Woosuk Kwon committed
10

11
12
VLLM_CONFIGURE_LOGGING = int(os.getenv("VLLM_CONFIGURE_LOGGING", "1"))

Woosuk Kwon's avatar
Woosuk Kwon committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
_FORMAT = "%(levelname)s %(asctime)s %(filename)s:%(lineno)d] %(message)s"
_DATE_FORMAT = "%m-%d %H:%M:%S"


class NewLineFormatter(logging.Formatter):
    """Adds logging prefix to newlines to align multi-line messages."""

    def __init__(self, fmt, datefmt=None):
        logging.Formatter.__init__(self, fmt, datefmt)

    def format(self, record):
        msg = logging.Formatter.format(self, record)
        if record.message != "":
            parts = msg.split(record.message)
            msg = msg.replace("\n", "\r\n" + parts[0])
        return msg


Woosuk Kwon's avatar
Woosuk Kwon committed
31
_root_logger = logging.getLogger("vllm")
32
_default_handler: Optional[logging.Handler] = None
Woosuk Kwon's avatar
Woosuk Kwon committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52


def _setup_logger():
    _root_logger.setLevel(logging.DEBUG)
    global _default_handler
    if _default_handler is None:
        _default_handler = logging.StreamHandler(sys.stdout)
        _default_handler.flush = sys.stdout.flush  # type: ignore
        _default_handler.setLevel(logging.INFO)
        _root_logger.addHandler(_default_handler)
    fmt = NewLineFormatter(_FORMAT, datefmt=_DATE_FORMAT)
    _default_handler.setFormatter(fmt)
    # Setting this will avoid the message
    # being propagated to the parent logger.
    _root_logger.propagate = False


# The logger is initialized when the module is imported.
# This is thread-safe as the module is only imported once,
# guaranteed by the Python GIL.
53
54
if VLLM_CONFIGURE_LOGGING:
    _setup_logger()
Woosuk Kwon's avatar
Woosuk Kwon committed
55
56
57


def init_logger(name: str):
58
59
    # Use the same settings as above for root logger
    logger = logging.getLogger(name)
60
    logger.setLevel(os.getenv("LOG_LEVEL", "DEBUG"))
61

62
    if VLLM_CONFIGURE_LOGGING:
63
64
65
66
        if _default_handler is None:
            raise ValueError(
                "_default_handler is not set up. This should never happen!"
                " Please open an issue on Github.")
67
68
        logger.addHandler(_default_handler)
        logger.propagate = False
69
    return logger
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85


logger = init_logger(__name__)


def _trace_calls(log_path, root_dir, frame, event, arg=None):
    if event in ['call', 'return']:
        # Extract the filename, line number, function name, and the code object
        filename = frame.f_code.co_filename
        lineno = frame.f_lineno
        func_name = frame.f_code.co_name
        if not filename.startswith(root_dir):
            # only log the functions in the vllm root_dir
            return
        # Log every function call or return
        try:
86
87
88
89
90
91
92
93
94
95
            last_frame = frame.f_back
            if last_frame is not None:
                last_filename = last_frame.f_code.co_filename
                last_lineno = last_frame.f_lineno
                last_func_name = last_frame.f_code.co_name
            else:
                # initial frame
                last_filename = ""
                last_lineno = 0
                last_func_name = ""
96
97
98
            with open(log_path, 'a') as f:
                if event == 'call':
                    f.write(f"{datetime.datetime.now()} Call to"
99
100
101
                            f" {func_name} in {filename}:{lineno}"
                            f" from {last_func_name} in {last_filename}:"
                            f"{last_lineno}\n")
102
103
                else:
                    f.write(f"{datetime.datetime.now()} Return from"
104
105
106
                            f" {func_name} in {filename}:{lineno}"
                            f" to {last_func_name} in {last_filename}:"
                            f"{last_lineno}\n")
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
        except NameError:
            # modules are deleted during shutdown
            pass
    return partial(_trace_calls, log_path, root_dir)


def enable_trace_function_call(log_file_path: str,
                               root_dir: Optional[str] = None):
    """
    Enable tracing of every function call in code under `root_dir`.
    This is useful for debugging hangs or crashes.
    `log_file_path` is the path to the log file.
    `root_dir` is the root directory of the code to trace. If None, it is the
    vllm root directory.

    Note that this call is thread-level, any threads calling this function
    will have the trace enabled. Other threads will not be affected.
    """
    logger.warning(
        "VLLM_TRACE_FUNCTION is enabled. It will record every"
        " function executed by Python. This will slow down the code. It "
        "is suggested to be used for debugging hang or crashes only.")
129
    logger.info("Trace frame log is saved to %s", log_file_path)
130
131
132
133
    if root_dir is None:
        # by default, this is the vllm root directory
        root_dir = os.path.dirname(os.path.dirname(__file__))
    sys.settrace(partial(_trace_calls, log_file_path, root_dir))