mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00

Up until now I didn't see the point of using spaces for indentation. However, the previous commit (a18bec3) was quite eye opening. Given that python is an indentation aware language, the amount of mistakes that went unnoticed because tabs and spaces were used at the same time (tabs for indentation and spaces for alignment) were unacceptable. E101,W191 have been re-enable in the tox flake8 checker and the documentation has been modified accordingly. The following files have been left as-is: * bootstrapvz/common/assets/extlinux/extlinux.conf * bootstrapvz/common/assets/init.d/expand-root * bootstrapvz/common/assets/init.d/generate-ssh-hostkeys * bootstrapvz/common/assets/init.d/squeeze/generate-ssh-hostkeys * bootstrapvz/plugins/docker_daemon/assets/init.d/docker * bootstrapvz/providers/ec2/assets/bin/growpart * bootstrapvz/providers/ec2/assets/grub.d/40_custom * bootstrapvz/providers/ec2/assets/init.d/ec2-get-credentials * bootstrapvz/providers/ec2/assets/init.d/ec2-run-user-data * docs/_static/taskoverview.coffee * docs/_static/taskoverview.less * tests/unit/subprocess.sh
104 lines
3.8 KiB
Python
104 lines
3.8 KiB
Python
"""This module holds functions and classes responsible for formatting the log output
|
|
both to a file and to the console.
|
|
"""
|
|
import logging
|
|
|
|
|
|
def get_console_handler(debug, colorize):
|
|
"""Returns a log handler for the console
|
|
The handler color codes the different log levels
|
|
|
|
:params bool debug: Whether to set the log level to DEBUG (otherwise INFO)
|
|
:params bool colorize: Whether to colorize console output
|
|
:return: The console logging handler
|
|
"""
|
|
# Create a console log handler
|
|
import sys
|
|
console_handler = logging.StreamHandler(sys.stderr)
|
|
if colorize:
|
|
# We want to colorize the output to the console, so we add a formatter
|
|
console_handler.setFormatter(ColorFormatter())
|
|
# Set the log level depending on the debug argument
|
|
if debug:
|
|
console_handler.setLevel(logging.DEBUG)
|
|
else:
|
|
console_handler.setLevel(logging.INFO)
|
|
return console_handler
|
|
|
|
|
|
def get_file_handler(path, debug):
|
|
"""Returns a log handler for the given path
|
|
If the parent directory of the logpath does not exist it will be created
|
|
The handler outputs relative timestamps (to when it was created)
|
|
|
|
:params str path: The full path to the logfile
|
|
:params bool debug: Whether to set the log level to DEBUG (otherwise INFO)
|
|
:return: The file logging handler
|
|
"""
|
|
import os.path
|
|
if not os.path.exists(os.path.dirname(path)):
|
|
os.makedirs(os.path.dirname(path))
|
|
# Create the log handler
|
|
file_handler = logging.FileHandler(path)
|
|
# Absolute timestamps are rather useless when bootstrapping, it's much more interesting
|
|
# to see how long things take, so we log in a relative format instead
|
|
file_handler.setFormatter(FileFormatter('[%(relativeCreated)s] %(levelname)s: %(message)s'))
|
|
# The file log handler always logs everything
|
|
file_handler.setLevel(logging.DEBUG)
|
|
return file_handler
|
|
|
|
|
|
def get_log_filename(manifest_path):
|
|
"""Returns the path to a logfile given a manifest
|
|
The logfile name is constructed from the current timestamp and the basename of the manifest
|
|
|
|
:param str manifest_path: The path to the manifest
|
|
:return: The path to the logfile
|
|
:rtype: str
|
|
"""
|
|
import os.path
|
|
from datetime import datetime
|
|
|
|
manifest_basename = os.path.basename(manifest_path)
|
|
manifest_name, _ = os.path.splitext(manifest_basename)
|
|
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
|
|
filename = '{timestamp}_{name}.log'.format(timestamp=timestamp, name=manifest_name)
|
|
return filename
|
|
|
|
|
|
class SourceFormatter(logging.Formatter):
|
|
"""Adds a [source] tag to the log message if it exists
|
|
The python docs suggest using a LoggingAdapter, but that would mean we'd
|
|
have to use it everywhere we log something (and only when called remotely),
|
|
which is not feasible.
|
|
"""
|
|
|
|
def format(self, record):
|
|
extra = getattr(record, 'extra', {})
|
|
if 'source' in extra:
|
|
record.msg = '[{source}] {message}'.format(source=record.extra['source'],
|
|
message=record.msg)
|
|
return super(SourceFormatter, self).format(record)
|
|
|
|
|
|
class ColorFormatter(SourceFormatter):
|
|
"""Colorizes log messages depending on the loglevel
|
|
"""
|
|
level_colors = {logging.ERROR: 'red',
|
|
logging.WARNING: 'magenta',
|
|
logging.INFO: 'blue',
|
|
}
|
|
|
|
def format(self, record):
|
|
# Colorize the message if we have a color for it (DEBUG has no color)
|
|
from termcolor import colored
|
|
record.msg = colored(record.msg, self.level_colors.get(record.levelno, None))
|
|
return super(ColorFormatter, self).format(record)
|
|
|
|
|
|
class FileFormatter(SourceFormatter):
|
|
"""Formats log statements for output to file
|
|
Currently this is just a stub
|
|
"""
|
|
def format(self, record):
|
|
return super(FileFormatter, self).format(record)
|