Skip to content

Commit f1ec799

Browse files
authored
Merge pull request #29 from SciCatProject/graylog_integration
Graylog integration
2 parents 251bd11 + 1c12e98 commit f1ec799

5 files changed

+144
-50
lines changed

resources/config.sample.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
"username": "USERNAME",
1818
"password": "PASSWORD"
1919
},
20+
"graylog": {
21+
"host" : "",
22+
"port" : "",
23+
"facility" : "scicat.ingestor"
24+
},
2025
"dataset": {
2126
"instrument_id" : "",
2227
"instrument" : "INSTRUMENT_NAME",
@@ -37,6 +42,7 @@
3742
"system_log_facility" : "mail",
3843
"log_message_prefix" : " SFI: ",
3944
"check_by_job_id" : true,
40-
"pyscicat": null
45+
"pyscicat": null,
46+
"graylog" : false
4147
}
4248
}
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"proposal_id" : {
3+
"field_type" : "high_level",
4+
"machine_name" : "proposalId",
5+
"source" : "NXS:/entry/experiment_identifier",
6+
"type" : "string"
7+
},
8+
"principal_investigator" : {
9+
"field_type" : "high_level",
10+
"machine_name" : "principalInvestigator",
11+
"source" : "UO:proposal:/proposer/firstname + UO:proposal:/proposer/lastname",
12+
"type" : "string"
13+
},
14+
"dataset_name" : {
15+
"field_type" : "high_level",
16+
"machine_name" : "datasetName",
17+
"source" : "NXS:/entry/title",
18+
"type" : "string"
19+
},
20+
"techniques" : {
21+
"field_type" : "high_level",
22+
"machine_name" : "techniques",
23+
"human_name" : "techniques",
24+
"value" : "",
25+
"type" : "object"
26+
},
27+
"start_time" : {
28+
"field_type" : "scientific_metadata",
29+
"machine_name" : "start_time",
30+
"human_name" : "Start Time",
31+
"source" : "WRDN:/metadata/start_time",
32+
"transformation" : "timestamp_to_iso8601",
33+
"type" : "date"
34+
}
35+
"end_time" : {
36+
"field_type" : "scientific_metadata",
37+
"machine_name" : "end_time",
38+
"human_name" : "End Time",
39+
"source" : "WRDN:/metadata/end_time",
40+
"transformation" : "timestamp_to_iso8601",
41+
"type" : "date"
42+
},
43+
"sample_id" : {
44+
"field_type" : "high_level",
45+
"machine_name" : "sampleId",
46+
"value" : "",
47+
"type" : "string"
48+
},
49+
"instrument_id" : {
50+
"field_type" : "high_level",
51+
"machine_name" : "instrumentId",
52+
"value" : "DREAM",
53+
"type" : "string"
54+
},
55+
]

src/scicat_configuration.py

+68-48
Original file line numberDiff line numberDiff line change
@@ -8,85 +8,99 @@
88
def build_main_arg_parser() -> argparse.ArgumentParser:
99
parser = argparse.ArgumentParser()
1010

11-
group = parser.add_argument_group('Scicat Ingestor Options')
11+
group = parser.add_argument_group("Scicat Ingestor Options")
1212

1313
group.add_argument(
14-
'-c',
15-
'--cf',
16-
'--config',
17-
'--config-file',
18-
default='config.20240405.json',
19-
dest='config_file',
20-
help='Configuration file name. Default: config.20240405.json',
14+
"-c",
15+
"--cf",
16+
"--config",
17+
"--config-file",
18+
default="config.20240405.json",
19+
dest="config_file",
20+
help="Configuration file name. Default: config.20240405.json",
2121
type=str,
2222
)
2323
group.add_argument(
24-
'-v',
25-
'--verbose',
26-
dest='verbose',
27-
help='Provide logging on stdout',
28-
action='store_true',
24+
"-v",
25+
"--verbose",
26+
dest="verbose",
27+
help="Provide logging on stdout",
28+
action="store_true",
2929
default=False,
3030
)
3131
group.add_argument(
32-
'--file-log',
33-
dest='file_log',
34-
help='Provide logging on file',
35-
action='store_true',
32+
"--file-log",
33+
dest="file_log",
34+
help="Provide logging on file",
35+
action="store_true",
3636
default=False,
3737
)
3838
group.add_argument(
39-
'--log-filepath-prefix',
40-
dest='log_filepath_prefix',
41-
help='Prefix of the log file path',
42-
default='.scicat_ingestor_log',
39+
"--log-filepath-prefix",
40+
dest="log_filepath_prefix",
41+
help="Prefix of the log file path",
42+
default=".scicat_ingestor_log",
4343
)
4444
group.add_argument(
45-
'--file-log-timestamp',
46-
dest='file_log_timestamp',
47-
help='Provide logging on the system log',
48-
action='store_true',
45+
"--file-log-timestamp",
46+
dest="file_log_timestamp",
47+
help="Provide logging on the system log",
48+
action="store_true",
4949
default=False,
5050
)
5151
group.add_argument(
52-
'--system-log',
53-
dest='system_log',
54-
help='Provide logging on the system log',
55-
action='store_true',
52+
"--system-log",
53+
dest="system_log",
54+
help="Provide logging on the system log",
55+
action="store_true",
5656
default=False,
5757
)
5858
group.add_argument(
59-
'--system-log-facility',
60-
dest='system_log_facility',
61-
help='Facility for system log',
62-
default='mail',
59+
"--system-log-facility",
60+
dest="system_log_facility",
61+
help="Facility for system log",
62+
default="mail",
6363
)
6464
group.add_argument(
65-
'--log-message-prefix',
66-
dest='log_message_prefix',
67-
help='Prefix for log messages',
68-
default=' SFI: ',
65+
"--log-message-prefix",
66+
dest="log_message_prefix",
67+
help="Prefix for log messages",
68+
default=" SFI: ",
6969
)
7070
group.add_argument(
71-
'--log-level', dest='log_level', help='Logging level', default='INFO', type=str
71+
"--log-level", dest="log_level", help="Logging level", default="INFO", type=str
7272
)
7373
group.add_argument(
74-
'--check-by-job-id',
75-
dest='check_by_job_id',
76-
help='Check the status of a job by job_id',
77-
action='store_true',
74+
"--check-by-job-id",
75+
dest="check_by_job_id",
76+
help="Check the status of a job by job_id",
77+
action="store_true",
7878
default=True,
7979
)
8080
group.add_argument(
81-
'--pyscicat',
82-
dest='pyscicat',
83-
help='Location where a specific version of pyscicat is available',
81+
"--pyscicat",
82+
dest="pyscicat",
83+
help="Location where a specific version of pyscicat is available",
8484
default=None,
8585
type=str,
8686
)
87+
group.add_argument(
88+
"--graylog",
89+
dest="graylog",
90+
help="Use graylog for additional logs",
91+
action="store_true",
92+
default=False,
93+
)
8794
return parser
8895

