import functools, logging from app.config import settings # stream options: 'ext://sys.stderr' or 'ext://sys.stdout' # NOTE: This log config is confusing and may need work... 2022-10-07 # 'uvicorn' under 'loggers' creates an output to the 'console' handler # Do not also add 'console' handler to the 'root' 'handlers' list # For now just using that to add or remove file logging options. logging.config.dictConfig({ 'version': 1, 'formatters': { 'default': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s'}, 'long': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S'}, 'short': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s', 'datefmt': '%H:%M:%S', 'use_colors': True}, }, #'filename': 'example.log', # 'level': logging.ERROR, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'stream': 'ext://sys.stderr', 'formatter': 'short', }, 'log_file_all': { 'level': 'NOTSET', 'class': 'logging.handlers.RotatingFileHandler', 'formatter': 'long', 'filename': 'admin/log/app.log', 'maxBytes': 10485760, # 5,242,880 = 5 MB; 10,485,760 = 10 MB 'backupCount': 9 }, # 'log_file_warning': { # 'level': 'WARNING', # 'class': 'logging.handlers.RotatingFileHandler', # 'formatter': 'long', # 'filename': settings.LOG_PATH['app_warning'], # 'maxBytes': 512000, # 524,288 = 512KB # 'backupCount': 9 # }, # 'test_handler': { # 'class': 'logging.StreamHandler', # 'level': 'INFO', # 'formatter': 'short', # }, # 'test_handler_all_rotate': { # 'class': 'logging.handlers.RotatingFileHandler', # 'level': 'NOTSET', # 'formatter': 'short', # 'filename': '/logs/test_rotate.log', # 'maxBytes': 100000, # 5120000 = 5 MB # 'backupCount': 2, # } }, 'loggers': { # 'uvicorn': {'handlers': ['default'], 'level': 'INFO'}, 'uvicorn': {'handlers': ['console'], 'level': 'INFO'}, # 'uvicorn.error': {'level': 'INFO', 'handlers': ['default'], 'propagate': True}, # 'uvicorn.error': {'level': 'INFO', 'handlers': ['console'], 'propagate': True}, # 'uvicorn.access': {'handlers': ['access'], 'level': 'INFO', 'propagate': False}, # 'gunicorn': {'handlers': ['console'], 'level': 'INFO'}, }, 'root': { 'handlers': ['log_file_all'], #, 'log_file_all', 'log_file_warning'], # 'handlers': ['console', 'log_file_all'], #, 'log_file_all', 'log_file_warning'], 'level': 'WARNING', # WARNING } }) log = logging.getLogger('root') # log.setLevel(logging.INFO) # DEBUG > INFO > WARNING > ERROR > CRITICAL # logging.basicConfig( # format='[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s' # ) # ### BEGIN ### Log ### logger_reset() ### # https://realpython.com/primer-on-python-decorators/ # Updated 2022-02-15 def logger_reset(func): # log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL # log.info(locals()) @functools.wraps(func) def wrapper(*args, **kwargs): if func.__name__ not in ['redis_lookup_id_random']: log.info(f'*** Function: "{func.__name__}()"') log.debug(f'*** Function Positional Args: {args}\nFunction Key Args: {kwargs}') init_log_level = log.level returned_result = func(*args, **kwargs) log.debug(f'*** Function finished: "{func.__name__}()". Resetting logger level to level: {log.level} ***') log.setLevel(init_log_level) return returned_result return wrapper # ### END ### Log ### logger_reset() ###