How do you put the TimedRotatingFileHandler in configuration?
-
I've got a logistics configuration:
"file_handler": { "class": "logging.handlers.TimedRotatingFileHandler", "level": "DEBUG", "formatter": "simple", "filename": "development.log", "encoding": "utf8" }
The configuration, as illustrated by the example, is
JSON
- an object. Loading and application of the configuration is banal and simple: first reading of the file, then interpretation of the modulejson
from the standard library calldict_config
♪I don't like the name of the log file after rotation. It is very uncomfortable with the fact that there is a time mark as an expansion of the file. I really want to put it in the base name, and the extension will be 'log'.
I found a solution to my problem, it's written on an enSO: https://stackoverflow.com/questions/338450/timedrotatingfilehandler-changing-file-name ♪ But I don't really like that decision. It's for runtime, and I'd like to file a declarative, that's the configuration.
Is it possible and if so, how?
-
In due course, it was a similar task to the following:
my_logging.py:
import os import datetime import errno import logging.config import logging.handlers
import yaml
def mkdir_p(path):
try:
os.makedirs(path, exist_ok=True) # Python>3.2
except TypeError:
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raiseclass EvalFileHandler(logging.FileHandler):
def init(self, **kwargs):
fn = eval(os.path.expandvars(kwargs['filename']))
mkdir_p(os.path.dirname(fn))
kwargs['filename'] = fn
logging.FileHandler.init(self, **kwargs)def setup_logging(
config_file='logging.yml',
default_level=logging.INFO,
env_key_config='LOGGING_CONFIG'
):
"""Setup logging configuration""" path = config_file value = os.getenv(env_key_config, None) if value: path = value if os.path.exists(path): with open(path, 'rt') as f: config = yaml.load(f.read()) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level)
logging.yml:
---
version: 1
disable_existing_loggers: False
formatters:
default:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
simple:
format: "%(asctime)s - %(levelname)-8s - %(message)s"
short:
format: "%(asctime)s - %(message)s"
message_only:
format: "%(message)s"handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdoutdebug_file_handler: class: my_logging.EvalFileHandler level: DEBUG formatter: simple filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic-debug.log')" encoding: utf8 info_file_handler: class: my_logging.EvalFileHandler level: INFO formatter: simple filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic.log')" encoding: utf8 error_file_handler: class: my_logging.EvalFileHandler level: ERROR formatter: simple filename: "__import__('datetime').datetime.now().strftime('$HOME/log/%Y/%m/%Y%m%d-db_jiramatic-errors.log')" encoding: utf8
loggers:
my_project:
level: INFOhandlers: [console, info_file_handler, error_file_handler, debug_file_handler]
handlers: [console, info_file_handler, error_file_handler] propagate: no
root:
level: INFO
handlers: [console, info_file_handler, error_file_handler]
Then basically squeak.
import my_logging
my_logging.setup_logging(config_file='/path/to/logging.yml')
logger = logging.getLogger('my_project')