generated from jCloud/repository-template
Create logging target option and fallbacks
This commit is contained in:
@@ -17,17 +17,50 @@ import jcloud_config_parser
|
||||
import logging
|
||||
import pathlib
|
||||
from dataclasses import dataclass
|
||||
from .exceptions import Fail
|
||||
|
||||
__all__ = [
|
||||
'LoggingInfo',
|
||||
'setup_logging'
|
||||
]
|
||||
|
||||
@dataclass
|
||||
class LoggingInfo:
|
||||
logger: logging.Logger
|
||||
logfile: pathlib.Path
|
||||
format: str
|
||||
level: int
|
||||
uvicorn_config: dict
|
||||
|
||||
def _logfile_fallback_used(path: pathlib.Path) -> bool:
|
||||
'''
|
||||
Returns whether the fallback value for the logfile should be used.
|
||||
|
||||
:param path: The path to the logfile.
|
||||
:type path: pathlib.Path
|
||||
|
||||
:return: Whether the fallback value should be used.
|
||||
:rtype: bool
|
||||
'''
|
||||
|
||||
# Path exists and is a directory -> invalid
|
||||
if path.exists() and path.is_dir():
|
||||
return True
|
||||
|
||||
parent = path.parent or pathlib.Path('.')
|
||||
|
||||
# Parent directory missing -> try to create it
|
||||
if not parent.exists():
|
||||
try:
|
||||
parent.mkdir(parents = True, exist_ok = True)
|
||||
except OSError:
|
||||
return True
|
||||
|
||||
# Check whether the path is writable.
|
||||
try:
|
||||
with open(path, 'a'):
|
||||
pass
|
||||
except (OSError, PermissionError):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def setup_logging(configuration: jcloud_config_parser.ini.INIConfiguration) -> LoggingInfo:
|
||||
'''
|
||||
@@ -40,8 +73,22 @@ def setup_logging(configuration: jcloud_config_parser.ini.INIConfiguration) -> L
|
||||
:rtype: LoggingInfo
|
||||
'''
|
||||
|
||||
logfile = configuration.logging.logfile
|
||||
if os.path.isdir(logfile) or not logfile:
|
||||
fail_strict = configuration.logging.fail_strict.lower() in ('true', 'yes', 't', 'y')
|
||||
|
||||
logtarget = configuration.logging.logtarget
|
||||
|
||||
if logtarget not in ('file', 'stdout'):
|
||||
if fail_strict:
|
||||
raise Fail(f'\'{logtarget}\': invalid value for [logging].logtarget. Expected either \'file\' or \'stdout\'.')
|
||||
logtarget = 'stdout'
|
||||
|
||||
if logtarget == 'file':
|
||||
logfile = pathlib.Path(configuration.logging.logfile)
|
||||
if _logfile_fallback_used(logfile):
|
||||
if fail_strict:
|
||||
raise Fail(f'\'{logfile}\': Cannot use as a log file.')
|
||||
logtarget = 'stdout' # fallback to stdout
|
||||
else:
|
||||
logfile = None
|
||||
|
||||
loglevel = logging._nameToLevel.get(
|
||||
@@ -54,17 +101,47 @@ def setup_logging(configuration: jcloud_config_parser.ini.INIConfiguration) -> L
|
||||
logging.basicConfig(level=loglevel, format=logging_format)
|
||||
logger = logging.getLogger('api')
|
||||
logger.propagate = False
|
||||
logger.handlers = list()
|
||||
|
||||
formatter = logging.Formatter(logging_format)
|
||||
if logfile is not None:
|
||||
logger_file_handler = logging.FileHandler(logfile)
|
||||
logger_file_handler.setFormatter(formatter)
|
||||
logger.addHandler(logger_file_handler)
|
||||
|
||||
if logtarget == 'file':
|
||||
logger.handlers = list()
|
||||
handler = logging.FileHandler(logfile)
|
||||
handler.setFormatter(formatter)
|
||||
else:
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
|
||||
uvicorn_config = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
'formatters': {
|
||||
'uvicorn_formatter': {
|
||||
'format': logging_format
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'uvicorn': {
|
||||
'handlers': ['uvicorn_handler'],
|
||||
'level': loglevel,
|
||||
'propagate': False
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'uvicorn_handler': {
|
||||
'class': 'logging.FileHandler',
|
||||
'filename': logfile,
|
||||
'formatter': 'uvicorn_formatter'
|
||||
} if logtarget == 'file'
|
||||
else {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'uvicorn_formatter'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LoggingInfo(
|
||||
logger,
|
||||
logfile,
|
||||
logging_format,
|
||||
loglevel
|
||||
uvicorn_config
|
||||
)
|
||||
@@ -50,27 +50,5 @@ def main():
|
||||
host = host,
|
||||
port = port,
|
||||
server_header = False,
|
||||
log_config = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
'handlers': {
|
||||
'uvicorn_handler': {
|
||||
'class': 'logging.FileHandler',
|
||||
'filename': str(logger_info.logfile),
|
||||
'formatter': 'uvicorn_formatter',
|
||||
},
|
||||
},
|
||||
'formatters': {
|
||||
'uvicorn_formatter': {
|
||||
'format': logger_info.format
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'uvicorn': {
|
||||
'handlers': ['uvicorn_handler'],
|
||||
'level': logger_info.level,
|
||||
'propagate': False
|
||||
},
|
||||
},
|
||||
}
|
||||
log_config = logger_info.uvicorn_config
|
||||
)
|
||||
Reference in New Issue
Block a user