mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
Merge 9c4b678fa1 into eed82023c5
This commit is contained in:
commit
d9e60f2cb7
@ -33,6 +33,9 @@ Usage:
|
||||
"""
|
||||
import logging
|
||||
import cherrypy
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
from cherrypy.process.servers import ServerAdapter
|
||||
from cheroot.wsgi import Server as WSGIServer
|
||||
from cheroot.ssl.builtin import BuiltinSSLAdapter
|
||||
@ -41,6 +44,28 @@ from typing import Any, Tuple, Optional, Dict
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class CherryPyAccessFilter(logging.Filter):
|
||||
"""Rate-limits access log to one entry per endpoint per 120 s.
|
||||
Non-200 responses always pass through."""
|
||||
_PATH_RE = re.compile(r'"[A-Z]+\s+(/[^\s]*)')
|
||||
|
||||
def __init__(self, interval: float = 120.0) -> None:
|
||||
super().__init__()
|
||||
self.interval = interval
|
||||
self._last: Dict[str, float] = {}
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
msg = record.getMessage()
|
||||
if '" 200 ' not in msg:
|
||||
return True
|
||||
key = (m := self._PATH_RE.search(msg)) and m.group(1) or msg
|
||||
now = time.monotonic()
|
||||
with self._lock:
|
||||
if now - self._last.get(key, 0.0) < self.interval:
|
||||
return False
|
||||
self._last[key] = now
|
||||
return True
|
||||
|
||||
class CherryPyErrorFilter(logging.Filter):
|
||||
"""
|
||||
@ -138,6 +163,18 @@ class CherryPyMgr:
|
||||
if not has_filter:
|
||||
error_log.addFilter(CherryPyErrorFilter())
|
||||
|
||||
access_filter = CherryPyAccessFilter()
|
||||
|
||||
access_log = logging.getLogger('cherrypy.access')
|
||||
|
||||
if not any(isinstance(f, CherryPyAccessFilter) for f in access_log.filters):
|
||||
access_log.addFilter(access_filter)
|
||||
|
||||
for name, obj in logging.Logger.manager.loggerDict.items():
|
||||
if name.startswith('cherrypy.access') and isinstance(obj, logging.Logger):
|
||||
if not any(isinstance(f, CherryPyAccessFilter) for f in obj.filters):
|
||||
obj.addFilter(access_filter)
|
||||
|
||||
@staticmethod
|
||||
def create_adapter(
|
||||
app: Any,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user