Source code for spinningdiskanalyzer.logger
"""Handles setup of the debug log."""
from . import meta
import logging
import logging.handlers
from appdirs import user_log_dir
from pathlib import Path
import sys
import re
[docs]
def setup():
"""Configures event logging for the application."""
# Set log granularity on root logger.
log = logging.getLogger()
log.setLevel(logging.DEBUG)
# Suppress noise from certain libraries in the log output.
mute = ('pyvips', 'PIL', 'matplotlib')
for package in mute:
logging.getLogger(package).propagate = False
# Store log files inside the system's application data folder.
logs = logs_folder()
logs.mkdir(exist_ok=True, parents=True)
# Also log to the console.
handler = logging.StreamHandler(sys.stdout)
log.setLevel(logging.DEBUG)
logging.setLogRecordFactory(timed_records)
entry = '%(timestamp)s | %(levelname)-8s | %(message)s'
times = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter(entry, datefmt=times)
handler.setFormatter(formatter)
log.addHandler(handler)
# Rotate out old log entries to separate file once a day.
handler = logging.handlers.TimedRotatingFileHandler(
logs/'today.txt', encoding='UTF-8-sig', when='midnight')
handler.rotation_filename = rotation_filename
entry = '%(asctime)s | %(levelname)-8s | %(message)s | %(name)s'
times = '%H:%M:%S'
formatter = logging.Formatter(entry, datefmt=times)
handler.setFormatter(formatter)
log.addHandler(handler)
[docs]
def logs_folder() -> Path:
"""Returns the folder containing the log files."""
return Path(user_log_dir(appname=meta.title, appauthor=''))
[docs]
def rotation_filename(path: Path) -> Path:
"""
Monkey-patches the logging handler's file renaming mechanism so that,
on roll-over, log files from previous days get the actual date, and
only that, as the file name, and have `.txt` as the suffix.
*Note*: A proper implementation would also have to override the
`getFilesToDelete()` method. But this here works for our use case
where we never purge logs. Refer to the [source code][1] for further
details.
[1]: https://github.com/python/cpython/blob/master/Lib/logging/handlers.py
"""
path = Path(path)
date = re.match(r'\.(\d\d\d\d-\d\d-\d\d)', path.suffix).group(1)
return path.with_name(f'{date}.txt')
original_records = logging.getLogRecordFactory()
[docs]
def timed_records(*args, **kwargs) -> logging.LogRecord:
"""
Adds a relative `timestamp` to the log record attributes.
Example usage:
```
logging.setLogRecordFactory(timed_records)
logging.basicConfig(format='[%(timestamp)s] %(message)s')
```
"""
record = original_records(*args, **kwargs)
(minutes, seconds) = divmod(record.relativeCreated/1000, 60)
record.timestamp = f'{minutes:02.0f}:{seconds:06.3f}'
return record