Source code for lightmlrestapi.mlapp.base_logging

"""
Machine Learning Post request


:githublink:`%|py|5`
"""
from datetime import datetime
import os
import json
from time import perf_counter
import logging
from logging import Formatter
from logging.handlers import TimedRotatingFileHandler
from ..tools import json_loads, json_dumps


[docs]class BaseLogging: """ Simplifies logging. Logging is encrypted with module :epkg:`pyjwt` if *secret* is specified. :githublink:`%|py|19` """
[docs] def __init__(self, secret, folder='.', level=logging.INFO, encoding='utf-8', when='d'): """ :param secret: secret for encryption (None to avoid encryption) :param folder: folder where to write the logs (None to disable the logging) :param level: logging level :param when: when rotating the logs, see `TimedRotatingFileHandler <https://docs.python.org/3/library/logging.handlers.html? highlight=streamhandler#logging.handlers.TimedRotatingFileHandler>`_ :param encoding: encoding :githublink:`%|py|31` """ if folder is None: self.logger = None else: current_time = datetime.now() current_date = current_time.strftime("%Y-%m-%d") filename = "{0}-{1}.log".format( self.__class__.__name__, current_date) file_location = os.path.join(folder, filename) form = Formatter('%(asctime)s,%(levelname)s,%(message)s,%(data)s') self.handler = TimedRotatingFileHandler( file_location, encoding=encoding, delay=True, when=when) self.handler.setFormatter(form) self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(level) self.logger.addHandler(self.handler) self.secret = secret if self.secret is not None: import jwt self.jwt = jwt
[docs] def save_time(self): """ Saves the times to get a duration later. :githublink:`%|py|55` """ self.t1 = perf_counter()
[docs] def duration(self): """ Get the duration since :meth:`save_time <lightmlrestapi.mlapp.base_logging.BaseLogging.save_time>` was called. :githublink:`%|py|61` """ return perf_counter() - self.t1
[docs] def info(self, msg, data): """ Logs any king of data into the logs. :param msg: message :param data: data to log :githublink:`%|py|70` """ self._logerrorinfo('info', msg, data)
[docs] def error(self, msg, data): """ Logs any king of data into the logs. :param msg: message :param data: data to log :githublink:`%|py|79` """ self._logerrorinfo('error', msg, data)
[docs] def _logerrorinfo(self, fct, msg, data): """ Logs any king of data into the logs. :param msg: message :param data: data to log :githublink:`%|py|88` """ if self.logger is not None: if self.secret is None: try: dumped = json_dumps(data) except Exception: # pylint: disable=W0703 # Cannot serialize into json. dumped = str(data) extra = dict(data=dumped) else: enc_data = self.jwt.encode( data, self.secret, algorithm='HS256') extra = dict(data=enc_data) if fct == 'info': self.logger.info(msg, extra=extra) else: self.logger.error(msg, extra=extra)
[docs]def enumerate_parsed_logs(folder, secret, encoding='utf-8'): """ Goes through a list of logged files, reads and decrypts the content. :param folder: folder which contains the logs :param secret: secret :param encoding: encoding :return: iterator on decrypted data :githublink:`%|py|116` """ if secret is not None: import jwt for root, _, files in os.walk(folder): for name in files: full = os.path.join(root, name) with open(full, 'r', encoding=encoding) as f: for i, line in enumerate(f): spl = line.rstrip('\n\r').split(',') if secret is None: dt = datetime.strptime(spl[0], '%Y-%m-%d %H:%M:%S') data = ','.join(spl[4:]) try: data = json_loads(data) except ValueError: # json gives better error messages. data = json.loads(data) # data should be a dictionary saved as a string rec = dict(dt=dt, code=spl[1], level=spl[2], msg=spl[3], data=data) yield rec else: if len(spl) != 5: raise ValueError( "Format issue in\n File \"{0}\", line {1}".format(full, i + 1)) if spl[4].startswith("b'") and spl[4].endswith("'"): data = spl[4][2:-1] else: data = spl[4] dec = jwt.decode(data, secret, algorithms=['HS256']) dt = datetime.strptime(spl[0], '%Y-%m-%d %H:%M:%S') rec = dict(dt=dt, code=spl[1], level=spl[2], msg=spl[3], data=dec) yield rec