From patchwork Wed Dec 20 10:33:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Juraj_Linke=C5=A1?= X-Patchwork-Id: 135392 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 39FE243723; Wed, 20 Dec 2023 11:34:19 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 281ED42EBA; Wed, 20 Dec 2023 11:33:47 +0100 (CET) Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) by mails.dpdk.org (Postfix) with ESMTP id E14E442EB3 for ; Wed, 20 Dec 2023 11:33:45 +0100 (CET) Received: by mail-lj1-f178.google.com with SMTP id 38308e7fff4ca-2cc61d4e5aeso48633591fa.0 for ; Wed, 20 Dec 2023 02:33:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pantheon.tech; s=google; t=1703068425; x=1703673225; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9dlYuGyfG0mULoa76SHQ1yVBwxqmADwYFieC9qyU4SU=; b=hQO6pHzJ+Mgx1jwgQhaOfEBo/g/KdK1HkwaIz4yqaeC36N5zB87zjf9CoRdj/n4HuC u8d85raBhNtbC0uPD/vMLSHDeOYlmDLFrOknOVF8UgZV2yz4HaieU//hnLuRMan/3ZSr mu2UaaYcWsJTddGUe2Sx4W12JacPi8C9wzspg28DSQi3aUxDKg0Z7LKDLMfnjjBJmeIK 60ZFnjQjvKsuL3QbiUxlDT32srRjAhHfk8zKIFz8cNdV6I4NNMBBldzJIgCWxfYJr0OS zdLuzzlLrVBGVyhLHnPDBisMisEEvVz5G4KxaeTnwBAVQG5lHeJLMPVRKWiPg483a2YV tpuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703068425; x=1703673225; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9dlYuGyfG0mULoa76SHQ1yVBwxqmADwYFieC9qyU4SU=; b=ejlFqoEuTcnIeP48zsqGIqHTGG/HlScACUYjcCU/pkhgLoA7BYzugjm/cu/4gKc/g3 eIbizbCB/uPF4DWVDsnfmGa0LySl8tLBbxwxN08e4dFqMV73yR3RrMw6zm+GSQ3umrCl kjgOFbvWTt/oVKnMNkKAIdZq/ZvdZk46YQQGoz9y8qLXOeeIDPpy1ew+4TT+TGZR88w2 cJ/Shv5LY8zlbW1NQ0DuJpKjEJt51ilt8WuCoFaYvosFyypL9oeVHESPYb4Qk0NRT8wf jTkYF89YRhJvjg0M4ylRIlQD/SVu7CXH45xxqBaNlzpQLJ9rXT/lgHqowcESCtpZkKYs Uhiw== X-Gm-Message-State: AOJu0YwMfi3JdggvzJwhfiHXCQgF6sF1QCijXZQ+AG275I4TyHo3zGW/ mvtGJJ+xLqrV1bIaBfTN3B4IQA== X-Google-Smtp-Source: AGHT+IENLswAlPpLfkHo75mROczPuUg55n/kuCqhcwyi+fb7VpFT+MZ7r81fvkroQtNlyp44oZ1caA== X-Received: by 2002:a05:6512:a8b:b0:50e:d55:3927 with SMTP id m11-20020a0565120a8b00b0050e0d553927mr7992990lfu.66.1703068425306; Wed, 20 Dec 2023 02:33:45 -0800 (PST) Received: from jlinkes-PT-Latitude-5530.pantheon.local (81.89.53.154.host.vnet.sk. [81.89.53.154]) by smtp.gmail.com with ESMTPSA id bd18-20020a056402207200b00542db304680sm12588981edb.63.2023.12.20.02.33.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Dec 2023 02:33:44 -0800 (PST) From: =?utf-8?q?Juraj_Linke=C5=A1?= To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, jspewock@iol.unh.edu, probb@iol.unh.edu, paul.szczepanek@arm.com, yoan.picchi@foss.arm.com, Luca.Vizzarro@arm.com Cc: dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= Subject: [RFC PATCH v1 5/5] dts: refactor logging configuration Date: Wed, 20 Dec 2023 11:33:31 +0100 Message-Id: <20231220103331.60888-6-juraj.linkes@pantheon.tech> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231220103331.60888-1-juraj.linkes@pantheon.tech> References: <20231220103331.60888-1-juraj.linkes@pantheon.tech> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Refactor logging for improved configuration and flexibility, investigating unclear arguments and exploring alternatives for logging test suites into separate files. In addition, efforts were made to ensure that the modules remained independent from the logger module, enabling potential use by other consumers. Signed-off-by: Juraj Linkeš --- dts/framework/logger.py | 162 ++++++++---------- dts/framework/remote_session/__init__.py | 4 +- dts/framework/remote_session/os_session.py | 6 +- .../remote_session/remote/__init__.py | 7 +- .../remote/interactive_remote_session.py | 7 +- .../remote/interactive_shell.py | 7 +- .../remote_session/remote/remote_session.py | 8 +- .../remote_session/remote/ssh_session.py | 5 +- dts/framework/runner.py | 13 +- dts/framework/test_result.py | 6 +- dts/framework/test_suite.py | 6 +- dts/framework/testbed_model/node.py | 10 +- dts/framework/testbed_model/scapy.py | 6 +- .../testbed_model/traffic_generator.py | 5 +- dts/main.py | 6 +- 15 files changed, 124 insertions(+), 134 deletions(-) diff --git a/dts/framework/logger.py b/dts/framework/logger.py index bb2991e994..43c49c2d03 100644 --- a/dts/framework/logger.py +++ b/dts/framework/logger.py @@ -10,108 +10,98 @@ import logging import os.path -from typing import TypedDict - -from .settings import SETTINGS +from enum import Enum +from logging import FileHandler, StreamHandler +from pathlib import Path date_fmt = "%Y/%m/%d %H:%M:%S" -stream_fmt = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" +stream_fmt = "%(asctime)s - %(stage)s - %(name)s - %(levelname)s - %(message)s" -class LoggerDictType(TypedDict): - logger: "DTSLOG" - name: str - node: str +def init_logger(verbose: bool, output_dir: str): + logging.raiseExceptions = False + DTSLog._output_dir = output_dir + logging.setLoggerClass(DTSLog) -# List for saving all using loggers -Loggers: list[LoggerDictType] = [] + root_logger = logging.getLogger() + root_logger.setLevel(1) + sh = StreamHandler() + sh.setFormatter(logging.Formatter(stream_fmt, date_fmt)) + sh.setLevel(logging.INFO) + if verbose: + sh.setLevel(logging.DEBUG) + root_logger.addHandler(sh) -class DTSLOG(logging.LoggerAdapter): - """ - DTS log class for framework and testsuite. - """ + if not os.path.exists(output_dir): + os.mkdir(output_dir) - _logger: logging.Logger - node: str - sh: logging.StreamHandler - fh: logging.FileHandler - verbose_fh: logging.FileHandler + add_file_handlers(Path(output_dir, "dts")) - def __init__(self, logger: logging.Logger, node: str = "suite"): - self._logger = logger - # 1 means log everything, this will be used by file handlers if their level - # is not set - self._logger.setLevel(1) - self.node = node +def add_file_handlers(log_file_path: Path) -> list[FileHandler]: + root_logger = logging.getLogger() - # add handler to emit to stdout - sh = logging.StreamHandler() - sh.setFormatter(logging.Formatter(stream_fmt, date_fmt)) - sh.setLevel(logging.INFO) # console handler default level + fh = FileHandler(f"{log_file_path}.log") + fh.setFormatter(logging.Formatter(stream_fmt, date_fmt)) + root_logger.addHandler(fh) - if SETTINGS.verbose is True: - sh.setLevel(logging.DEBUG) + verbose_fh = FileHandler(f"{log_file_path}.verbose.log") + verbose_fh.setFormatter( + logging.Formatter( + "%(asctime)s|%(stage)s|%(name)s|%(levelname)s|%(pathname)s|%(lineno)d|" + "%(funcName)s|%(process)d|%(thread)d|%(threadName)s|%(message)s", + datefmt=date_fmt, + ) + ) + root_logger.addHandler(verbose_fh) - self._logger.addHandler(sh) - self.sh = sh + return [fh, verbose_fh] - # prepare the output folder - if not os.path.exists(SETTINGS.output_dir): - os.mkdir(SETTINGS.output_dir) - logging_path_prefix = os.path.join(SETTINGS.output_dir, node) +class DtsStage(Enum): + pre_execution = "pre-execution" + execution = "execution" + build_target = "build-target" + suite = "suite" + post_execution = "post-execution" - fh = logging.FileHandler(f"{logging_path_prefix}.log") - fh.setFormatter( - logging.Formatter( - fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s", - datefmt=date_fmt, - ) - ) + def __str__(self) -> str: + return self.value - self._logger.addHandler(fh) - self.fh = fh - - # This outputs EVERYTHING, intended for post-mortem debugging - # Also optimized for processing via AWK (awk -F '|' ...) - verbose_fh = logging.FileHandler(f"{logging_path_prefix}.verbose.log") - verbose_fh.setFormatter( - logging.Formatter( - fmt="%(asctime)s|%(name)s|%(levelname)s|%(pathname)s|%(lineno)d|" - "%(funcName)s|%(process)d|%(thread)d|%(threadName)s|%(message)s", - datefmt=date_fmt, - ) - ) - self._logger.addHandler(verbose_fh) - self.verbose_fh = verbose_fh - - super(DTSLOG, self).__init__(self._logger, dict(node=self.node)) - - def logger_exit(self) -> None: - """ - Remove stream handler and logfile handler. - """ - for handler in (self.sh, self.fh, self.verbose_fh): - handler.flush() - self._logger.removeHandler(handler) - - -def getLogger(name: str, node: str = "suite") -> DTSLOG: - """ - Get logger handler and if there's no handler for specified Node will create one. - """ - global Loggers - # return saved logger - logger: LoggerDictType - for logger in Loggers: - if logger["name"] == name and logger["node"] == node: - return logger["logger"] - - # return new logger - dts_logger: DTSLOG = DTSLOG(logging.getLogger(name), node) - Loggers.append({"logger": dts_logger, "name": name, "node": node}) - return dts_logger +class DTSLog(logging.Logger): + _stage: DtsStage = DtsStage.pre_execution + _extra_file_handlers: list[FileHandler] = [] + _output_dir: None | str = None + + def makeRecord(self, *args, **kwargs): + record = super().makeRecord(*args, **kwargs) + record.stage = DTSLog._stage + return record + + def set_stage(self, stage: DtsStage, log_file_name: str | None = None): + self._remove_extra_file_handlers() + + if DTSLog._stage != stage: + self.info(f"Moving from stage '{DTSLog._stage}' to stage '{stage}'.") + DTSLog._stage = stage + + if log_file_name: + if DTSLog._output_dir: + DTSLog._extra_file_handlers.extend( + add_file_handlers(Path(DTSLog._output_dir, log_file_name)) + ) + else: + self.warning( + f"Cannot log '{DTSLog._stage}' stage in separate file, " + "output dir is not defined." + ) + + def _remove_extra_file_handlers(self) -> None: + if DTSLog._extra_file_handlers: + for extra_file_handler in DTSLog._extra_file_handlers: + self.root.removeHandler(extra_file_handler) + + DTSLog._extra_file_handlers = [] diff --git a/dts/framework/remote_session/__init__.py b/dts/framework/remote_session/__init__.py index 6124417bd7..a4ec2f40ae 100644 --- a/dts/framework/remote_session/__init__.py +++ b/dts/framework/remote_session/__init__.py @@ -11,10 +11,10 @@ """ # pylama:ignore=W0611 +import logging from framework.config import OS, NodeConfiguration from framework.exception import ConfigurationError -from framework.logger import DTSLOG from .linux_session import LinuxSession from .os_session import InteractiveShellType, OSSession @@ -30,7 +30,7 @@ ) -def create_session(node_config: NodeConfiguration, name: str, logger: DTSLOG) -> OSSession: +def create_session(node_config: NodeConfiguration, name: str, logger: logging.Logger) -> OSSession: match node_config.os: case OS.linux: return LinuxSession(node_config, name, logger) diff --git a/dts/framework/remote_session/os_session.py b/dts/framework/remote_session/os_session.py index 8a709eac1c..2524a4e669 100644 --- a/dts/framework/remote_session/os_session.py +++ b/dts/framework/remote_session/os_session.py @@ -2,6 +2,7 @@ # Copyright(c) 2023 PANTHEON.tech s.r.o. # Copyright(c) 2023 University of New Hampshire +import logging from abc import ABC, abstractmethod from collections.abc import Iterable from ipaddress import IPv4Interface, IPv6Interface @@ -9,7 +10,6 @@ from typing import Type, TypeVar, Union from framework.config import Architecture, NodeConfiguration, NodeInfo -from framework.logger import DTSLOG from framework.remote_session.remote import InteractiveShell from framework.settings import SETTINGS from framework.testbed_model import LogicalCore @@ -36,7 +36,7 @@ class OSSession(ABC): _config: NodeConfiguration name: str - _logger: DTSLOG + _logger: logging.Logger remote_session: RemoteSession interactive_session: InteractiveRemoteSession @@ -44,7 +44,7 @@ def __init__( self, node_config: NodeConfiguration, name: str, - logger: DTSLOG, + logger: logging.Logger, ): self._config = node_config self.name = name diff --git a/dts/framework/remote_session/remote/__init__.py b/dts/framework/remote_session/remote/__init__.py index 06403691a5..4a22155153 100644 --- a/dts/framework/remote_session/remote/__init__.py +++ b/dts/framework/remote_session/remote/__init__.py @@ -4,8 +4,9 @@ # pylama:ignore=W0611 +import logging + from framework.config import NodeConfiguration -from framework.logger import DTSLOG from .interactive_remote_session import InteractiveRemoteSession from .interactive_shell import InteractiveShell @@ -16,12 +17,12 @@ def create_remote_session( - node_config: NodeConfiguration, name: str, logger: DTSLOG + node_config: NodeConfiguration, name: str, logger: logging.Logger ) -> RemoteSession: return SSHSession(node_config, name, logger) def create_interactive_session( - node_config: NodeConfiguration, logger: DTSLOG + node_config: NodeConfiguration, logger: logging.Logger ) -> InteractiveRemoteSession: return InteractiveRemoteSession(node_config, logger) diff --git a/dts/framework/remote_session/remote/interactive_remote_session.py b/dts/framework/remote_session/remote/interactive_remote_session.py index 098ded1bb0..bf0996a747 100644 --- a/dts/framework/remote_session/remote/interactive_remote_session.py +++ b/dts/framework/remote_session/remote/interactive_remote_session.py @@ -2,7 +2,7 @@ # Copyright(c) 2023 University of New Hampshire """Handler for an SSH session dedicated to interactive shells.""" - +import logging import socket import traceback @@ -16,7 +16,6 @@ from framework.config import NodeConfiguration from framework.exception import SSHConnectionError -from framework.logger import DTSLOG class InteractiveRemoteSession: @@ -54,11 +53,11 @@ class InteractiveRemoteSession: username: str password: str session: SSHClient - _logger: DTSLOG + _logger: logging.Logger _node_config: NodeConfiguration _transport: Transport | None - def __init__(self, node_config: NodeConfiguration, _logger: DTSLOG) -> None: + def __init__(self, node_config: NodeConfiguration, _logger: logging.Logger) -> None: self._node_config = node_config self._logger = _logger self.hostname = node_config.hostname diff --git a/dts/framework/remote_session/remote/interactive_shell.py b/dts/framework/remote_session/remote/interactive_shell.py index 4db19fb9b3..b6074838c2 100644 --- a/dts/framework/remote_session/remote/interactive_shell.py +++ b/dts/framework/remote_session/remote/interactive_shell.py @@ -11,14 +11,13 @@ elevated privileges to start it is expected that the method for gaining those privileges is provided when initializing the class. """ - +import logging from abc import ABC from pathlib import PurePath from typing import Callable from paramiko import Channel, SSHClient, channel # type: ignore[import] -from framework.logger import DTSLOG from framework.settings import SETTINGS @@ -58,7 +57,7 @@ class InteractiveShell(ABC): _stdin: channel.ChannelStdinFile _stdout: channel.ChannelFile _ssh_channel: Channel - _logger: DTSLOG + _logger: logging.Logger _timeout: float _app_args: str _default_prompt: str = "" @@ -69,7 +68,7 @@ class InteractiveShell(ABC): def __init__( self, interactive_session: SSHClient, - logger: DTSLOG, + logger: logging.Logger, get_privileged_command: Callable[[str], str] | None, app_args: str = "", timeout: float = SETTINGS.timeout, diff --git a/dts/framework/remote_session/remote/remote_session.py b/dts/framework/remote_session/remote/remote_session.py index 719f7d1ef7..da78e5c921 100644 --- a/dts/framework/remote_session/remote/remote_session.py +++ b/dts/framework/remote_session/remote/remote_session.py @@ -2,14 +2,13 @@ # Copyright(c) 2010-2014 Intel Corporation # Copyright(c) 2022-2023 PANTHEON.tech s.r.o. # Copyright(c) 2022-2023 University of New Hampshire - import dataclasses +import logging from abc import ABC, abstractmethod from pathlib import PurePath from framework.config import NodeConfiguration from framework.exception import RemoteCommandExecutionError -from framework.logger import DTSLOG from framework.settings import SETTINGS @@ -50,14 +49,14 @@ class RemoteSession(ABC): username: str password: str history: list[CommandResult] - _logger: DTSLOG + _logger: logging.Logger _node_config: NodeConfiguration def __init__( self, node_config: NodeConfiguration, session_name: str, - logger: DTSLOG, + logger: logging.Logger, ): self._node_config = node_config @@ -120,7 +119,6 @@ def close(self, force: bool = False) -> None: """ Close the remote session and free all used resources. """ - self._logger.logger_exit() self._close(force) @abstractmethod diff --git a/dts/framework/remote_session/remote/ssh_session.py b/dts/framework/remote_session/remote/ssh_session.py index 1a7ee649ab..42441c4587 100644 --- a/dts/framework/remote_session/remote/ssh_session.py +++ b/dts/framework/remote_session/remote/ssh_session.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2023 PANTHEON.tech s.r.o. - +import logging import socket import traceback from pathlib import PurePath @@ -20,7 +20,6 @@ from framework.config import NodeConfiguration from framework.exception import SSHConnectionError, SSHSessionDeadError, SSHTimeoutError -from framework.logger import DTSLOG from .remote_session import CommandResult, RemoteSession @@ -49,7 +48,7 @@ def __init__( self, node_config: NodeConfiguration, session_name: str, - logger: DTSLOG, + logger: logging.Logger, ): super(SSHSession, self).__init__(node_config, session_name, logger) diff --git a/dts/framework/runner.py b/dts/framework/runner.py index 28570d4a1c..5c06e4ca1a 100644 --- a/dts/framework/runner.py +++ b/dts/framework/runner.py @@ -11,6 +11,7 @@ from copy import deepcopy from dataclasses import dataclass from types import MethodType, ModuleType +from typing import cast from .config import ( BuildTargetConfiguration, @@ -24,7 +25,7 @@ SSHTimeoutError, TestCaseVerifyError, ) -from .logger import DTSLOG, getLogger +from .logger import DTSLog, DtsStage from .settings import SETTINGS from .test_result import ( BuildTargetResult, @@ -68,12 +69,12 @@ def processed_config(self) -> ExecutionConfiguration: class DTSRunner: - _logger: DTSLOG + _logger: DTSLog _result: DTSResult _executions: list[Execution] def __init__(self, configuration: Configuration): - self._logger = getLogger("DTSRunner") + self._logger = cast(DTSLog, logging.getLogger("DTSRunner")) self._result = DTSResult(configuration, self._logger) self._executions = create_executions(configuration.executions) @@ -146,6 +147,7 @@ def _run_execution( Run the given execution. This involves running the execution setup as well as running all build targets in the given execution. """ + self._logger.set_stage(DtsStage.execution) self._logger.info( "Running execution with SUT " f"'{execution.config.system_under_test_node.name}'." @@ -175,6 +177,7 @@ def _run_execution( sut_node.tear_down_execution() execution_result.update_teardown(Result.PASS) except Exception as e: + self._logger.set_stage(DtsStage.execution) self._logger.exception("Execution teardown failed.") execution_result.update_teardown(Result.FAIL, e) @@ -189,6 +192,7 @@ def _run_build_target( """ Run the given build target. """ + self._logger.set_stage(DtsStage.build_target) self._logger.info(f"Running build target '{build_target.name}'.") build_target_result = execution_result.add_child_result(build_target) @@ -209,6 +213,7 @@ def _run_build_target( sut_node.tear_down_build_target() build_target_result.update_teardown(Result.PASS) except Exception as e: + self._logger.set_stage(DtsStage.build_target) self._logger.exception("Build target teardown failed.") build_target_result.update_teardown(Result.FAIL, e) @@ -265,6 +270,7 @@ def _run_test_suite( """ test_suite = test_suite_setup.test_suite(sut_node, tg_node) test_suite_name = test_suite_setup.test_suite.__name__ + self._logger.set_stage(DtsStage.suite, test_suite_name) test_suite_result = build_target_result.add_child_result( test_suite_setup.processed_config() ) @@ -397,6 +403,7 @@ def _exit_dts(self) -> None: self._result.process() if self._logger: + self._logger.set_stage(DtsStage.post_execution) self._logger.info("DTS execution has ended.") logging.shutdown() diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py index dba2c55d36..221e75205e 100644 --- a/dts/framework/test_result.py +++ b/dts/framework/test_result.py @@ -6,6 +6,7 @@ Generic result container and reporters """ +import logging import os.path from collections.abc import MutableSequence from enum import Enum, auto @@ -24,7 +25,6 @@ TestSuiteConfig, ) from .exception import DTSError, ErrorSeverity -from .logger import DTSLOG from .settings import SETTINGS @@ -153,13 +153,13 @@ class DTSResult(BaseResult): dpdk_version: str | None _child_configs: list[ExecutionConfiguration] - _logger: DTSLOG + _logger: logging.Logger _errors: list[Exception] _return_code: ErrorSeverity _stats_result: Union["Statistics", None] _stats_filename: str - def __init__(self, configuration: Configuration, logger: DTSLOG): + def __init__(self, configuration: Configuration, logger: logging.Logger): super(DTSResult, self).__init__() self.dpdk_version = None self._child_configs = configuration.executions diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py index e73206993d..9c9a8c1e08 100644 --- a/dts/framework/test_suite.py +++ b/dts/framework/test_suite.py @@ -6,6 +6,7 @@ Base class for creating DTS test cases. """ +import logging from ipaddress import IPv4Interface, IPv6Interface, ip_interface from typing import Union @@ -14,7 +15,6 @@ from scapy.packet import Packet, Padding # type: ignore[import] from .exception import TestCaseVerifyError -from .logger import DTSLOG, getLogger from .testbed_model import SutNode, TGNode from .testbed_model.hw.port import Port, PortLink from .utils import get_packet_summaries @@ -41,7 +41,7 @@ class TestSuite(object): sut_node: SutNode tg_node: TGNode is_blocking = False - _logger: DTSLOG + _logger: logging.Logger _port_links: list[PortLink] _sut_port_ingress: Port _sut_port_egress: Port @@ -59,7 +59,7 @@ def __init__( ): self.sut_node = sut_node self.tg_node = tg_node - self._logger = getLogger(self.__class__.__name__) + self._logger = logging.getLogger(self.__class__.__name__) self._port_links = [] self._process_links() self._sut_port_ingress, self._tg_port_egress = ( diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py index ef700d8114..a98c58df4f 100644 --- a/dts/framework/testbed_model/node.py +++ b/dts/framework/testbed_model/node.py @@ -6,7 +6,7 @@ """ A node is a generic host that DTS connects to and manages. """ - +import logging from abc import ABC from ipaddress import IPv4Interface, IPv6Interface from typing import Any, Callable, Type, Union @@ -16,7 +16,6 @@ ExecutionConfiguration, NodeConfiguration, ) -from framework.logger import DTSLOG, getLogger from framework.remote_session import InteractiveShellType, OSSession, create_session from framework.settings import SETTINGS @@ -43,7 +42,7 @@ class Node(ABC): name: str lcores: list[LogicalCore] ports: list[Port] - _logger: DTSLOG + _logger: logging.Logger _other_sessions: list[OSSession] _execution_config: ExecutionConfiguration virtual_devices: list[VirtualDevice] @@ -51,7 +50,7 @@ class Node(ABC): def __init__(self, node_config: NodeConfiguration): self.config = node_config self.name = node_config.name - self._logger = getLogger(self.name) + self._logger = logging.getLogger(self.name) self.main_session = create_session(self.config, self.name, self._logger) self._logger.info(f"Connected to node: {self.name}") @@ -137,7 +136,7 @@ def create_session(self, name: str) -> OSSession: connection = create_session( self.config, session_name, - getLogger(session_name, node=self.name), + logging.getLogger(session_name), ) self._other_sessions.append(connection) return connection @@ -237,7 +236,6 @@ def close(self) -> None: self.main_session.close() for session in self._other_sessions: session.close() - self._logger.logger_exit() @staticmethod def skip_setup(func: Callable[..., Any]) -> Callable[..., Any]: diff --git a/dts/framework/testbed_model/scapy.py b/dts/framework/testbed_model/scapy.py index 9083e92b3d..61058cd38a 100644 --- a/dts/framework/testbed_model/scapy.py +++ b/dts/framework/testbed_model/scapy.py @@ -13,6 +13,7 @@ """ import inspect +import logging import marshal import time import types @@ -24,7 +25,6 @@ from scapy.packet import Packet # type: ignore[import] from framework.config import OS, ScapyTrafficGeneratorConfig -from framework.logger import DTSLOG, getLogger from framework.remote_session import PythonShell from framework.settings import SETTINGS @@ -190,12 +190,12 @@ class ScapyTrafficGenerator(CapturingTrafficGenerator): rpc_server_proxy: xmlrpc.client.ServerProxy _config: ScapyTrafficGeneratorConfig _tg_node: TGNode - _logger: DTSLOG + _logger: logging.Logger def __init__(self, tg_node: TGNode, config: ScapyTrafficGeneratorConfig): self._config = config self._tg_node = tg_node - self._logger = getLogger(f"{self._tg_node.name} {self._config.traffic_generator_type}") + self._logger = logging.getLogger(f"{self._tg_node.name} {self._config.traffic_generator_type}") assert ( self._tg_node.config.os == OS.linux diff --git a/dts/framework/testbed_model/traffic_generator.py b/dts/framework/testbed_model/traffic_generator.py index 28c35d3ce4..6b0838958a 100644 --- a/dts/framework/testbed_model/traffic_generator.py +++ b/dts/framework/testbed_model/traffic_generator.py @@ -7,12 +7,11 @@ These traffic generators can't capture received traffic, only count the number of received packets. """ - +import logging from abc import ABC, abstractmethod from scapy.packet import Packet # type: ignore[import] -from framework.logger import DTSLOG from framework.utils import get_packet_summaries from .hw.port import Port @@ -24,7 +23,7 @@ class TrafficGenerator(ABC): Defines the few basic methods that each traffic generator must implement. """ - _logger: DTSLOG + _logger: logging.Logger def send_packet(self, packet: Packet, port: Port) -> None: """Send a packet and block until it is fully sent. diff --git a/dts/main.py b/dts/main.py index 879ce5cb89..f2828148f0 100755 --- a/dts/main.py +++ b/dts/main.py @@ -8,18 +8,18 @@ A test framework for testing DPDK. """ -import logging - from framework.config import load_config +from framework.logger import init_logger from framework.runner import DTSRunner +from framework.settings import SETTINGS def main() -> None: + init_logger(SETTINGS.verbose, SETTINGS.output_dir) dts = DTSRunner(configuration=load_config()) dts.run() # Main program begins here if __name__ == "__main__": - logging.raiseExceptions = True main()