8996

97+
@dataclass
98+
class GraylogOptions:
99+
host: str = ""
100+
port: str = ""
101+
facility: str = "scicat.ingestor"
102+
103+
90104
@dataclass
91105
class RunOptions:
92106
"""RunOptions dataclass to store the configuration options.
@@ -107,6 +121,7 @@ class RunOptions:
107121
check_by_job_id: bool
108122
system_log_facility: Optional[str] = None
109123
pyscicat: Optional[str] = None
124+
graylog: bool = False
110125

111126

112127
@dataclass
@@ -139,6 +154,8 @@ class ScicatConfig:
139154
"""Merged configuration dictionary with command line arguments."""
140155
kafka_options: kafkaOptions
141156
"""Kafka configuration options read from files."""
157+
graylog_options: GraylogOptions
158+
"""Graylog configuration options for streaming logs."""
142159

143160
def to_dict(self) -> dict:
144161
"""Return the configuration as a dictionary."""
@@ -150,7 +167,9 @@ def to_dict(self) -> dict:
150167
if isinstance(value, Mapping):
151168
original_dict[key] = dict(value)
152169

153-
copied = ScicatConfig(original_dict, self.run_options, self.kafka_options)
170+
copied = ScicatConfig(
171+
original_dict, self.run_options, self.kafka_options, self.graylog_options
172+
)
154173
return asdict(copied)
155174

156175

@@ -171,7 +190,7 @@ def build_scicat_config(input_args: argparse.Namespace) -> ScicatConfig:
171190
config_dict = dict()
172191

173192
# Overwrite deep-copied options with command line arguments
174-
run_option_dict: dict = copy.deepcopy(config_dict.setdefault('options', dict()))
193+
run_option_dict: dict = copy.deepcopy(config_dict.setdefault("options", dict()))
175194
for arg_name, arg_value in vars(input_args).items():
176195
if arg_value is not None:
177196
run_option_dict[arg_name] = arg_value
@@ -184,5 +203,6 @@ def build_scicat_config(input_args: argparse.Namespace) -> ScicatConfig:
184203
return ScicatConfig(
185204
original_dict=MappingProxyType(config_dict),
186205
run_options=RunOptions(**run_option_dict),
187-
kafka_options=kafkaOptions(**config_dict.setdefault('kafka', dict())),
206+
kafka_options=kafkaOptions(**config_dict.setdefault("kafka", dict())),
207+
graylog_options=GraylogOptions(**config_dict.setdefault("graylog", dict())),
188208
)

src/scicat_logging.py

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import logging.handlers
55
from datetime import datetime
66

7+
import graypy
8+
79
from scicat_configuration import ScicatConfig
810

911

@@ -33,6 +35,16 @@ def build_logger(config: ScicatConfig) -> logging.Logger:
3335
if run_options.system_log:
3436
logger.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
3537

38+
# Add graylog handler
39+
if run_options.graylog:
40+
graylog_config = config.graylog_options
41+
graylog_handler = graypy.GELFTCPHandler(
42+
graylog_config.host,
43+
int(graylog_config.port),
44+
facility=graylog_config.facility,
45+
)
46+
logger.addHandler(graylog_handler)
47+
3648
# Set the level and formatter for all handlers
3749
logger.setLevel(run_options.log_level)
3850
for handler in logger.handlers:

tests/test_logging.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from scicat_configuration import RunOptions, ScicatConfig, kafkaOptions
5+
from scicat_configuration import GraylogOptions, RunOptions, ScicatConfig, kafkaOptions
66

77

88
@pytest.fixture
@@ -23,6 +23,7 @@ def scicat_config(tmp_path: pathlib.Path) -> ScicatConfig:
2323
pyscicat='test',
2424
),
2525
kafka_options=kafkaOptions(),
26+
graylog_options=GraylogOptions(),
2627
)
2728

2829

0 commit comments

Comments
 (0)