import functools, logging # 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': 5120000, # 5120000 = 5 MB 'backupCount': 5 }, 'log_file_warning': { 'level': 'WARNING', 'class': 'logging.handlers.RotatingFileHandler', 'formatter': 'long', 'filename': 'admin/log/app_warning.log', 'maxBytes': 512000, # 512000 = .512 MB 'backupCount': 5 }, 'test_handler': { 'class': 'logging.StreamHandler', 'level': 'INFO', 'formatter': 'short', } }, '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}, }, '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): 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() ###