Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: don't create logging handler multiple times (DEV-2891) #609

Merged
merged 17 commits into from
Oct 30, 2023
41 changes: 23 additions & 18 deletions src/dsp_tools/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ def _make_parser(
parser_upload_files.add_argument("-p", "--password", default=root_user_pw, help=password_text)

# fast-xmlupload
parser_fast_xmlupload_files = subparsers.add_parser(
parser_fast_xmlupload = subparsers.add_parser(
name="fast-xmlupload",
help="For internal use only: create resources with already uploaded files",
)
parser_fast_xmlupload_files.set_defaults(action="fast-xmlupload")
parser_fast_xmlupload_files.add_argument("-s", "--server", default=default_dsp_api_url, help=dsp_server_text)
parser_fast_xmlupload_files.add_argument("-u", "--user", default=root_user_email, help=username_text)
parser_fast_xmlupload_files.add_argument("-p", "--password", default=root_user_pw, help=password_text)
parser_fast_xmlupload_files.add_argument("xml_file", help="path to XML file containing the data")
parser_fast_xmlupload.set_defaults(action="fast-xmlupload")
parser_fast_xmlupload.add_argument("-s", "--server", default=default_dsp_api_url, help=dsp_server_text)
parser_fast_xmlupload.add_argument("-u", "--user", default=root_user_email, help=username_text)
parser_fast_xmlupload.add_argument("-p", "--password", default=root_user_pw, help=password_text)
parser_fast_xmlupload.add_argument("xml_file", help="path to XML file containing the data")

# excel2json
parser_excel2json = subparsers.add_parser(
Expand Down Expand Up @@ -296,24 +296,29 @@ def _log_cli_arguments(parsed_args: argparse.Namespace) -> None:
Args:
parsed_args: parsed arguments
"""
msg = f"*** Called the DSP-TOOLS action '{parsed_args.action}' from the command line with these parameters:"
metadata_lines = []
_version = version("dsp-tools")
metadata_lines.append(f"DSP-TOOLS {_version}: Called the action '{parsed_args.action}' from the command line")
metadata_lines.append(f"Location of this installation: {__file__}")
metadata_lines.append("CLI arguments:")
metadata_lines = [f"*** {line}" for line in metadata_lines]

parameter_lines = list()
parameters_to_log = {key: value for key, value in vars(parsed_args).items() if key != "action"}
longest_key_length = max(len(key) for key in parameters_to_log) if parameters_to_log else 0
lines = list()
for key, value in parameters_to_log.items():
if key == "password":
lines.append(f"*** {key:<{longest_key_length}} = {'*' * len(value)}")
parameter_lines.append(f"{key:<{longest_key_length}} = {'*' * len(value)}")
else:
lines.append(f"*** {key:<{longest_key_length}} = {value}")
if not lines:
lines.append("*** (no parameters)")
asterisk_count = max(
len(msg),
max(len(line) for line in lines),
)
parameter_lines.append(f"{key:<{longest_key_length}} = {value}")
parameter_lines = parameter_lines or ["(no parameters)"]
parameter_lines = [f"*** {line}" for line in parameter_lines]

asterisk_count = max(len(line) for line in metadata_lines + parameter_lines)
logger.info("*" * asterisk_count)
logger.info(msg)
for line in lines:
for line in metadata_lines:
logger.info(line)
for line in parameter_lines:
logger.info(line)
logger.info("*" * asterisk_count)

Expand Down
2 changes: 1 addition & 1 deletion src/dsp_tools/fast_xmlupload/process_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from dsp_tools.utils.create_logger import get_logger
from dsp_tools.utils.shared import http_call_with_retry, make_chunks

logger = get_logger(__name__, filesize_mb=100, backupcount=36)
logger = get_logger(__name__)
sipi_container: Optional[Container] = None
export_moving_image_frames_script: Optional[Path] = None

Expand Down
72 changes: 48 additions & 24 deletions src/dsp_tools/utils/create_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,34 @@
import logging.handlers
from pathlib import Path

# the handler must live on module level, so that it is created only once
_rotating_file_handler: logging.handlers.RotatingFileHandler | None = None

def get_logger(
name: str,
level: int = logging.INFO,
filesize_mb: int = 5,
backupcount: int = 4,
) -> logging.Logger:

def _make_handler(
logfile_directory: Path,
filesize_mb: int,
backupcount: int,
) -> logging.handlers.RotatingFileHandler:
"""
Create a logger instance,
set its level to INFO,
and configure it to write to a file in the user's home directory.
Create a rotating file handler.
A RotatingFileHandler fills "filename" until it is "maxBytes" big,
then appends ".1" to it and starts with a new file "filename",
fills it until it is "maxBytes" big,
then appends ".1" to it (replacing the old ".1" file)

Args:
name: name of the logger
level: logging level, defaults to logging.INFO
filesize_mb: maximum size per log file in MB, defaults to 5
backupcount: number of log files to keep, defaults to 4
logfile_directory: directory to store the logfiles in
filesize_mb: maximum size of a logfile in MB
backupcount: number of logfiles to keep

Returns:
the logger instance
handler instance
"""
_logger = logging.getLogger(name)
_logger.setLevel(level)
formatter = logging.Formatter(fmt="{asctime} {filename: <20} {levelname: <8} {message}", style="{")
formatter = logging.Formatter(fmt="{asctime} {filename: <30} {levelname: <8} {message}", style="{")
formatter.default_time_format = "%Y-%m-%d %H:%M:%S"
formatter.default_msec_format = "%s.%03d"
# a RotatingFileHandler fills "filename" until it is "maxBytes" big,
# then appends ".1" to it and starts with a new file "filename",
# fills it until it is "maxBytes" big,
# then appends ".1" to it (replacing the old ".1" file)
logfile_directory = Path.home() / Path(".dsp-tools")

logfile_directory.mkdir(exist_ok=True)
handler = logging.handlers.RotatingFileHandler(
filename=logfile_directory / "logging.log",
Expand All @@ -41,5 +38,32 @@ def get_logger(
backupCount=backupcount,
)
handler.setFormatter(formatter)
_logger.addHandler(handler)
return _logger
return handler


def get_logger(
name: str,
level: int = logging.DEBUG,
) -> logging.Logger:
"""
Create a logger instance,
and configure it to write to a file in the user's home directory.

Args:
name: name of the logger
level: logging level, defaults to logging.DEBUG

Returns:
the logger instance
"""
global _rotating_file_handler
if not _rotating_file_handler:
_rotating_file_handler = _make_handler(
Path.home() / Path(".dsp-tools"),
filesize_mb=100,
backupcount=30,
)
logger = logging.getLogger(name)
logger.setLevel(level)
logger.addHandler(_rotating_file_handler)
return logger