-
-
Notifications
You must be signed in to change notification settings - Fork 11.8k
[Frontend] Add --uvicorn-access-log-exclude-paths option #30175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[Frontend] Add --uvicorn-access-log-exclude-paths option #30175
Conversation
Add a new CLI option to selectively exclude specific paths from
uvicorn access logs. This is useful for filtering out noisy endpoints
like /health and /metrics that are frequently polled by monitoring
systems.
Usage example:
vllm serve model --uvicorn-access-log-exclude-paths /metrics \
--uvicorn-access-log-exclude-paths /health
Fixes vllm-project#29023
Signed-off-by: GeoffreyWang1117 <173976389+GeoffreyWang1117@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new CLI option --uvicorn-access-log-exclude-paths to filter uvicorn access logs, which is a useful feature for reducing log noise from health checks and metrics endpoints. The implementation adds a new UvicornAccessLogFilter class. My review focuses on the correctness of this filter's logic. I've identified a critical issue in the filter method that could lead to incorrect log filtering and have provided a suggestion to make it more robust and correct.
| def filter(self, record: logging.LogRecord) -> bool: | ||
| # Uvicorn access log format: '%(client_addr)s - "%(request_line)s" %(status_code)s' # noqa: E501 | ||
| # The request line contains the method, path, and protocol. | ||
| # Example: '127.0.0.1:12345 - "GET /metrics HTTP/1.1" 200' | ||
| if hasattr(record, "scope"): | ||
| path = record.scope.get("path", "") # type: ignore[union-attr] | ||
| if path in self.exclude_paths: | ||
| return False | ||
| # Fallback: check the message for the path | ||
| # The path appears after the HTTP method (GET, POST, etc.) | ||
| # Pattern: 'METHOD /path ' or 'METHOD /path"' | ||
| message = record.getMessage() | ||
| for path in self.exclude_paths: | ||
| # Match patterns like: "GET /metrics " or "POST /health HTTP" | ||
| if f" {path} " in message or f' {path}"' in message: | ||
| return False | ||
| return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filter method has two issues that can lead to incorrect log filtering:
-
Incorrect Fall-through Logic: When a log record has a
scopeattribute, the path is correctly extracted. However, if this path is not inexclude_paths, the code incorrectly falls through to the string-based fallback logic instead of immediately returningTrue. Thescopeattribute should be treated as the source of truth, and the fallback should only be engaged ifscopeis absent. -
Fragile Fallback for Query Parameters: The fallback logic, which parses the log message as a plain string, does not correctly handle URL query parameters. For instance, a request to
/health?foo=barwill not be filtered even if/healthis specified inexclude_paths, because the string matching for" /health "will fail.
I suggest refactoring the filter method to fix these issues. The proposed change ensures that if scope is present, a definitive filtering decision is made. If not, it uses a more robust fallback mechanism that correctly parses the path from the request line, even with query parameters.
def filter(self, record: logging.LogRecord) -> bool:
# Uvicorn access log format: '%(client_addr)s - "%(request_line)s" %(status_code)s' # noqa: E501
# The request line contains the method, path, and protocol.
# Example: '127.0.0.1:12345 - "GET /metrics HTTP/1.1" 200'
if hasattr(record, "scope"):
path = record.scope.get("path", "") # type: ignore[union-attr]
# The `path` from scope is the source of truth.
# If it's not in exclude_paths, we should log it.
return path not in self.exclude_paths
# Fallback: check the message for the path
# The request line is typically quoted: "METHOD /path?query HTTP/1.1"
# We'll look for the path within the quotes.
message = record.getMessage()
try:
request_line = message.split('"')[1]
path_with_query = request_line.split(" ", 2)[1]
path = path_with_query.split("?", 1)[0]
if path in self.exclude_paths:
return False
except IndexError:
# If the message format is unexpected, we can't reliably filter.
# It's safer to log than to incorrectly filter.
pass
return True
Summary
--uvicorn-access-log-exclude-pathsto selectively exclude specific paths from uvicorn access logs/healthand/metricsthat are frequently polled by monitoring systemsUvicornAccessLogFilterclass that filters log records based on the request pathUsage Example
vllm serve model-name \ --uvicorn-access-log-exclude-paths /metrics \ --uvicorn-access-log-exclude-paths /healthTest plan
UvicornAccessLogFilterclass with various path patterns/metricsand/healthpaths are correctly filtered/v1/chat/completionspass through correctlyFixes #29023
Signed-off-by: GeoffreyWang1117 173976389+GeoffreyWang1117@users.noreply.github.com