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()
