1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
mariadb-AlanMologorsky a079a2c944 MCOL-5496: Merge CMAPI code to engine repo.
[add] cmapi code to engine
2023-06-07 10:00:16 +03:00

132 lines
4.5 KiB
Python

import json
import logging
import logging.config
from functools import partial, partialmethod
import cherrypy
from cherrypy import _cperror
from cmapi_server.constants import CMAPI_LOG_CONF_PATH
class AddIpFilter(logging.Filter):
"""Filter to add IP address to logging record."""
def filter(self, record):
record.ip = cherrypy.request.remote.name or cherrypy.request.remote.ip
return True
def custom_cherrypy_error(
self, msg='', context='', severity=logging.INFO, traceback=False
):
"""Write the given ``msg`` to the error log. [now without hardcoded time]
This is not just for errors! [looks awful, but cherrypy realisation as is]
Applications may call this at any time to log application-specific
information.
If ``traceback`` is True, the traceback of the current exception
(if any) will be appended to ``msg``.
..Note:
All informatio
"""
exc_info = None
if traceback:
exc_info = _cperror._exc_info()
self.error_log.log(severity, ' '.join((context, msg)), exc_info=exc_info)
def dict_config(config_filepath: str):
with open(config_filepath, 'r', encoding='utf-8') as json_config:
config_dict = json.load(json_config)
logging.config.dictConfig(config_dict)
def add_logging_level(level_name, level_num, method_name=None):
"""
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`.
`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
-------
>>> add_logging_level('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
# https://stackoverflow.com/a/35804945
# https://stackoverflow.com/a/55276759
logging.addLevelName(level_num, level_name)
setattr(logging, level_name, level_num)
setattr(
logging.getLoggerClass(), method_name,
partialmethod(logging.getLoggerClass().log, level_num)
)
setattr(logging, method_name, partial(logging.log, level_num))
def config_cmapi_server_logging():
# add custom level TRACE only for develop purposes
# could be activated using API endpoints or cli tool without relaunching
add_logging_level('TRACE', 5)
cherrypy._cplogging.LogManager.error = custom_cherrypy_error
# reconfigure cherrypy.access log message format
# Default access_log_format '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
# h - remote.name or remote.ip, l - "-",
# u - getattr(request, 'login', None) or '-', t - self.time(),
# r - request.request_line, s - status,
# b - dict.get(outheaders, 'Content-Length', '') or '-',
# f - dict.get(inheaders, 'Referer', ''),
# a - dict.get(inheaders, 'User-Agent', ''),
# o - dict.get(inheaders, 'Host', '-'),
# i - request.unique_id, z - LazyRfc3339UtcTime()
cherrypy._cplogging.LogManager.access_log_format = (
'{h} ACCESS "{r}" code {s}, bytes {b}, user-agent "{a}"'
)
dict_config(CMAPI_LOG_CONF_PATH)
def change_loggers_level(level: str):
"""Set level for each custom logger except cherrypy library.
:param level: logging level to set
:type level: str
"""
loggers = [
logging.getLogger(name) for name in logging.root.manager.loggerDict
if 'cherrypy' not in name
]
loggers.append(logging.getLogger()) # add RootLogger
for logger in loggers:
logger.setLevel(level)