Skip to content

Commit f630498

Browse files
authored
Merge pull request #12 from SciCatProject/logging
Refactor logging configuration.
2 parents 9268e88 + 9aff18c commit f630498

7 files changed

+114
-15
lines changed

config.20240405.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
"config_file" : "config.json",
3232
"verbose" : false,
3333
"file_log" : false,
34-
"log_file_suffix" : ".scicat_ingestor_log",
34+
"log_filepath_prefix" : ".scicat_ingestor_log",
3535
"file_log_timestamp" : false,
3636
"log_level" : "INFO",
3737
"system_log" : false,
3838
"system_log_facility" : "mail",
39-
"log_prefix" : " SFI: ",
39+
"log_message_prefix" : " SFI: ",
4040
"check_by_job_id" : true,
4141
"pyscicat": null
4242
}

resources/config.sample.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
"config_file" : "config.json",
3232
"verbose" : false,
3333
"file_log" : false,
34-
"log_file_suffix" : ".scicat_ingestor_log",
34+
"log_filepath_prefix" : ".scicat_ingestor_log",
3535
"file_log_timestamp" : false,
3636
"log_level" : "INFO",
3737
"system_log" : false,
3838
"system_log_facility" : "mail",
39-
"log_prefix" : " SFI: ",
39+
"log_message_prefix" : " SFI: ",
4040
"check_by_job_id" : true,
4141
"pyscicat": null
4242
}

src/scicat_configuration.py

+21-8
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ def build_main_arg_parser() -> argparse.ArgumentParser:
3636
default=False,
3737
)
3838
group.add_argument(
39-
'--log-file-suffix',
40-
dest='log_file_suffix',
41-
help='Suffix of the log file name',
39+
'--log-filepath-prefix',
40+
dest='log_filepath_prefix',
41+
help='Prefix of the log file path',
4242
default='.scicat_ingestor_log',
4343
)
4444
group.add_argument(
@@ -62,8 +62,8 @@ def build_main_arg_parser() -> argparse.ArgumentParser:
6262
default='mail',
6363
)
6464
group.add_argument(
65-
'--log-prefix',
66-
dest='log_prefix',
65+
'--log-message-prefix',
66+
dest='log_message_prefix',
6767
help='Prefix for log messages',
6868
default=' SFI: ',
6969
)
@@ -92,13 +92,13 @@ class RunOptions:
9292
config_file: str
9393
verbose: bool
9494
file_log: bool
95-
log_file_suffix: str
95+
log_filepath_prefix: str
9696
file_log_timestamp: bool
9797
system_log: bool
98-
system_log_facility: str
99-
log_prefix: str
98+
log_message_prefix: str
10099
log_level: str
101100
check_by_job_id: bool
101+
system_log_facility: Optional[str] = None
102102
pyscicat: Optional[str] = None
103103

104104

@@ -109,6 +109,19 @@ class ScicatConfig:
109109
run_options: RunOptions
110110
"""Merged configuration dictionary with command line arguments."""
111111

112+
def to_dict(self) -> dict:
113+
"""Return the configuration as a dictionary."""
114+
from dataclasses import asdict
115+
116+
# Deep copy the original dictionary recursively
117+
original_dict = dict(self.original_dict)
118+
for key, value in original_dict.items():
119+
if isinstance(value, Mapping):
120+
original_dict[key] = dict(value)
121+
122+
copied = ScicatConfig(original_dict, self.run_options)
123+
return asdict(copied)
124+
112125

113126
def build_scicat_config(input_args: argparse.Namespace) -> ScicatConfig:
114127
"""Merge configuration from the configuration file and input arguments."""

src/scicat_ingestor.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
# SPDX-License-Identifier: BSD-3-Clause
22
# Copyright (c) 2024 ScicatProject contributors (https://github.com/ScicatProject)
33
from scicat_configuration import build_main_arg_parser, build_scicat_config
4+
from scicat_logging import build_logger
45

56

67
def main() -> None:
78
"""Main entry point of the app."""
89
arg_parser = build_main_arg_parser()
910
arg_namespace = arg_parser.parse_args()
1011
config = build_scicat_config(arg_namespace)
11-
print(config)
12+
logger = build_logger(config)
13+
14+
# Log the configuration as dictionary so that it is easier to read from the logs
15+
logger.info('Starting the Scicat Ingestor with the following configuration:')
16+
logger.info(config.to_dict())

src/scicat_logging.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
# Copyright (c) 2024 ScicatProject contributors (https://github.com/ScicatProject)
3+
import logging
4+
import logging.handlers
5+
from datetime import datetime
6+
7+
from scicat_configuration import ScicatConfig
8+
9+
10+
def build_logger(config: ScicatConfig) -> logging.Logger:
11+
"""Build a logger and configure it according to the ``config``."""
12+
run_options = config.run_options
13+
14+
# Build logger and formatter
15+
logger = logging.getLogger('esd extract parameters')
16+
formatter = logging.Formatter(
17+
run_options.log_message_prefix
18+
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
19+
)
20+
21+
# Add FileHandler
22+
if run_options.file_log:
23+
file_name_components = [run_options.log_filepath_prefix]
24+
if run_options.file_log_timestamp:
25+
file_name_components.append(datetime.now().strftime('%Y%m%d%H%M%S%f'))
26+
file_name_components.append('.log')
27+
28+
file_name = '_'.join(file_name_components)
29+
file_handler = logging.FileHandler(file_name, mode='w', encoding='utf-8')
30+
logger.addHandler(file_handler)
31+
32+
# Add SysLogHandler
33+
if run_options.system_log:
34+
logger.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
35+
36+
# Set the level and formatter for all handlers
37+
logger.setLevel(run_options.log_level)
38+
for handler in logger.handlers:
39+
handler.setLevel(run_options.log_level)
40+
handler.setFormatter(formatter)
41+
42+
# Add StreamHandler
43+
# streamer handler is added last since it is using different formatter
44+
if run_options.verbose:
45+
from rich.logging import RichHandler
46+
47+
logger.addHandler(RichHandler(level=run_options.log_level))
48+
49+
return logger

tests/test_logging.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import pathlib
2+
3+
import pytest
4+
5+
from scicat_configuration import RunOptions, ScicatConfig
6+
7+
8+
@pytest.fixture
9+
def scicat_config(tmp_path: pathlib.Path) -> ScicatConfig:
10+
return ScicatConfig(
11+
original_dict=dict(),
12+
run_options=RunOptions(
13+
config_file='test',
14+
verbose=True,
15+
file_log=True,
16+
log_filepath_prefix=(tmp_path / pathlib.Path('test')).as_posix(),
17+
file_log_timestamp=True,
18+
system_log=False,
19+
system_log_facility=None,
20+
log_message_prefix='test',
21+
log_level='DEBUG',
22+
check_by_job_id=True,
23+
pyscicat='test',
24+
),
25+
)
26+
27+
28+
def test_scicat_logging_build_logger(scicat_config: ScicatConfig) -> None:
29+
from scicat_logging import build_logger
30+
31+
logger = build_logger(scicat_config)
32+
assert len(logger.handlers) == 2 # FileHandler and StreamHandler

tox.ini

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ isolated_build = true
66
deps = -r requirements/test.txt
77
setenv =
88
JUPYTER_PLATFORM_DIRS = 1
9-
commands = pytest {posargs}
10-
scicat_ingestor --help # Minimal test of the script
9+
commands = scicat_ingestor --help # Minimal test of the script
10+
pytest {posargs}
1111

1212
[testenv:nightly]
1313
deps = -r requirements/nightly.txt

0 commit comments

Comments
 (0)