Belle II Software development
basf2.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9/*
10 * There are two ways to work with the framework. Either
11 * by executing "basf2" and providing a python steering
12 * file as an argument or by using the framework within
13 * python itself.
14 *
15 * This file implements the main executable "basf2".
16 */
17
18#include <Python.h> //Has to be the first include (restriction due to python)
19
20#include <framework/core/Environment.h>
21#include <framework/core/DataFlowVisualization.h>
22#include <framework/core/MetadataService.h>
23#include <framework/core/RandomNumbers.h>
24#include <framework/logging/Logger.h>
25#include <framework/logging/LogConfig.h>
26#include <framework/logging/LogSystem.h>
27#include <framework/utilities/FileSystem.h>
28
29
30#include <boost/program_options.hpp>
31#include <boost/algorithm/string/predicate.hpp> //for iequals()
32
33#include <csignal>
34#include <cstdlib>
35#include <iostream>
36#include <string>
37#include <vector>
38#include <fstream>
39#include <locale>
40#include <codecvt>
41#include <filesystem>
42
43#ifdef HAS_CALLGRIND
44#include <valgrind/valgrind.h>
45#endif
46
47using namespace std;
48using namespace Belle2;
49
50namespace prog = boost::program_options;
51
52namespace {
53
54 void checkPythonStatus(PyConfig& config, PyStatus& status)
55 {
56 if (PyStatus_Exception(status)) {
57 PyConfig_Clear(&config);
58 Py_ExitStatusException(status);
59 }
60 }
61}
62
63int main(int argc, char* argv[])
64{
65 //remove SIGPIPE handler set by ROOT which sometimes caused infinite loops
66 //See https://savannah.cern.ch/bugs/?97991
67 //default action is to abort
68 if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
69 B2FATAL("Cannot remove SIGPIPE signal handler");
70 }
71
72 //Initialize metadata service
74
75 //Check for Belle2 environment variables (during environment initialisation)
77
78 //Get the lib path (checked for NULL in Environment)
79 const char* belle2SubDir = getenv("BELLE2_SUBDIR");
80 std::filesystem::path libPath = "lib";
81 libPath /= belle2SubDir;
82
83 string runModuleIOVisualization(""); //nothing done if empty
84 vector<string> arguments;
85 string pythonFile;
86
87 try {
88 //---------------------------------------------------
89 // Handle command line options
90 //---------------------------------------------------
91
92 prog::options_description generic("Generic options (to be used instead of steering file)");
93 generic.add_options()
94 ("help,h", "Print this help")
95 ("version,v", "Print long and verbose version string")
96 ("version-short", "Print short version string")
97 ("info", "Print information about basf2")
98 ("license", "Print the short version of the basf2 license")
99 ("modules,m", prog::value<string>()->implicit_value(""),
100 "Print a list of all available modules (can be limited to a given package), or give detailed information on a specific module given as an argument (case sensitive).")
101 ;
102
103 prog::options_description config("Configuration");
104 config.add_options()
105 ("steering", prog::value<string>(), "The python steering file to run.")
106 ("arg", prog::value<vector<string> >(&arguments), "Additional arguments to be passed to the steering file")
107 ("log_level,l", prog::value<string>(),
108 "Set global log level (one of DEBUG, INFO, RESULT, WARNING, or ERROR). Takes precedence over set_log_level() in steering file.")
109 ("package_log_level", prog::value<vector<string> >(),
110 "Set package log level. Can be specified multiple times to use more than one package. (Examples: 'klm:INFO or cdc:DEBUG:10') ")
111 ("module_log_level", prog::value<vector<string> >(),
112 "Set module log level. Can be specified multiple times to use more than one package. (Examples: 'EventInfoSetter:INFO or CDCDigitizer:DEBUG:10') ")
113 ("random-seed", prog::value<string>(),
114 "Set the default initial seed for the random number generator. "
115 "This does not take precedence over calls to set_random_seed() in the steering file, but just changes the default. "
116 "If no seed is set via either of these mechanisms, the initial seed will be taken from the system's entropy pool.")
117 ("debug_level,d", prog::value<unsigned int>(), "Set default debug level. Also sets the log level to DEBUG.")
118 ("events,n", prog::value<unsigned int>(), "Override number of events for EventInfoSetter; otherwise set maximum number of events.")
119 ("run", prog::value<int>(), "Override run for EventInfoSetter, must be used with -n and --experiment")
120 ("experiment", prog::value<int>(), "Override experiment for EventInfoSetter, must be used with -n and --run")
121 ("skip-events", prog::value<unsigned int>(),
122 "Override skipNEvents for EventInfoSetter and RootInput. Skips this many events before starting.")
123 ("input,i", prog::value<vector<string> >(),
124 "Override name of input file for (Seq)RootInput. Can be specified multiple times to use more than one file. For RootInput, wildcards (as in *.root or [1-3].root) can be used, but need to be escaped with \\ or by quoting the argument to avoid expansion by the shell.")
125 ("sequence,S", prog::value<vector<string> >(),
126 "Override the number sequence (e.g. 23:42,101) defining the entries (starting from 0) which are processed by RootInput."
127 "Must be specified exactly once for each file to be opened."
128 "This means one sequence per input file AFTER wildcard expansion."
129 "The first event has the number 0.")
130 ("output,o", prog::value<string>(),
131 "Override name of output file for (Seq)RootOutput. In case multiple modules are present in the path, only the first will be affected.")
132 ("processes,p", prog::value<int>(), "Override number of worker processes (>=1 enables, 0 disables parallel processing)");
133
134 prog::options_description advanced("Advanced Options");
135 advanced.add_options()
136 ("module-io", prog::value<string>(),
137 "Create diagram of inputs and outputs for a single module, saved as ModuleName.dot. To create a PostScript file, use e.g. 'dot ModuleName.dot -Tps -o out.ps'.")
138 ("visualize-dataflow", "Generate data flow diagram (dataflow.dot) for the executed steering file.")
139 ("no-stats",
140 "Disable collection of statistics during event processing. Useful for very high-rate applications, but produces empty table with 'print(statistics)'.")
141 ("dry-run",
142 "Read steering file, but do not start any event processing when process(path) is called. Prints information on input/output files that would be used during normal execution.")
143 ("dump-path", prog::value<string>(),
144 "Read steering file, but do not actually start any event processing. The module path the steering file would execute is instead pickled (serialized) into the given file.")
145 ("execute-path", prog::value<string>(),
146 "Do not read any provided steering file, instead execute the pickled (serialized) path from the given file.")
147 ("zmq",
148 "Use ZMQ for multiprocessing instead of a RingBuffer. This has many implications and should only be used by experts.")
149 ("job-information", prog::value<string>(),
150 "Create json file with metadata of output files and basf2 execution status.")
151 ("realm", prog::value<string>(),
152 "Set the realm of the basf2 execution (online or production).")
153 ("secondary-input", prog::value<vector<string>>(),
154 "Override name of input file for the secondary RootInput module used for the event embedding. Can be specified multiple times to use more than one file. Wildcards (as in *.root or [1-3].root) can be used, but need to be escaped with \\ or by quoting the argument to avoid expansion by the shell.")
155#ifdef HAS_CALLGRIND
156 ("profile", prog::value<string>(),
157 "Name of a module to profile using callgrind. If more than one module of that name is registered only the first one will be profiled.")
158#endif
159 ;
160
161 prog::options_description cmdlineOptions;
162 cmdlineOptions.add(generic).add(config).add(advanced);
163
164 prog::positional_options_description posOptDesc;
165 posOptDesc.add("steering", 1);
166 posOptDesc.add("arg", -1);
167
168 prog::variables_map varMap;
169 prog::store(prog::command_line_parser(argc, argv).
170 options(cmdlineOptions).positional(posOptDesc).run(), varMap);
171 prog::notify(varMap);
172
173 //Check for non-steering file options
174 if (varMap.count("help")) {
175 cout << "Usage: " << argv[0] << " [OPTIONS] [STEERING_FILE] [-- [STEERING_FILE_OPTIONS]]\n";
176 cout << cmdlineOptions << endl;
177 return 0;
178 } else if (varMap.count("version")) {
179 pythonFile = "basf2/version.py";
180 } else if (varMap.count("version-short")) {
181 pythonFile = "basf2/version_short.py";
182 } else if (varMap.count("info")) {
183 pythonFile = "basf2_cli/print_info.py";
184 } else if (varMap.count("license")) {
185 pythonFile = "basf2_cli/print_license.py";
186 } else if (varMap.count("modules")) {
187 string modArgs = varMap["modules"].as<string>();
188 if (!modArgs.empty()) {
189 arguments.insert(arguments.begin(), modArgs);
190 }
191 // recent boost program_options will not consume extra tokens for
192 // implicit options. In this case the module/package name gets consumed
193 // in the steering file so we just use that.
194 if (varMap.count("steering")) {
195 arguments.insert(arguments.begin(), varMap["steering"].as<string>());
196 }
197 pythonFile = "basf2_cli/modules.py";
198 } else if (varMap.count("module-io")) {
199 runModuleIOVisualization = varMap["module-io"].as<string>();
200 pythonFile = "basf2/core.py"; //make module maps available, visualization will happen later
201 } else if (varMap.count("execute-path")) {
202 Environment::Instance().setPicklePath(varMap["execute-path"].as<string>());
203 pythonFile = "basf2_cli/execute_pickled_path.py";
204 } else if (varMap.count("steering")) {
205 // steering file not misused as module name, so print it's name :D
206 pythonFile = varMap["steering"].as<string>();
207 } else {
208 // launch an interactive python session.
209 pythonFile = "interactive.py";
210 }
211
212 if (!pythonFile.empty()) {
213 //Search in local or central lib/ if this isn't a direct path
214 if (!std::filesystem::exists(pythonFile)) {
215 std::string libFile = FileSystem::findFile((libPath / pythonFile).string(), true);
216 if (!libFile.empty())
217 pythonFile = libFile;
218 }
219 if (varMap.count("steering") and not varMap.count("modules")) {
220 B2INFO("Steering file: " << pythonFile);
221 }
222 }
223
224 // -p
225 // Do now so that we can override if profiling is requested
226 if (varMap.count("processes")) {
227 int nprocesses = varMap["processes"].as<int>();
228 if (nprocesses < 0) {
229 B2FATAL("Invalid number of processes!");
230 }
232 }
233
234 // --zmq
235 if (varMap.count("zmq")) {
237 }
238
239
240#ifdef HAS_CALLGRIND
241 if (varMap.count("profile")) {
242 string profileModule = varMap["profile"].as<string>();
243 //We want to profile a module so check if we are running under valgrind
244 if (!RUNNING_ON_VALGRIND) {
245 //Apparently not. Ok, let's call ourself using valgrind
246 cout << "Profiling requested, restarting using callgrind" << endl;
247
248 //Sadly calling processes in C++ is very annoying as we have to
249 //build a command line.
250 vector<char*> cmd;
251 //First we add all valgrind arguments.
252 const vector<string> valgrind_argv {
253 "valgrind", "--tool=callgrind", "--instr-atstart=no", "--trace-children=no",
254 "--callgrind-out-file=callgrind." + profileModule + ".%p",
255 };
256 //As execvp wants non-const char* pointers we have to copy the string contents.
257 cmd.reserve(valgrind_argv.size());
258 for (const auto& arg : valgrind_argv) { cmd.push_back(strdup(arg.c_str())); }
259 //And now we add our own arguments, including the program name.
260 for (int i = 0; i < argc; ++i) { cmd.push_back(argv[i]); }
261 //Finally, execvp wants a nullptr as last argument
262 cmd.push_back(nullptr);
263 //And call this thing. Execvp will not return if successful as the
264 //current process will be replaced so we do not need to care about what
265 //happens if successful
266 if (execvp(cmd[0], cmd.data()) == -1) {
267 int errsv = errno;
268 perror("Problem calling valgrind");
269 return errsv;
270 }
271 }
272 //Ok, running under valgrind, set module name we want to profile in
273 //environment.
275 //and make sure there is no multiprocessing when profiling
277 }
278#endif
279
280 // -n
281 if (varMap.count("events")) {
282 unsigned int nevents = varMap["events"].as<unsigned int>();
283 if (nevents == 0 or nevents == std::numeric_limits<unsigned int>::max()) {
284 B2FATAL("Invalid number of events (valid range: 1.." << std::numeric_limits<unsigned int>::max() - 1 << ")!");
285 }
287 }
288 // --run & --experiment
289 if (varMap.count("experiment") or varMap.count("run")) {
290 if (!varMap.count("events"))
291 B2FATAL("--experiment and --run must be used with --events/-n!");
292 if (!(varMap.count("run") and varMap.count("experiment")))
293 B2FATAL("Both --experiment and --run must be specified!");
294
295 int run = varMap["run"].as<int>();
296 int experiment = varMap["experiment"].as<int>();
297 B2ASSERT("run must be >= 0!", run >= 0);
298 B2ASSERT("experiment must be >= 0!", experiment >= 0);
300 }
301
302 // --skip-events
303 if (varMap.count("skip-events")) {
304 unsigned int skipevents = varMap["skip-events"].as<unsigned int>();
306 }
307
308 // -i
309 if (varMap.count("input")) {
310 const auto& names = varMap["input"].as<vector<string>>();
312 }
313
314 // -S
315 if (varMap.count("sequence")) {
316 const auto& sequences = varMap["sequence"].as<vector<string>>();
318 }
319
320 // -o
321 if (varMap.count("output")) {
322 std::string name = varMap["output"].as<string>();
324 }
325
326 // -l
327 if (varMap.count("log_level")) {
328 std::string levelParam = varMap["log_level"].as<string>();
329 int level = -1;
330 for (int i = LogConfig::c_Debug; i < LogConfig::c_Fatal; i++) {
331 std::string thisLevel = LogConfig::logLevelToString((LogConfig::ELogLevel)i);
332 if (boost::iequals(levelParam, thisLevel)) { //case-insensitive
333 level = i;
334 break;
335 }
336 }
337 if (level < 0) {
338 B2FATAL("Invalid log level! Needs to be one of DEBUG, INFO, RESULT, WARNING, or ERROR.");
339 }
340
341 //set log level
343 //and make sure it takes precedence over anything in the steering file
345 }
346
347 // --package_log_level
348 if (varMap.count("package_log_level")) {
349 const auto& packLogList = varMap["package_log_level"].as<vector<string>>();
350 const std::string delimiter = ":";
351 for (const std::string& packLog : packLogList) {
352 if (packLog.find(delimiter) == std::string::npos) {
353 B2FATAL("In --package_log_level input " << packLog << ", no colon detected. ");
354 break;
355 }
356 /* string parsing for packageName:LOGLEVEL or packageName:DEBUG:LEVEL*/
357 auto packageName = packLog.substr(0, packLog.find(delimiter));
358 std::string logName = packLog.substr(packLog.find(delimiter) + delimiter.length(), packLog.length());
359 int debugLevel = -1;
360 if ((logName.find("DEBUG") != std::string::npos) && logName.length() > 5) {
361 try {
362 debugLevel = std::stoi(logName.substr(logName.find(delimiter) + delimiter.length(), logName.length()));
363 } catch (std::exception& e) {
364 B2WARNING("In --package_log_level, issue parsing debugLevel. Still setting log level to DEBUG.");
365 }
366 logName = "DEBUG";
367 }
368
369 int level = -1;
370 /* determine log level for package */
371 for (int i = LogConfig::c_Debug; i < LogConfig::c_Fatal; i++) {
372 std::string thisLevel = LogConfig::logLevelToString((LogConfig::ELogLevel)i);
373 if (boost::iequals(logName, thisLevel)) { //case-insensitive
374 level = i;
375 break;
376 }
377 }
378 if (level < 0) {
379 B2FATAL("Invalid log level! Needs to be one of DEBUG, INFO, RESULT, WARNING, or ERROR.");
380 }
381 /* set package log level*/
382 if ((logName == "DEBUG") && (debugLevel >= 0)) {
383 LogSystem::Instance().getPackageLogConfig(packageName).setDebugLevel(debugLevel);
384 }
386
387 }
388 }
389
390 // --module_log_level
391 if (varMap.count("module_log_level")) {
392 const auto& moduleLogList = varMap["module_log_level"].as<vector<string>>();
393 const std::string delimiter = ":";
394 for (const std::string& moduleLog : moduleLogList) {
395 if (moduleLog.find(delimiter) == std::string::npos) {
396 B2FATAL("In --module_log_level input " << moduleLog << ", no colon detected. ");
397 break;
398 }
399 /* string parsing for packageName:LOGLEVEL or packageName:DEBUG:LEVEL*/
400 auto moduleName = moduleLog.substr(0, moduleLog.find(delimiter));
401 std::string moduleLogName = moduleLog.substr(moduleLog.find(delimiter) + delimiter.length(), moduleLog.length());
402 int moduleDebugLevel = -1;
403 if ((moduleLogName.find("DEBUG") != std::string::npos) && moduleLogName.length() > 5) {
404 try {
405 moduleDebugLevel = std::stoi(moduleLogName.substr(moduleLogName.find(delimiter) + delimiter.length(), moduleLogName.length()));
406 } catch (std::exception& e) {
407 B2WARNING("In --module_log_level, issue parsing debugLevel. Still setting log level to DEBUG.");
408 }
409 moduleLogName = "DEBUG";
410 }
411
412 int module_level = -1;
413 /* determine log level for module */
414 for (int i = LogConfig::c_Debug; i < LogConfig::c_Fatal; i++) {
415 std::string moduleThisLevel = LogConfig::logLevelToString((LogConfig::ELogLevel)i);
416 if (boost::iequals(moduleLogName, moduleThisLevel)) { //case-insensitive
417 module_level = i;
418 break;
419 }
420 }
421 if (module_level < 0) {
422 B2FATAL("Invalid log level! Needs to be one of DEBUG, INFO, RESULT, WARNING, or ERROR.");
423 }
424 /* set package log level*/
425 if ((moduleLogName == "DEBUG") && (moduleDebugLevel >= 0)) {
426 LogSystem::Instance().getModuleLogConfig(moduleName).setDebugLevel(moduleDebugLevel);
427 }
429
430 }
431 }
432
433 // -d
434 if (varMap.count("debug_level")) {
435 unsigned int level = varMap["debug_level"].as<unsigned int>();
438 }
439
440 if (varMap.count("visualize-dataflow")) {
442 if (Environment::Instance().getNumberProcesses() > 0) {
443 B2WARNING("--visualize-dataflow cannot be used with parallel processing, no graphs will be saved!");
444 }
445 }
446
447 if (varMap.count("no-stats")) {
449 }
450
451 if (varMap.count("dry-run")) {
453 }
454
455 if (varMap.count("dump-path")) {
456 Environment::Instance().setPicklePath(varMap["dump-path"].as<string>());
457 }
458
459 if (varMap.count("random-seed")) {
460 RandomNumbers::initialize(varMap["random-seed"].as<string>());
461 }
462
463 if (varMap.count("job-information")) {
464 string jobInfoFile = varMap["job-information"].as<string>();
466 B2INFO("Job information file: " << jobInfoFile);
467 }
468
469 if (varMap.count("realm")) {
470 std::string realmParam = varMap["realm"].as<string>();
471 int realm = -1;
472 for (int i = LogConfig::c_Online; i <= LogConfig::c_Production; i++) {
473 std::string thisRealm = LogConfig::logRealmToString((LogConfig::ELogRealm)i);
474 if (boost::iequals(realmParam, thisRealm)) { //case-insensitive
475 realm = i;
476 break;
477 }
478 }
479 if (realm < 0) {
480 B2FATAL("Invalid realm! Needs to be one of online or production.");
481 }
483 }
484
485 if (varMap.count("secondary-input")) {
486 const auto& names = varMap["secondary-input"].as<vector<string>>();
488 }
489
490 } catch (exception& e) {
491 cerr << "error: " << e.what() << endl;
492 return 1;
493 } catch (...) {
494 cerr << "Exception of unknown type!" << endl;
495 return 1;
496 }
497
498 //---------------------------------------------------
499 // If the python file is set, execute it
500 //---------------------------------------------------
501 PyStatus status;
502 PyConfig config;
503 PyConfig_InitPythonConfig(&config);
504 config.install_signal_handlers = 0;
505 config.safe_path = 0;
506
507 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
508
509 std::vector<wstring> pyArgvString(arguments.size() + 2);
510
511
512 pyArgvString[0] = L"python3"; //set the executable
513 pyArgvString[1] = converter.from_bytes(pythonFile);
514 for (size_t i = 0; i < arguments.size(); i++) {
515 pyArgvString[i + 2] = converter.from_bytes(arguments[i]);
516 }
517 std::vector<const wchar_t*> pyArgvArray(pyArgvString.size());
518 for (size_t i = 0; i < pyArgvString.size(); ++i) {
519 pyArgvArray[i] = pyArgvString[i].c_str();
520 }
521
522
523 //Pass python filename and additional arguments to python
524 status = PyConfig_SetArgv(&config, pyArgvArray.size(), const_cast<wchar_t**>(pyArgvArray.data()));
525 checkPythonStatus(config, status);
526
527 status = Py_InitializeFromConfig(&config);
528 checkPythonStatus(config, status);
529
530 auto fullPath = std::filesystem::absolute(std::filesystem::path(pythonFile));
531
532 if ((std::filesystem::is_directory(fullPath)) || !(std::filesystem::exists(fullPath))) {
533 B2FATAL("The given filename and/or path is not valid: " + pythonFile);
534 }
535
536 std::ifstream file(fullPath.string().c_str());
537 std::stringstream buffer;
538 buffer << file.rdbuf();
539 Environment::Instance().setSteering(buffer.str());
540 int pyReturnValue = Py_RunMain();
541
542 //Finish Python interpreter
543 PyConfig_Clear(&config);
544 Py_Finalize();
545
546 //basf2.py was loaded, now do module I/O visualization
547 if (!runModuleIOVisualization.empty()) {
549 }
550
551 //--dry-run: print gathered information
552 if (Environment::Instance().getDryRun()) {
554 }
555
556 //Report completion in json metadata
557 MetadataService::Instance().addBasf2Status("finished successfully");
559
560 return pyReturnValue;
561}
static void executeModuleAndCreateIOPlot(const std::string &module)
Create independent I/O graph for a single module (without requiring a steering file).
void setOutputFileOverride(const std::string &name)
Override output file name for modules.
void setProfileModuleName(const std::string &name)
Set the name of a module to be profiled.
void setSteering(const std::string &steering)
Sets the steering file content.
void setNumberEventsOverride(unsigned int nevents)
Override the number of events in run 1 for EventInfoSetter module.
Definition Environment.h:65
void setRealm(LogConfig::ELogRealm realm)
Set the basf2 execution realm.
void setRunExperimentOverride(int run, int experiment)
Override run and experiment for EventInfoSetter.
Definition Environment.h:80
void setNumberProcessesOverride(int nproc)
Override number of processes to run in parallel.
void setLogLevelOverride(int level)
Override global log level if != LogConfig::c_Default.
void printJobInformation() const
Print information on input/output files in current steering file, used by –dry-run.
void setEntrySequencesOverride(const std::vector< std::string > &sequences)
Override the number sequences (e.g.
Definition Environment.h:71
static Environment & Instance()
Static method to get a reference to the Environment instance.
void setSecondaryInputFilesOverride(const std::vector< std::string > &names)
Override secondary input file names for modules.
void setUseZMQ(bool useZMQ)
Set the flag if ZMQ should be used instead of the RingBuffer multiprocessing implementation.
void setPicklePath(const std::string &path)
Sets the path to the file where the pickled path is stored.
void setSkipEventsOverride(unsigned int skipEvents)
Set skipNEvents override.
Definition Environment.h:88
void setVisualizeDataFlow(bool on)
Whether to generate DOT files with data store inputs/outputs of each module.
void setInputFilesOverride(const std::vector< std::string > &names)
Override input file names for modules.
void setNoStats(bool noStats)
Disable collection of statistics during event processing.
void setDryRun(bool dryRun)
Read steering file, but do not start any actually start any event processing.
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
void setDebugLevel(int debugLevel)
Configure the debug messaging level.
Definition LogConfig.h:98
static const char * logRealmToString(ELogRealm realm)
Converts a log realm type to a string.
Definition LogConfig.cc:49
ELogLevel
Definition of the supported log levels.
Definition LogConfig.h:26
@ c_Debug
Debug: for code development.
Definition LogConfig.h:26
@ c_Fatal
Fatal: for situations were the program execution can not be continued.
Definition LogConfig.h:31
ELogRealm
Definition of the supported execution realms.
Definition LogConfig.h:48
@ c_Online
Online data taking.
Definition LogConfig.h:49
@ c_Production
Data production jobs.
Definition LogConfig.h:50
void setLogLevel(ELogLevel logLevel)
Configure the log level.
Definition LogConfig.cc:25
static const char * logLevelToString(ELogLevel logLevelType)
Converts a log level type to a string.
Definition LogConfig.cc:42
LogConfig * getLogConfig()
Returns global log system configuration.
Definition LogSystem.h:78
LogConfig & getModuleLogConfig(const std::string &module)
Get the log configuration for the module with the given name.
Definition LogSystem.h:105
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
Definition LogSystem.cc:28
LogConfig & getPackageLogConfig(const std::string &package)
Get the log configuration for the package with the given name.
Definition LogSystem.h:96
void addBasf2Status(const std::string &message="")
Add metadata of basf2 status.
void setJsonFileName(const std::string &fileName)
Set the name of the json metadata file.
static MetadataService & Instance()
Static method to get a reference to the MetadataService instance.
void finishBasf2(bool success=true)
Add metadata for basf2 completion.
static void initialize()
Initialize the random number generator with a unique random seed;.
Abstract base class for different kinds of events.
STL namespace.