88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
# Adapted from https://github.com/numtide/deploykit
|
|
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
# https://no-color.org
|
|
DISABLE_COLOR = not sys.stderr.isatty() or os.environ.get("NO_COLOR", "") != ""
|
|
|
|
|
|
def ansi_color(color: int) -> str:
|
|
return f"\x1b[{color}m"
|
|
|
|
|
|
class CommandFormatter(logging.Formatter):
|
|
"""
|
|
print errors in red and warnings in yellow
|
|
"""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__(
|
|
"%(prefix_color)s[%(command_prefix)s]%(color_reset)s %(color)s%(message)s%(color_reset)s"
|
|
)
|
|
self.hostnames: list[str] = []
|
|
self.hostname_color_offset = 1 # first host shouldn't get aggressive red
|
|
|
|
def format(self, record: logging.LogRecord) -> str:
|
|
colorcode = 0
|
|
if record.levelno == logging.ERROR:
|
|
colorcode = 31 # red
|
|
if record.levelno == logging.WARNING:
|
|
colorcode = 33 # yellow
|
|
|
|
color, prefix_color, color_reset = "", "", ""
|
|
if not DISABLE_COLOR:
|
|
command_prefix = getattr(record, "command_prefix", "")
|
|
color = ansi_color(colorcode)
|
|
prefix_color = ansi_color(self.hostname_colorcode(command_prefix))
|
|
color_reset = "\x1b[0m"
|
|
|
|
record.color = color
|
|
record.prefix_color = prefix_color
|
|
record.color_reset = color_reset
|
|
|
|
return super().format(record)
|
|
|
|
def hostname_colorcode(self, hostname: str) -> int:
|
|
try:
|
|
index = self.hostnames.index(hostname)
|
|
except ValueError:
|
|
self.hostnames += [hostname]
|
|
index = self.hostnames.index(hostname)
|
|
return 31 + (index + self.hostname_color_offset) % 7
|
|
|
|
|
|
def setup_loggers() -> tuple[logging.Logger, logging.Logger]:
|
|
# If we use the default logger here (logging.error etc) or a logger called
|
|
# "deploykit", then cmdlog messages are also posted on the default logger.
|
|
# To avoid this message duplication, we set up a main and command logger
|
|
# and use a "deploykit" main logger.
|
|
kitlog = logging.getLogger("deploykit.main")
|
|
kitlog.setLevel(logging.INFO)
|
|
|
|
ch = logging.StreamHandler()
|
|
ch.setLevel(logging.INFO)
|
|
ch.setFormatter(logging.Formatter())
|
|
|
|
kitlog.addHandler(ch)
|
|
|
|
# use specific logger for command outputs
|
|
cmdlog = logging.getLogger("deploykit.command")
|
|
cmdlog.setLevel(logging.INFO)
|
|
|
|
ch = logging.StreamHandler()
|
|
ch.setLevel(logging.INFO)
|
|
ch.setFormatter(CommandFormatter())
|
|
|
|
cmdlog.addHandler(ch)
|
|
return (kitlog, cmdlog)
|
|
|
|
|
|
# loggers for: general deploykit, command output
|
|
kitlog, cmdlog = setup_loggers()
|
|
|
|
info = kitlog.info
|
|
warn = kitlog.warning
|
|
error = kitlog.error
|