Skip to content
Snippets Groups Projects
Commit 0f0c8dd3 authored by Ashwin Kumar Karnad's avatar Ashwin Kumar Karnad
Browse files

Merge branch 'introduce-logging-module' into 'main'

Introduce logging module

See merge request mpsd-cs/mpsd-software-environments!22
parents 631f8d01 4478fd02
No related branches found
No related tags found
1 merge request!22Introduce logging module
Pipeline #368898 passed
......@@ -4,6 +4,7 @@
import argparse
import datetime
import logging
import os
import subprocess
import sys
......@@ -11,6 +12,7 @@ import time
from pathlib import Path
from typing import List, Tuple
about_tool = """
Build toolchains using Spack.\n
......@@ -30,6 +32,47 @@ config_vars = {
}
def set_up_logging(loglevel="warning", filename=None):
"""Set up logging.
This function sets up the logging configuration for the script.
It configures the log level, log format, and log handlers
for both file and console output.
Parameters
----------
loglevel : str or int
Loglevels are:
- warning (default): only print statements if something is unexpected
- info (show more detailed progress)
- debug (show very detailed output)
filename : str
- filename to save logging messages into
If loglevel is 'debug', save line numbers in log messages.
"""
log_level_numeric = getattr(logging, loglevel.upper(), logging.WARNING)
assert log_level_numeric
if not isinstance(log_level_numeric, int):
raise ValueError("Invalid log level: %s" % loglevel)
handlers = []
if filename:
handlers.append(logging.FileHandler(filename))
handlers.append(logging.StreamHandler())
linenumbers = " %(lineno)4d" if log_level_numeric == logging.DEBUG else ""
logging.basicConfig(
format="%(asctime)s %(levelname)7s" + linenumbers + " | %(message)s",
datefmt="[%X]",
level=log_level_numeric,
handlers=handlers,
force=True,
)
logging.debug(f"Logging has been setup, loglevel={loglevel.upper()} {filename=}")
# Helper class to change directory via context manager
class os_chdir:
"""The os_chdir class is a context manager.
......@@ -123,16 +166,16 @@ def run(*args, counter=[0], **kwargs):
options = ", ".join([f"{key}={value}" for key, value in kwargs.items()])
# provide information about upcoming subprocess.run call
print(f"{token} Starting subprocess.run({arg}) with options {options}")
print(f"{token} getcwd={os.getcwd()}")
print(f"{token} COMMAND={command}")
logging.info(f"{token} Starting subprocess.run('{command}') with options {options}")
logging.debug(f"{token} getcwd={os.getcwd()}")
logging.debug(f"{token} exact call: subprocess.run({arg})")
time_start = time.time()
process = subprocess.run(*args, **kwargs)
execution_time = time.time() - time_start
print(f"{token} Completed in {execution_time:.4f}s.")
print(f"{token}") # near-empty line to make reading logs easier
logging.debug(f"{token} Completed in {execution_time:.4f}s.")
logging.debug(f"{token}") # near-empty line to make reading logs easier
return process
......@@ -395,7 +438,7 @@ def install_environment(
-------
None
"""
print(
logging.info(
f"Installing release {mpsd_release} with toolchains {toolchains} "
f"to {script_dir}"
)
......@@ -419,7 +462,7 @@ def install_environment(
elif toolchains == "NONE":
# No toolchains requested, so we only create the env and print the
# list of available toolchains
print(
logging.warning(
"No toolchains requested. Available toolchains for release "
f"{mpsd_release} are: \n {available_toolchains}"
)
......@@ -442,7 +485,7 @@ def install_environment(
# and replace _toolchains_ with the toolchain name and
# _mpsd_spack_ver_ with mpsd_release
print(f"Installing toolchain {toolchain} to {toolchain_dir}")
logging.info(f"Installing toolchain {toolchain} to {toolchain_dir}")
install_log_file = (
config_vars["build_log_file"]
.replace("mpsd_spack_ver_", f"{mpsd_release}_")
......@@ -473,20 +516,30 @@ def install_environment(
def remove_environment(release, toolchains, target_dir):
"""Remove release from installation."""
msg = f"Removing release {release} with toolchains {toolchains} from {target_dir}"
print(msg)
logging.info(msg)
raise NotImplementedError(msg)
def start_new_environment(release, from_release, target_dir):
"""Start new MPSD software environment version."""
msg = f"Starting new release {release} from {from_release} to {target_dir}"
print(msg)
logging.info(msg)
raise NotImplementedError(msg)
def main():
"""Execute main entry point."""
parser = argparse.ArgumentParser(description=about_tool)
parser.add_argument(
"--log",
"-l",
dest="loglevel",
choices=["warning", "info", "debug"],
required=False,
default="warning",
help="Set the log level",
)
subparsers = parser.add_subparsers(
dest="action", title="actions", description="valid actions", required=True
)
......@@ -555,6 +608,9 @@ def main():
# Carry out the action
args = parser.parse_args()
# parse logging first
set_up_logging(args.loglevel)
# target dir is the place where this script exists. the
# release `dev` in script_dir/dev-23a
script_dir = Path(os.path.dirname(os.path.realpath(__file__)))
......
"""Tests for mpsd-software-environment.py."""
import importlib
import logging
import os
import shutil
import subprocess
......@@ -10,6 +11,11 @@ import pytest
mod = importlib.import_module("mpsd-software-environment")
# set loglevel to debug - useful for understanding problems.
# (if the tests pass, pytest doesn't show any output)
mod.set_up_logging(loglevel="debug", filename="tests.log")
logging.debug(f"We have set up logging from {__file__}")
def create_mock_git_repository(target_directory, create_directory=True):
"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment