You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
MCOL-5496: Merge CMAPI code to engine repo.
[add] cmapi code to engine
This commit is contained in:
committed by
Alan Mologorsky
parent
77eedd1756
commit
a079a2c944
131
cmapi/cmapi_server/logging_management.py
Normal file
131
cmapi/cmapi_server/logging_management.py
Normal file
@ -0,0 +1,131 @@
|
||||
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)
|
Reference in New Issue
Block a user