Move verbosity filtering to logger (#2453)
This commit is contained in:
parent
b87982769f
commit
1668e1532f
|
@ -1573,8 +1573,9 @@ class Sanic(BaseSanic, RunnerMixin, metaclass=TouchUpMeta):
|
||||||
"shutdown",
|
"shutdown",
|
||||||
):
|
):
|
||||||
raise SanicException(f"Invalid server event: {event}")
|
raise SanicException(f"Invalid server event: {event}")
|
||||||
if self.state.verbosity >= 1:
|
logger.debug(
|
||||||
logger.debug(f"Triggering server events: {event}")
|
f"Triggering server events: {event}", extra={"verbosity": 1}
|
||||||
|
)
|
||||||
reverse = concern == "shutdown"
|
reverse = concern == "shutdown"
|
||||||
if loop is None:
|
if loop is None:
|
||||||
loop = self.loop
|
loop = self.loop
|
||||||
|
|
|
@ -9,7 +9,7 @@ from socket import socket
|
||||||
from ssl import SSLContext
|
from ssl import SSLContext
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union
|
||||||
|
|
||||||
from sanic.log import logger
|
from sanic.log import VerbosityFilter, logger
|
||||||
from sanic.server.async_server import AsyncioServer
|
from sanic.server.async_server import AsyncioServer
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +91,9 @@ class ApplicationState:
|
||||||
if getattr(self.app, "configure_logging", False) and self.app.debug:
|
if getattr(self.app, "configure_logging", False) and self.app.debug:
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
def set_verbosity(self, value: int):
|
||||||
|
VerbosityFilter.verbosity = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_debug(self):
|
def is_debug(self):
|
||||||
return self.mode is Mode.DEBUG
|
return self.mode is Mode.DEBUG
|
||||||
|
|
|
@ -25,27 +25,28 @@ class Lifespan:
|
||||||
def __init__(self, asgi_app: ASGIApp) -> None:
|
def __init__(self, asgi_app: ASGIApp) -> None:
|
||||||
self.asgi_app = asgi_app
|
self.asgi_app = asgi_app
|
||||||
|
|
||||||
if self.asgi_app.sanic_app.state.verbosity > 0:
|
if (
|
||||||
if (
|
"server.init.before"
|
||||||
"server.init.before"
|
in self.asgi_app.sanic_app.signal_router.name_index
|
||||||
in self.asgi_app.sanic_app.signal_router.name_index
|
):
|
||||||
):
|
logger.debug(
|
||||||
logger.debug(
|
'You have set a listener for "before_server_start" '
|
||||||
'You have set a listener for "before_server_start" '
|
"in ASGI mode. "
|
||||||
"in ASGI mode. "
|
"It will be executed as early as possible, but not before "
|
||||||
"It will be executed as early as possible, but not before "
|
"the ASGI server is started.",
|
||||||
"the ASGI server is started."
|
extra={"verbosity": 1},
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
"server.shutdown.after"
|
"server.shutdown.after"
|
||||||
in self.asgi_app.sanic_app.signal_router.name_index
|
in self.asgi_app.sanic_app.signal_router.name_index
|
||||||
):
|
):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'You have set a listener for "after_server_stop" '
|
'You have set a listener for "after_server_stop" '
|
||||||
"in ASGI mode. "
|
"in ASGI mode. "
|
||||||
"It will be executed as late as possible, but not after "
|
"It will be executed as late as possible, but not after "
|
||||||
"the ASGI server is stopped."
|
"the ASGI server is stopped.",
|
||||||
)
|
extra={"verbosity": 1},
|
||||||
|
)
|
||||||
|
|
||||||
async def startup(self) -> None:
|
async def startup(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
17
sanic/log.py
17
sanic/log.py
|
@ -61,21 +61,36 @@ class Colors(str, Enum): # no cov
|
||||||
END = "\033[0m"
|
END = "\033[0m"
|
||||||
BLUE = "\033[01;34m"
|
BLUE = "\033[01;34m"
|
||||||
GREEN = "\033[01;32m"
|
GREEN = "\033[01;32m"
|
||||||
YELLOW = "\033[01;33m"
|
PURPLE = "\033[01;35m"
|
||||||
RED = "\033[01;31m"
|
RED = "\033[01;31m"
|
||||||
|
SANIC = "\033[38;2;255;13;104m"
|
||||||
|
YELLOW = "\033[01;33m"
|
||||||
|
|
||||||
|
|
||||||
|
class VerbosityFilter(logging.Filter):
|
||||||
|
verbosity: int = 0
|
||||||
|
|
||||||
|
def filter(self, record: logging.LogRecord) -> bool:
|
||||||
|
verbosity = getattr(record, "verbosity", 0)
|
||||||
|
return verbosity <= self.verbosity
|
||||||
|
|
||||||
|
|
||||||
|
_verbosity_filter = VerbosityFilter()
|
||||||
|
|
||||||
logger = logging.getLogger("sanic.root") # no cov
|
logger = logging.getLogger("sanic.root") # no cov
|
||||||
|
logger.addFilter(_verbosity_filter)
|
||||||
"""
|
"""
|
||||||
General Sanic logger
|
General Sanic logger
|
||||||
"""
|
"""
|
||||||
|
|
||||||
error_logger = logging.getLogger("sanic.error") # no cov
|
error_logger = logging.getLogger("sanic.error") # no cov
|
||||||
|
error_logger.addFilter(_verbosity_filter)
|
||||||
"""
|
"""
|
||||||
Logger used by Sanic for error logging
|
Logger used by Sanic for error logging
|
||||||
"""
|
"""
|
||||||
|
|
||||||
access_logger = logging.getLogger("sanic.access") # no cov
|
access_logger = logging.getLogger("sanic.access") # no cov
|
||||||
|
access_logger.addFilter(_verbosity_filter)
|
||||||
"""
|
"""
|
||||||
Logger used by Sanic for access logging
|
Logger used by Sanic for access logging
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -24,9 +24,7 @@ class OptionalDispatchEvent(BaseScheme):
|
||||||
raw_source = getsource(method)
|
raw_source = getsource(method)
|
||||||
src = dedent(raw_source)
|
src = dedent(raw_source)
|
||||||
tree = parse(src)
|
tree = parse(src)
|
||||||
node = RemoveDispatch(
|
node = RemoveDispatch(self._registered_events).visit(tree)
|
||||||
self._registered_events, self.app.state.verbosity
|
|
||||||
).visit(tree)
|
|
||||||
compiled_src = compile(node, method.__name__, "exec")
|
compiled_src = compile(node, method.__name__, "exec")
|
||||||
exec_locals: Dict[str, Any] = {}
|
exec_locals: Dict[str, Any] = {}
|
||||||
exec(compiled_src, module_globals, exec_locals) # nosec
|
exec(compiled_src, module_globals, exec_locals) # nosec
|
||||||
|
@ -64,9 +62,8 @@ class OptionalDispatchEvent(BaseScheme):
|
||||||
|
|
||||||
|
|
||||||
class RemoveDispatch(NodeTransformer):
|
class RemoveDispatch(NodeTransformer):
|
||||||
def __init__(self, registered_events, verbosity: int = 0) -> None:
|
def __init__(self, registered_events) -> None:
|
||||||
self._registered_events = registered_events
|
self._registered_events = registered_events
|
||||||
self._verbosity = verbosity
|
|
||||||
|
|
||||||
def visit_Expr(self, node: Expr) -> Any:
|
def visit_Expr(self, node: Expr) -> Any:
|
||||||
call = node.value
|
call = node.value
|
||||||
|
@ -83,8 +80,10 @@ class RemoveDispatch(NodeTransformer):
|
||||||
if hasattr(event, "s"):
|
if hasattr(event, "s"):
|
||||||
event_name = getattr(event, "value", event.s)
|
event_name = getattr(event, "value", event.s)
|
||||||
if self._not_registered(event_name):
|
if self._not_registered(event_name):
|
||||||
if self._verbosity >= 2:
|
logger.debug(
|
||||||
logger.debug(f"Disabling event: {event_name}")
|
f"Disabling event: {event_name}",
|
||||||
|
extra={"verbosity": 2},
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,7 @@ def test_listeners_triggered_async(app, caplog):
|
||||||
assert after_server_stop
|
assert after_server_stop
|
||||||
|
|
||||||
app.state.mode = Mode.DEBUG
|
app.state.mode = Mode.DEBUG
|
||||||
|
app.state.verbosity = 0
|
||||||
with caplog.at_level(logging.DEBUG):
|
with caplog.at_level(logging.DEBUG):
|
||||||
server.run()
|
server.run()
|
||||||
|
|
||||||
|
|
|
@ -209,3 +209,42 @@ def test_access_log_client_ip_reqip(monkeypatch):
|
||||||
"request": f"GET {request.scheme}://{request.host}/",
|
"request": f"GET {request.scheme}://{request.host}/",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"app_verbosity,log_verbosity,exists",
|
||||||
|
(
|
||||||
|
(0, 0, True),
|
||||||
|
(0, 1, False),
|
||||||
|
(0, 2, False),
|
||||||
|
(1, 0, True),
|
||||||
|
(1, 1, True),
|
||||||
|
(1, 2, False),
|
||||||
|
(2, 0, True),
|
||||||
|
(2, 1, True),
|
||||||
|
(2, 2, True),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_verbosity(app, caplog, app_verbosity, log_verbosity, exists):
|
||||||
|
rand_string = str(uuid.uuid4())
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def log_info(request):
|
||||||
|
logger.info("DEFAULT")
|
||||||
|
logger.info(rand_string, extra={"verbosity": log_verbosity})
|
||||||
|
return text("hello")
|
||||||
|
|
||||||
|
with caplog.at_level(logging.INFO):
|
||||||
|
_ = app.test_client.get(
|
||||||
|
"/", server_kwargs={"verbosity": app_verbosity}
|
||||||
|
)
|
||||||
|
|
||||||
|
record = ("sanic.root", logging.INFO, rand_string)
|
||||||
|
|
||||||
|
if exists:
|
||||||
|
assert record in caplog.record_tuples
|
||||||
|
else:
|
||||||
|
assert record not in caplog.record_tuples
|
||||||
|
|
||||||
|
if app_verbosity == 0:
|
||||||
|
assert ("sanic.root", logging.INFO, "DEFAULT") in caplog.record_tuples
|
||||||
|
|
Loading…
Reference in New Issue
Block a user