forked from Github-Mirrors/canaille
refactor: move logging machinery in its own dedicated file
This commit is contained in:
parent
103c6343be
commit
52031dd2c4
2 changed files with 95 additions and 92 deletions
|
@ -1,8 +1,5 @@
|
|||
import datetime
|
||||
import logging
|
||||
import sys
|
||||
from logging.config import dictConfig
|
||||
from logging.config import fileConfig
|
||||
|
||||
from flask import Flask
|
||||
from flask import request
|
||||
|
@ -29,46 +26,6 @@ def setup_sentry(app): # pragma: no cover
|
|||
return sentry_sdk
|
||||
|
||||
|
||||
def setup_logging(app):
|
||||
conf = app.config["CANAILLE"]["LOGGING"]
|
||||
|
||||
security_level_name = "SECURITY"
|
||||
if not hasattr(logging, security_level_name):
|
||||
addLoggingLevel(security_level_name, logging.INFO + 5)
|
||||
|
||||
if conf is None:
|
||||
log_level = "DEBUG" if app.debug else "INFO"
|
||||
dictConfig(
|
||||
{
|
||||
"version": 1,
|
||||
"formatters": {
|
||||
"default": {
|
||||
"format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s",
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"wsgi": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://flask.logging.wsgi_errors_stream",
|
||||
"formatter": "default",
|
||||
}
|
||||
},
|
||||
"root": {"level": log_level, "handlers": ["wsgi"]},
|
||||
"loggers": {
|
||||
"faker": {"level": "WARNING"},
|
||||
"mail.log": {"level": "WARNING"},
|
||||
},
|
||||
"disable_existing_loggers": False,
|
||||
}
|
||||
)
|
||||
|
||||
elif isinstance(conf, dict):
|
||||
dictConfig(conf)
|
||||
|
||||
else:
|
||||
fileConfig(conf, disable_existing_loggers=False)
|
||||
|
||||
|
||||
def setup_jinja(app):
|
||||
app.jinja_env.filters["len"] = len
|
||||
app.jinja_env.policies["ext.i18n.trimmed"] = True
|
||||
|
@ -126,6 +83,7 @@ def create_app(
|
|||
from .app.configuration import setup_config
|
||||
from .app.features import setup_features
|
||||
from .app.i18n import setup_i18n
|
||||
from .app.logging import setup_logging
|
||||
from .app.themes import setup_themer
|
||||
from .backends import setup_backend
|
||||
|
||||
|
@ -163,52 +121,3 @@ def create_app(
|
|||
raise
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def addLoggingLevel(levelName, levelNum, methodName=None):
|
||||
"""Comprehensively adds a new logging level to the `logging` module and the
|
||||
currently configured logging class.
|
||||
|
||||
`levelName` becomes an attribute of the `logging` module with the value
|
||||
`levelNum`. `methodName` becomes a convenience method for both `logging`
|
||||
itself and the class returned by `logging.getLoggerClass()` (usually just
|
||||
`logging.Logger`). If `methodName` is not specified, `levelName.lower()` is
|
||||
used.
|
||||
|
||||
To avoid accidental clobberings of existing attributes, this method will
|
||||
raise an `AttributeError` if the level name is already an attribute of the
|
||||
`logging` module or if the method name is already present
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> addLoggingLevel("TRACE", logging.DEBUG - 5)
|
||||
>>> logging.getLogger(__name__).setLevel("TRACE")
|
||||
>>> logging.getLogger(__name__).trace("that worked")
|
||||
>>> logging.trace("so did this")
|
||||
>>> logging.TRACE
|
||||
5
|
||||
"""
|
||||
if not methodName:
|
||||
methodName = levelName.lower()
|
||||
|
||||
if hasattr(logging, levelName):
|
||||
raise AttributeError(f"{levelName} already defined in logging module")
|
||||
if hasattr(logging, methodName):
|
||||
raise AttributeError(f"{methodName} already defined in logging module")
|
||||
if hasattr(logging.getLoggerClass(), methodName):
|
||||
raise AttributeError(f"{methodName} already defined in logger class")
|
||||
|
||||
# This method was inspired by the answers to Stack Overflow post
|
||||
# http://stackoverflow.com/q/2183233/2988730, especially
|
||||
# http://stackoverflow.com/a/13638084/2988730
|
||||
def logForLevel(self, message, *args, **kwargs):
|
||||
if self.isEnabledFor(levelNum):
|
||||
self._log(levelNum, message, args, **kwargs)
|
||||
|
||||
def logToRoot(message, *args, **kwargs):
|
||||
logging.log(levelNum, message, *args, **kwargs)
|
||||
|
||||
logging.addLevelName(levelNum, levelName)
|
||||
setattr(logging, levelName, levelNum)
|
||||
setattr(logging.getLoggerClass(), methodName, logForLevel)
|
||||
setattr(logging, methodName, logToRoot)
|
||||
|
|
94
canaille/app/logging.py
Normal file
94
canaille/app/logging.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
import logging
|
||||
from logging.config import dictConfig
|
||||
from logging.config import fileConfig
|
||||
|
||||
|
||||
def add_log_level(level_name, level_num, method_name=None):
|
||||
"""
|
||||
Adapted from https://stackoverflow.com/a/35804945/2700168
|
||||
|
||||
Comprehensively adds a new logging level to the `logging` module and the
|
||||
currently configured logging class.
|
||||
`level_name` becomes an attribute of the `logging` module with the value
|
||||
`level_num`. `method_name` becomes a convenience method for both `logging`
|
||||
itself and the class returned by `logging.getLoggerClass()` (usually just
|
||||
`logging.Logger`). If `methodName` is not specified, `levelName.lower()` is
|
||||
used.
|
||||
To avoid accidental clobberings of existing attributes, this method will
|
||||
raise an `AttributeError` if the level name is already an attribute of the
|
||||
`logging` module or if the method name is already present
|
||||
Example
|
||||
-------
|
||||
>>> addLoggingLevel("TRACE", logging.DEBUG - 5)
|
||||
>>> logging.getLogger(__name__).setLevel("TRACE")
|
||||
>>> logging.getLogger(__name__).trace("that worked")
|
||||
>>> logging.trace("so did this")
|
||||
>>> logging.TRACE
|
||||
5
|
||||
"""
|
||||
if not method_name:
|
||||
method_name = level_name.lower()
|
||||
|
||||
if hasattr(logging, level_name):
|
||||
raise AttributeError(f"{level_name} already defined in logging module")
|
||||
if hasattr(logging, method_name):
|
||||
raise AttributeError(f"{method_name} already defined in logging module")
|
||||
if hasattr(logging.getLoggerClass(), method_name):
|
||||
raise AttributeError(f"{method_name} already defined in logger class")
|
||||
|
||||
# This method was inspired by the answers to Stack Overflow post
|
||||
# http://stackoverflow.com/q/2183233/2988730, especially
|
||||
# http://stackoverflow.com/a/13638084/2988730
|
||||
def log_for_level(self, message, *args, **kwargs):
|
||||
if self.isEnabledFor(level_num):
|
||||
self._log(level_num, message, args, **kwargs)
|
||||
|
||||
def log_to_root(message, *args, **kwargs):
|
||||
logging.log(level_num, message, *args, **kwargs)
|
||||
|
||||
logging.addLevelName(level_num, level_name)
|
||||
setattr(logging, level_name, level_num)
|
||||
setattr(logging.getLoggerClass(), method_name, log_for_level)
|
||||
setattr(logging, method_name, log_to_root)
|
||||
|
||||
|
||||
def setup_logging(app):
|
||||
conf = app.config["CANAILLE"]["LOGGING"]
|
||||
|
||||
security_level_name = "SECURITY"
|
||||
security_level = logging.INFO + 5
|
||||
|
||||
if not hasattr(logging, security_level_name):
|
||||
add_log_level(security_level_name, security_level)
|
||||
|
||||
if conf is None:
|
||||
log_level = "DEBUG" if app.debug else "INFO"
|
||||
dictConfig(
|
||||
{
|
||||
"version": 1,
|
||||
"formatters": {
|
||||
"default": {
|
||||
"format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s",
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"wsgi": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://flask.logging.wsgi_errors_stream",
|
||||
"formatter": "default",
|
||||
}
|
||||
},
|
||||
"root": {"level": log_level, "handlers": ["wsgi"]},
|
||||
"loggers": {
|
||||
"faker": {"level": "WARNING"},
|
||||
"mail.log": {"level": "WARNING"},
|
||||
},
|
||||
"disable_existing_loggers": False,
|
||||
}
|
||||
)
|
||||
|
||||
elif isinstance(conf, dict):
|
||||
dictConfig(conf)
|
||||
|
||||
else:
|
||||
fileConfig(conf, disable_existing_loggers=False)
|
Loading…
Reference in a new issue