diff --git a/docs/env.md b/docs/env.md index 8264b5ed6..748fb4809 100644 --- a/docs/env.md +++ b/docs/env.md @@ -13,12 +13,9 @@ GALLIA_CONFIG : The path to the config file usually called `gallia.toml`. Disables autodiscovery of the config. -GALLIA_LOGLEVEL -: When {meth}`gallia.log.setup_logging()` is called without an argument this environment variable is read to set the loglevel. - Supported value are: `trace`, `debug`, `info`, `notice`, `warning`, `error`, `critical`. - As an alternative, the int values from 0 to 7 can be used. - Mostly useful in own scripts or tests. - This variable is not read when using the gallia cli. +GALLIA_LOGGING_SYSTEMD +: Tells gallia to omit colors and status bars in logging output. + Additionally, the priority information gets added such that the journal can add it. NO_COLOR : If this variable is set, `gallia` by default does not use color codes, see: https://no-color.org/ diff --git a/src/gallia/log.py b/src/gallia/log.py index f3ad090e5..f3e4dd2e3 100644 --- a/src/gallia/log.py +++ b/src/gallia/log.py @@ -243,18 +243,12 @@ def setup_logging( logging. :param level: The loglevel to enable for the console handler. - If this argument is None, the env variable - ``GALLIA_LOGLEVEL`` (see :doc:`../env`) is read. :param file_level: The loglevel to enable for the file handler. :param path: The path to the logfile containing json records. :param color_mode: The color mode to use for the console. """ if level is None: - # FIXME why is this here and not in config? - if (raw := os.getenv("GALLIA_LOGLEVEL")) is not None: - level = PenlogPriority.from_str(raw).to_level() - else: - level = Loglevel.DEBUG + level = Loglevel.DEBUG # These are slow and not used by gallia. logging.logMultiprocessing = False @@ -344,9 +338,9 @@ class _PenlogRecordV2(msgspec.Struct, omit_defaults=True, tag=2, tag_field="vers _PenlogRecord: TypeAlias = _PenlogRecordV2 -def _colorize_msg(data: str, levelno: int) -> tuple[str, int]: +def _colorize_msg(data: str, levelno: int) -> str: if sys.platform == "win32" or not sys.stderr.isatty(): - return data, 0 + return data out = "" match levelno: @@ -371,7 +365,12 @@ def _colorize_msg(data: str, levelno: int) -> tuple[str, int]: out += data out += _Color.RESET.value - return out, len(style) + return out + + +def _delete_cur_line() -> None: + sys.stderr.write("\33[2K\r") + sys.stderr.flush() def _format_record( # noqa: PLR0913 @@ -384,36 +383,49 @@ def _format_record( # noqa: PLR0913 colored: bool = False, volatile_info: bool = False, ) -> str: + systemd = True if "GALLIA_LOGGING_SYSTEMD" in os.environ else False + if systemd: + colored = False + volatile_info = False + + delete_line = volatile_info and levelno <= Loglevel.INFO + if delete_line: + _delete_cur_line() + msg = "" - if volatile_info: - msg += "\33[2K" - extra_len = 4 - msg += dt.strftime("%b %d %H:%M:%S.%f")[:-3] - msg += " " + + # Add the priority info for the systemd journal… + if systemd: + msg += f"<{PenlogPriority.from_level(levelno).value}>" + # …else add timestamps if gallia runs under a terminal. + else: + msg += f"{dt.strftime('%b %d %H:%M:%S.%f')[:-3]} " + msg += name if tags is not None and len(tags) > 0: msg += f" [{', '.join(tags)}]" msg += ": " if colored: - tmp_msg, extra_len_tmp = _colorize_msg(data, levelno) - msg += tmp_msg - extra_len += extra_len_tmp + msg += _colorize_msg(data, levelno) else: msg += data - if volatile_info and levelno <= Loglevel.INFO: - terminal_width, _ = shutil.get_terminal_size() - msg = msg[: terminal_width + extra_len - 1] # Adapt length to invisible ANSI colors - msg += _Color.RESET.value - msg += "\r" - else: - msg += "\n" - if stacktrace is not None: msg += "\n" msg += stacktrace + if delete_line: + # Truncate the line that gets deleted in + # in case the terminal wraps the line. + cols, _ = shutil.get_terminal_size() + msg = msg[:cols] + if colored: + msg = msg[:-2] + _Color.RESET.value + msg += "\r" + else: + msg += "\n" + return msg