Coloring process name based on pid

pull/277/head
sezanzeb 3 years ago
parent 753ce5319f
commit 5cd015f1cb

@ -91,12 +91,14 @@ def is_debug():
return logger.level <= logging.DEBUG
def get_ansi_code(r, g, b):
return 16 + b + (6 * g) + (36 * r)
class ColorfulFormatter(logging.Formatter):
"""Overwritten Formatter to print nicer logs.
It colors all logs from the same filename in the same color to visually group them
together. It also adds process name, process id, file, line-number and time.
class Formatter(logging.Formatter):
"""Overwritten Formatter to print nicer logs."""
If debug mode is not active, it will not do any of this.
"""
def __init__(self):
super().__init__()
@ -111,18 +113,19 @@ class Formatter(logging.Formatter):
# https://stackoverflow.com/a/596243
brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b
if brightness < 1:
# prefer light colors, because most people have a dark terminal background
# prefer light colors, because most people have a dark
# terminal background
continue
if g + b <= 1:
# red is reserved for errors
# red makes it look like it's an error
continue
if abs(g - b) < 2 and abs(b - r) < 2 and abs(r - g) < 2:
# no colors that are too grey
continue
self.allowed_colors.append(get_ansi_code(r, g, b))
self.allowed_colors.append(self._get_ansi_code(r, g, b))
self.level_based_colors = {
logging.WARNING: 11,
@ -130,33 +133,38 @@ class Formatter(logging.Formatter):
logging.FATAL: 9,
}
self.process_name = {
"gtk": "GUI",
"helper": "GUI-Helper",
"service": "Service",
"control": "Control",
}.get(sys.argv[0].split("-")[-1], sys.argv[0])
self.process_color = self.word_to_color(sys.argv[0])
def _get_ansi_code(self, r, g, b):
return 16 + b + (6 * g) + (36 * r)
def word_to_color(self, word):
def _word_to_color(self, word):
"""Convert a word to a 8bit ansi color code."""
digit_sum = sum([ord(char) for char in word])
index = digit_sum % len(self.allowed_colors)
return self.allowed_colors[index]
def allocate_debug_log_color(self, record):
"""Pick a random color that ideally has enough contrast to the previously picked colors."""
if self.file_color_mapping.get(record.pathname) is not None:
return self.file_color_mapping[record.pathname]
def _allocate_debug_log_color(self, record):
"""Get the color that represents the source file of the log."""
if self.file_color_mapping.get(record.filename) is not None:
return self.file_color_mapping[record.filename]
color = self.word_to_color(record.pathname)
color = self._word_to_color(record.filename)
if self.file_color_mapping.get(record.pathname) is None:
if self.file_color_mapping.get(record.filename) is None:
# calculate the color for each file only once
self.file_color_mapping[record.pathname] = color
self.file_color_mapping[record.filename] = color
return color
def _get_process_name(self):
"""Generate a beaitiful to read name for this process."""
name = sys.argv[0].split("/")[-1].split("-")[-1]
return {
"gtk": "GUI",
"helper": "GUI-Helper",
"service": "Service",
"control": "Control",
}.get(name, name)
def _get_format(self, record):
"""Generate a message format string."""
debug_mode = is_debug()
@ -169,23 +177,27 @@ class Formatter(logging.Formatter):
color = self.level_based_colors[record.levelno]
return f"\033[38;5;{color}m%(levelname)s\033[0m: %(message)s"
color = self._allocate_debug_log_color(record)
if record.levelno in [logging.ERROR, logging.WARNING, logging.FATAL]:
color = self.level_based_colors[record.levelno]
# underline
style = f"\033[4;38;5;{color}m"
else:
color = self.allocate_debug_log_color(record)
style = f"\033[38;5;{color}m"
process_color = self._word_to_color(f"{os.getpid()}{sys.argv[0]}")
return ( # noqa
f'{datetime.now().strftime("%H:%M:%S.%f")} '
f"\033[38;5;{self.process_color}m" # color
f"\033[38;5;{process_color}m" # color
f"{os.getpid()} "
f"{self.process_name} "
f"{self._get_process_name()} "
"\033[0m" # end style
f"\033[38;5;{color}m" # color
f"{style}"
f"%(levelname)s "
f"%(filename)s:%(lineno)d: "
"%(message)s"
"\033[0m" # end style
)
).replace(" ", " ")
def format(self, record):
"""Overwritten format function."""
@ -195,7 +207,7 @@ class Formatter(logging.Formatter):
handler = logging.StreamHandler()
handler.setFormatter(Formatter())
handler.setFormatter(ColorfulFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logging.getLogger("asyncio").setLevel(logging.WARNING)
@ -274,7 +286,7 @@ def add_filehandler(log_path=LOG_PATH):
file.writelines(content)
file_handler = logging.FileHandler(log_path)
file_handler.setFormatter(Formatter())
file_handler.setFormatter(ColorfulFormatter())
logger.addHandler(file_handler)
logger.info('Starting logging to "%s"', log_path)

Loading…
Cancel
Save