From bf664cde78d7ce00953a75290fb09c408c6bc47b Mon Sep 17 00:00:00 2001 From: Leah Leshchinsky Date: Wed, 11 May 2022 18:25:19 +0000 Subject: [PATCH] Add logging infrastructure to tuna --- tuna-Add-cleanlogs-rule-to-Makefile.patch | 31 ++++ ...d-logging-infrastructure-to-tuna-cmd.patch | 159 ++++++++++++++++++ tuna.spec | 11 +- 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 tuna-Add-cleanlogs-rule-to-Makefile.patch create mode 100644 tuna-Add-logging-infrastructure-to-tuna-cmd.patch diff --git a/tuna-Add-cleanlogs-rule-to-Makefile.patch b/tuna-Add-cleanlogs-rule-to-Makefile.patch new file mode 100644 index 0000000..dca3db9 --- /dev/null +++ b/tuna-Add-cleanlogs-rule-to-Makefile.patch @@ -0,0 +1,31 @@ +From 681304a9a57a9c2b05fcc2cc372e3d921b5ff415 Mon Sep 17 00:00:00 2001 +From: Leah Leshchinsky +Date: Tue, 10 May 2022 11:59:08 -0400 +Subject: [PATCH 2/2] tuna: Add cleanlogs rule to Makefile + +The logging infrastructure creates directories that contain log files. +It may be tedious for users to manually remove these directories and +files. + +Add a Makefile rule that allows for easy removal of multiple logging +directories. The rule can be called via 'make cleanlogs'. + +Signed-off-by: Leah Leshchinsky +Signed-off-by: John Kacur + +diff --git a/Makefile b/Makefile +index 2c72feaa398c..50ded3985743 100644 +--- a/Makefile ++++ b/Makefile +@@ -45,4 +45,8 @@ tags: + cleantags: + rm -f tags + ++.PHONY: cleanlogs ++cleanlogs: ++ rm -rf tuna-20* ++ + clean: pyclean rpmclean +-- +2.27.0 + diff --git a/tuna-Add-logging-infrastructure-to-tuna-cmd.patch b/tuna-Add-logging-infrastructure-to-tuna-cmd.patch new file mode 100644 index 0000000..e665919 --- /dev/null +++ b/tuna-Add-logging-infrastructure-to-tuna-cmd.patch @@ -0,0 +1,159 @@ +From 85330a8ab1afec5370676e7c3d753a4528f24e6f Mon Sep 17 00:00:00 2001 +From: Leah Leshchinsky +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 +Signed-off-by: John Kacur + +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 + diff --git a/tuna.spec b/tuna.spec index b53f202..efa2a51 100644 --- a/tuna.spec +++ b/tuna.spec @@ -1,6 +1,6 @@ Name: tuna Version: 0.17 -Release: 3%{?dist} +Release: 4%{?dist} License: GPLv2 Summary: Application tuning GUI & command line utility URL: https://git.kernel.org/pub/scm/utils/tuna/tuna.git @@ -18,6 +18,8 @@ Patch1: tuna-Fix-ModuleNotFoundError.patch Patch2: tuna-Fix-typo-for-variable-parm.patch Patch3: tuna-Handle-get_policy_and_rtprio-exceptions.patch Patch4: tuna-Remove-finally-block-in-get_policy_and_rtprio.patch +Patch5: tuna-Add-logging-infrastructure-to-tuna-cmd.patch +Patch6: tuna-Add-cleanlogs-rule-to-Makefile.patch %description Provides interface for changing scheduler and IRQ tunables, at whole CPU and at @@ -34,6 +36,8 @@ installed. %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 %build %py3_build @@ -75,6 +79,11 @@ done %{_datadir}/polkit-1/actions/org.tuna.policy %changelog +* Wed May 11 2022 Leah Leshchinsky - 0.17-4 +- Add logging infrastructure to tuna cmd +- Add cleanlogs rule to Makefile +Resolves: rhbz#2062881 + * Mon Apr 11 2022 Leah Leshchinsky - 0.17-3 - Fix typo for variable parm - Handle get_policy_and_rtprio exceptions