Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions nixos/doc/manual/redirects.json
Original file line number Diff line number Diff line change
Expand Up @@ -2207,6 +2207,9 @@
"test-opt-interactive": [
"index.html#test-opt-interactive"
],
"test-opt-logLevel": [
"index.html#test-opt-logLevel"
],
"test-opt-meta": [
"index.html#test-opt-meta"
],
Expand Down
13 changes: 13 additions & 0 deletions nixos/lib/test-driver/src/test_driver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from test_driver.logger import (
CompositeLogger,
JunitXMLLogger,
LogLevel,
TerminalLogger,
XMLLogger,
)
Expand Down Expand Up @@ -151,6 +152,15 @@ def main() -> None:
help="indicates that the interactive SSH backdoor is active and dumps information about it on start",
type=int,
)
log_level_map = {level.name.lower(): level for level in LogLevel}
arg_parser.add_argument(
"--log-level",
metavar="LOG_LEVEL",
action=EnvDefault,
envvar="logLevel",
choices=log_level_map,
help="Set the log level",
)

args = arg_parser.parse_args()

Expand All @@ -169,6 +179,9 @@ def main() -> None:
if args.junit_xml:
logger.add_logger(JunitXMLLogger(output_directory / args.junit_xml))

if args.log_level:
logger.set_log_level(log_level_map[args.log_level])

if not args.keep_machine_state:
logger.info(
"Machine state will be reset. To keep it, pass --keep-machine-state"
Expand Down
45 changes: 39 additions & 6 deletions nixos/lib/test-driver/src/test_driver/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from abc import ABC, abstractmethod
from collections.abc import Iterator
from contextlib import ExitStack, contextmanager
from enum import IntEnum
from pathlib import Path
from queue import Empty, Queue
from typing import Any
Expand All @@ -17,6 +18,12 @@
from junit_xml import TestCase, TestSuite


class LogLevel(IntEnum):
INFO = 1
WARNING = 2
ERROR = 3


class AbstractLogger(ABC):
@abstractmethod
def log(self, message: str, attributes: dict[str, str] = {}) -> None:
Expand Down Expand Up @@ -56,6 +63,10 @@ def log_serial(self, message: str, machine: str) -> None:
def print_serial_logs(self, enable: bool) -> None:
pass

@abstractmethod
def set_log_level(self, level: LogLevel) -> None:
pass


class JunitXMLLogger(AbstractLogger):
class TestCaseState:
Expand All @@ -71,6 +82,7 @@ def __init__(self, outfile: Path) -> None:
self.currentSubtest = "main"
self.outfile: Path = outfile
self._print_serial_logs = True
self._log_level = LogLevel.INFO
atexit.register(self.close)

def log(self, message: str, attributes: dict[str, str] = {}) -> None:
Expand All @@ -92,10 +104,12 @@ def nested(self, message: str, attributes: dict[str, str] = {}) -> Iterator[None
yield

def info(self, *args, **kwargs) -> None: # type: ignore
self.tests[self.currentSubtest].stdout += args[0] + os.linesep
if self._log_level <= LogLevel.INFO:
self.tests[self.currentSubtest].stdout += args[0] + os.linesep

def warning(self, *args, **kwargs) -> None: # type: ignore
self.tests[self.currentSubtest].stdout += args[0] + os.linesep
if self._log_level <= LogLevel.WARNING:
self.tests[self.currentSubtest].stdout += args[0] + os.linesep

def error(self, *args, **kwargs) -> None: # type: ignore
self.tests[self.currentSubtest].stderr += args[0] + os.linesep
Expand All @@ -113,6 +127,9 @@ def log_serial(self, message: str, machine: str) -> None:
def print_serial_logs(self, enable: bool) -> None:
self._print_serial_logs = enable

def set_log_level(self, level: LogLevel) -> None:
self._log_level = level

def close(self) -> None:
with open(self.outfile, "w") as f:
test_cases = []
Expand Down Expand Up @@ -180,10 +197,15 @@ def log_serial(self, message: str, machine: str) -> None:
for logger in self.logger_list:
logger.log_serial(message, machine)

def set_log_level(self, level: LogLevel) -> None:
for logger in self.logger_list:
logger.set_log_level(level)


class TerminalLogger(AbstractLogger):
def __init__(self) -> None:
self._print_serial_logs = True
self._log_level = LogLevel.INFO

def maybe_prefix(self, message: str, attributes: dict[str, str]) -> str:
if "machine" in attributes:
Expand Down Expand Up @@ -216,17 +238,22 @@ def nested(self, message: str, attributes: dict[str, str] = {}) -> Iterator[None
self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)", attributes)

def info(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)
if self._log_level <= LogLevel.INFO:
self.log(*args, **kwargs)

def warning(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)
if self._log_level <= LogLevel.WARNING:
self.log(*args, **kwargs)

def error(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)

def print_serial_logs(self, enable: bool) -> None:
self._print_serial_logs = enable

def set_log_level(self, level: LogLevel) -> None:
self._log_level = level

def log_serial(self, message: str, machine: str) -> None:
if not self._print_serial_logs:
return
Expand All @@ -246,6 +273,7 @@ def __init__(self, outfile: str) -> None:
self.queue: Queue[dict[str, str]] = Queue()

self._print_serial_logs = True
self._log_level = LogLevel.INFO

self.xml.startDocument()
self.xml.startElement("logfile", attrs=AttributesImpl({}))
Expand All @@ -269,10 +297,12 @@ def log_line(self, message: str, attributes: dict[str, str]) -> None:
self.xml.endElement("line")

def info(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)
if self._log_level <= LogLevel.INFO:
self.log(*args, **kwargs)

def warning(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)
if self._log_level <= LogLevel.WARNING:
self.log(*args, **kwargs)

def error(self, *args, **kwargs) -> None: # type: ignore
self.log(*args, **kwargs)
Expand All @@ -287,6 +317,9 @@ def log(self, message: str, attributes: dict[str, str] = {}) -> None:
def print_serial_logs(self, enable: bool) -> None:
self._print_serial_logs = enable

def set_log_level(self, level: LogLevel) -> None:
self._log_level = level

def log_serial(self, message: str, machine: str) -> None:
if not self._print_serial_logs:
return
Expand Down
12 changes: 12 additions & 0 deletions nixos/lib/testing/driver.nix
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ let
--set testScript "$out/test-script" \
--set globalTimeout "${toString config.globalTimeout}" \
--set vlans '${toString vlans}' \
--set logLevel "${config.logLevel}" \
${lib.escapeShellArgs (
lib.concatMap (arg: [
"--add-flags"
Expand Down Expand Up @@ -219,6 +220,17 @@ in
This may speed up your iteration cycle, unless you're working on the [{option}`testScript`](#test-opt-testScript).
'';
};

logLevel = mkOption {
description = "Log level for the test driver.";
type = types.enum [
"info"
"warning"
"error"
];
default = "info";
example = "warning";
};
};

config = {
Expand Down
Loading