from __future__ import annotations
import logging
import sys
import typing as t
from werkzeug . local import LocalProxy
from . globals import request
if t . TYPE_CHECKING : # pragma: no cover
from . sansio . app import App
@LocalProxy
def wsgi_errors_stream ( ) - > t . TextIO :
""" Find the most appropriate error stream for the application. If a request
is active , log to ` ` wsgi . errors ` ` , otherwise use ` ` sys . stderr ` ` .
If you configure your own : class : ` logging . StreamHandler ` , you may want to
use this for the stream . If you are using file or dict configuration and
can ' t import this directly, you can refer to it as
` ` ext : / / flask . logging . wsgi_errors_stream ` ` .
"""
if request :
return request . environ [ " wsgi.errors " ] # type: ignore[no-any-return]
return sys . stderr
def has_level_handler ( logger : logging . Logger ) - > bool :
""" Check if there is a handler in the logging chain that will handle the
given logger ' s :meth:`effective level <~logging.Logger.getEffectiveLevel>`.
"""
level = logger . getEffectiveLevel ( )
current = logger
while current :
if any ( handler . level < = level for handler in current . handlers ) :
return True
if not current . propagate :
break
current = current . parent # type: ignore
return False
#: Log messages to :func:`~flask.logging.wsgi_errors_stream` with the format
#: ``[%(asctime)s] %(levelname)s in %(module)s: %(message)s``.
default_handler = logging . StreamHandler ( wsgi_errors_stream ) # type: ignore
default_handler . setFormatter (
logging . Formatter ( " [ %(asctime)s ] %(levelname)s in %(module)s : %(message)s " )
)
def create_logger ( app : App ) - > logging . Logger :
""" Get the Flask app ' s logger and configure it if needed.
The logger name will be the same as
: attr : ` app . import_name < flask . Flask . name > ` .
When : attr : ` ~ flask . Flask . debug ` is enabled , set the logger level to
: data : ` logging . DEBUG ` if it is not set .
If there is no handler for the logger ' s effective level, add a
: class : ` ~ logging . StreamHandler ` for
: func : ` ~ flask . logging . wsgi_errors_stream ` with a basic format .
"""
logger = logging . getLogger ( app . name )
if app . debug and not logger . level :
logger . setLevel ( logging . DEBUG )
if not has_level_handler ( logger ) :
logger . addHandler ( default_handler )
return logger