tuna/tuna-Add-logging-infrastruc...

160 lines
5.9 KiB
Diff

From 85330a8ab1afec5370676e7c3d753a4528f24e6f Mon Sep 17 00:00:00 2001
From: Leah Leshchinsky <lleshchi@redhat.com>
Date: Tue, 10 May 2022 11:59:07 -0400
Subject: [PATCH 1/2] tuna: Add logging infrastructure to tuna-cmd
Currently, tuna does not have an easy way for developers and maintainers
to access necessary information about the state of the program.
Add logging infrastructure that allows the user to specify, at the
command line, what level of logging to print from the following levels:
(notset, debug, info, warning, error, critical). Levels may also be
specified numerically, ranging from 0-5.
A directory will be created with the current date and test run.
Logging statements will print to a log file within the created directory,
and can be specified with the '-L' and '--logging' flags. The '-D' and
'--debug' flags will print all debug information to the console.
Logging of other files outside of tuna-cmd.py can be implemented by
importing the logging directory and adding the necessary logging
statments.
Signed-off-by: Leah Leshchinsky <lleshchi@redhat.com>
Signed-off-by: John Kacur <jkacur@redhat.com>
diff --git a/tuna-cmd.py b/tuna-cmd.py
index ac21481df554..57b62298c48a 100755
--- a/tuna-cmd.py
+++ b/tuna-cmd.py
@@ -29,6 +29,50 @@ import ethtool
import tuna.tuna_sched as tuna_sched
import procfs
from tuna import tuna, sysfs
+import logging
+import time
+
+def get_loglevel(level):
+ if level.isdigit() and int(level) in range(0,5):
+ # logging built-in module levels:
+ # 0 - NOTSET
+ # 10 - DEBUG
+ # 20 - INFO,
+ # 30 - WARNING
+ # 40 - ERROR
+ return int(level) * 10
+ level_str = level.upper()
+ if level_str == "CRITICAL":
+ raise ValueError("CRITICAL level is not supported by tuna")
+ return level_str
+
+def setup_logging(logger_name):
+
+ logger = logging.getLogger(logger_name)
+ logger.setLevel(logging.DEBUG)
+ logger.propagate = False
+ return logger
+
+def add_handler(loglevel, tofile=False):
+
+ formatter = logging.Formatter('[%(levelname)s] %(message)s')
+
+ if tofile:
+ lognum = 1
+ date = time.strftime("%Y%m%d")
+ while os.path.exists("tuna-{}-{}".format(date, lognum)):
+ lognum += 1
+
+ path = "tuna-{}-{}/log/Log".format(date,lognum)
+ os.makedirs(os.path.dirname(path), exist_ok=True, mode=0o777)
+ handler = logging.FileHandler(path)
+ else:
+ handler = logging.StreamHandler(sys.stderr)
+
+ handler.setFormatter(formatter)
+ handler.setLevel(loglevel)
+
+ return handler
try:
import inet_diag
@@ -61,6 +105,7 @@ def usage():
_('Operation will affect children threads')))
print(fmt % ('-d, --disable_perf',
_('Explicitly disable usage of perf in GUI for process view')))
+ print(fmt % ('-D, --debug', _('Print DEBUG level logging details to console')))
print(fmt % ('-f, --filter',
_('Display filter the selected entities')))
print(fmt % ('-i, --isolate', _('Move all allowed threads and IRQs away from %(cpulist)s') %
@@ -69,6 +114,8 @@ def usage():
{"cpulist": _('CPU-LIST')}))
print(fmt % ('-K, --no_kthreads',
_('Operations will not affect kernel threads')))
+ print(fmt % ('-L, --logging',
+ _('Log application details to log file for given LOG-LEVEL')))
print(fmt % ('-m, --move', _('Move selected entities to %(cpulist)s') %
{"cpulist": _('CPU-LIST')}))
print(fmt % ('-N, --nohz_full',
@@ -490,14 +537,14 @@ def main():
i18n_init()
try:
- short = "a:c:dCfgGhiIKlmNp:PQq:r:R:s:S:t:UvWx"
+ short = "a:c:dDCfgGhiIKlmNp:PQq:r:R:s:S:t:UvWxL:"
long = ["cpus=", "affect_children", "filter", "gui", "help",
"isolate", "include", "no_kthreads", "move", "nohz_full",
"show_sockets", "priority=", "show_threads",
"show_irqs", "irqs=",
"save=", "sockets=", "threads=", "no_uthreads",
"version", "what_is", "spread", "cgroup", "config_file_apply=",
- "config_file_list", "run=", "refresh=", "disable_perf"]
+ "config_file_list", "run=", "refresh=", "disable_perf", "logging=", "debug"]
if have_inet_diag:
short += "n"
long.append("show_sockets")
@@ -512,8 +559,10 @@ def main():
uthreads = True
cgroups = False
cpu_list = None
+ debug = False
irq_list = None
irq_list_str = None
+ log = False
rtprio = None
policy = None
thread_list = []
@@ -529,6 +578,30 @@ def main():
if o in ("-h", "--help"):
usage()
return
+ if o in ("-D", "--debug"):
+ if debug:
+ my_logger.warning("Debugging already set")
+ continue
+ debug = True
+ if not log:
+ my_logger = setup_logging("my_logger")
+ my_logger.addHandler(add_handler("DEBUG", tofile=False))
+ my_logger.info("Debug option set")
+ if o in ("-L", "--logging"):
+ if log:
+ my_logger.warning("Logging already set")
+ continue
+ log = True
+ loglevel = get_loglevel(a)
+ if not debug:
+ my_logger = setup_logging("my_logger")
+ try:
+ my_logger.addHandler(add_handler(loglevel, tofile=True))
+ except ValueError as e:
+ print(e, "tuna: --logging requires valid logging level\n")
+ print("Valid log levels: NOTSET, DEBUG, INFO, WARNING, ERROR")
+ print("Log levels may be specified numerically (0-4)")
+ my_logger.info("Logging option set")
if o in ("-a", "--config_file_apply"):
apply_config(a)
elif o in ("-l", "--config_file_list"):
--
2.27.0