LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
DebugOptionsHandler.cc
Go to the documentation of this file.
2 
6 #include "fhiclcpp/coding.h"
9 #include "fhiclcpp/parse.h"
10 
11 #include <regex>
12 #include <string>
13 
14 using namespace std::string_literals;
17 
18 namespace {
19  std::pair<std::string, bool>
20  destination_via_env()
21  {
22  char const* debug_config{getenv("ART_DEBUG_CONFIG")};
23  if (debug_config == nullptr)
24  return std::make_pair("", false);
25 
26  try {
27  // Check if the provided character string is a file name
28  std::string fn;
29  if (std::regex_match(debug_config, std::regex("[[:alpha:]/\\.].*"))) {
30  fn = debug_config;
31  }
32  std::cerr << "** ART_DEBUG_CONFIG is defined **\n";
33  return std::make_pair(fn, true);
34  }
35  catch (std::regex_error const& e) {
36  std::cerr << "REGEX ERROR: " << e.code() << ".\n";
37  }
38  return std::make_pair("", false);
39  }
40 }
41 
42 art::DebugOptionsHandler::DebugOptionsHandler(bpo::options_description& desc,
43  std::string const& basename)
44 {
45  bpo::options_description debug_options{"Debugging options"};
46  auto options = debug_options.add_options();
47  add_opt(options,
48  "mt-diagnostics,M",
49  bpo::value<std::string>(),
50  "Log art-specific multi-threading diagnostics to "
51  "the provided destination.");
52  add_opt(options, "trace", "Activate tracing.");
53  add_opt(options, "notrace", "Deactivate tracing.");
54  add_opt(
55  options, "timing", "Activate monitoring of time spent per event/module.");
56  add_opt(options,
57  "timing-db",
58  bpo::value<std::string>(),
59  "Output time-tracking data to SQLite3 database with name <db-file>.");
60  add_opt(options, "notiming", "Deactivate time tracking.");
61  add_opt(options,
62  "memcheck",
63  "Activate monitoring of memory use (deprecated--per-job "
64  "memory information printed in job summary).");
65  add_opt(options,
66  "memcheck-db",
67  bpo::value<std::string>(),
68  "Output memory use data to SQLite3 database with name <db-file>.");
69  add_opt(options, "nomemcheck", "Deactivate monitoring of memory use.");
70  add_opt(
71  options,
72  "validate-config",
73  bpo::value<std::string>(),
74  "Output post-processed configuration to <file>; call constructors of all "
75  "sources, modules and services, performing extra configuration "
76  "verification. Exit just before processing the event loop.");
77  add_opt(
78  options,
79  "debug-config",
80  bpo::value<std::string>(),
81  ("Output post-processed configuration to <file> and exit. Equivalent to env ART_DEBUG_CONFIG=<file> "s +
82  basename + " ...")
83  .c_str());
84  add_opt(
85  options,
86  "config-out",
87  bpo::value<std::string>(),
88  "Output post-processed configuration to <file> and continue with job.");
89  add_opt(
90  options, "annotate", "Include configuration parameter source information.");
91  add_opt(options,
92  "prefix-annotate",
93  "Include configuration parameter source information "
94  "on line preceding parameter declaration.");
95  desc.add(debug_options);
96 }
97 
98 int
99 art::DebugOptionsHandler::doCheckOptions(bpo::variables_map const& vm)
100 {
101  if (vm.count("trace") + vm.count("notrace") > 1) {
103  << "Options --trace and --notrace are incompatible.\n";
104  }
105  if (vm.count("timing") + vm.count("notiming") > 1) {
107  << "Options --timing and --notiming are incompatible.\n";
108  }
109  if (vm.count("timing-db") + vm.count("notiming") > 1) {
111  << "Options --timing-db and --notiming are incompatible.\n";
112  }
113  if (vm.count("memcheck") + vm.count("nomemcheck") > 1) {
115  << "Options --memcheck and --nomemcheck are incompatible.\n";
116  }
117  if (vm.count("memcheck-db") + vm.count("nomemcheck") > 1) {
119  << "Options --memcheck-db and --nomemcheck are incompatible.\n";
120  }
121  if (vm.count("validate-config") + vm.count("debug-config") +
122  vm.count("config-out") >
123  1) {
125  << "Options --validate-config, --debug-config, and --config-out are "
126  "incompatible.\n";
127  }
128  if (vm.count("annotate") + vm.count("prefix-annotate") > 1) {
130  << "Options --annotate and --prefix-annotate are incompatible.\n";
131  }
132 
133  if (vm.count("annotate") + vm.count("prefix-annotate") == 1 &&
134  vm.count("debug-config") + vm.count("config-out") == 0) {
136  << "Options --annotate and --prefix-annotate must be specified with "
137  "either --debug-config or --config-out.\n";
138  }
139 
140  return 0;
141 }
142 
143 int
145  bpo::variables_map const& vm,
146  fhicl::intermediate_table& raw_config)
147 {
148 
149  using namespace fhicl::detail;
150 
151  auto const scheduler_key = fhicl_key("services", "scheduler");
152  std::string debug_table;
153 
154  // Get ART_DEBUG_CONFIG value
155  std::string fn;
156  auto const result = destination_via_env();
157  if (result.second) {
158  debug_table = fhicl_key(scheduler_key, "debugConfig");
159  fn = result.first;
160  }
161 
162  // "validate-config" and "debug-config" win over ART_DEBUG_CONFIG
163  if (vm.count("validate-config")) {
164  debug_table = fhicl_key(scheduler_key, "validateConfig");
165  fn = vm["validate-config"].as<std::string>();
166  } else if (vm.count("debug-config")) {
167  debug_table = fhicl_key(scheduler_key, "debugConfig");
168  fn = vm["debug-config"].as<std::string>();
169  } else if (vm.count("config-out")) {
170  debug_table = fhicl_key(scheduler_key, "configOut");
171  fn = vm["config-out"].as<std::string>();
172  }
173  if (!debug_table.empty()) {
174  raw_config.put(fhicl_key(debug_table, "fileName"), fn);
175  }
176 
177  std::string mode{"raw"};
178  if (vm.count("annotate")) {
179  mode = "annotate";
180  }
181  if (vm.count("prefix-annotate")) {
182  mode = "prefix-annotate";
183  }
184  if (!debug_table.empty()) {
185  raw_config.put(fhicl_key(debug_table, "printMode"), mode);
186  }
187 
188  if (vm.count("trace")) {
189  raw_config.put("services.scheduler.wantTracer", true);
190  } else if (vm.count("notrace")) {
191  raw_config.put("services.scheduler.wantTracer", false);
192  }
193  auto const timingdb = vm.count("timing-db");
194  if (vm.count("timing") || timingdb) {
195  raw_config.putEmptyTable("services.TimeTracker");
196  if (timingdb)
197  raw_config.put("services.TimeTracker.dbOutput.filename",
198  vm["timing-db"].as<std::string>());
199  } else if (vm.count("notiming")) {
200  raw_config.erase("services.TimeTracker");
201  }
202  auto const memdb = vm.count("memcheck-db");
203  if (vm.count("memcheck") || memdb) {
204  raw_config.putEmptyTable("services.MemoryTracker");
205  if (memdb)
206  raw_config.put("services.MemoryTracker.dbOutput.filename",
207  vm["memcheck-db"].as<std::string>());
208  } else if (vm.count("nomemcheck")) {
209  raw_config.erase("services.MemoryTracker");
210  }
211 
212  // messagefacility configuration.
213  auto const message_key = fhicl_key("services", "message");
214  auto const dests_key = fhicl_key(message_key, "destinations");
215  if (!detail::exists_outside_prolog(raw_config, message_key)) {
216  raw_config.put(fhicl_key(dests_key, "STDOUT.categories.ArtReport.limit"),
217  100);
218  raw_config.put(fhicl_key(dests_key, "STDOUT.categories.default.limit"), -1);
219  raw_config.put(fhicl_key(dests_key, "STDOUT.type"), "cout");
220  raw_config.put(fhicl_key(dests_key, "STDOUT.threshold"), "INFO");
221  }
222  assert(detail::exists_outside_prolog(raw_config, dests_key));
223  auto const& dests = raw_config.get<table_t const&>(dests_key);
224 
225  // By default, suppress all logging of messages of MTdiagnostics category.
226  for (auto const& p : dests) {
227  std::string const& dest_name = p.first;
228  if (dest_name == "statistics"s)
229  continue; // statistics are special -- see below
230  raw_config.put(
231  fhicl_key(dests_key, dest_name, "categories.MTdiagnostics.limit"), 0);
232  }
233 
234  // The statistics destination represents a table of named destinations.
235  auto const& stats_dest_key = fhicl_key(dests_key, "statistics");
236  if (detail::exists_outside_prolog(raw_config, stats_dest_key)) {
237  auto const& stats_dests = raw_config.get<table_t const&>(stats_dest_key);
238  for (auto const& p : stats_dests) {
239  std::string const& dest_name = p.first;
240  raw_config.put(
241  fhicl_key(stats_dest_key, dest_name, "categories.MTdiagnostics.limit"),
242  0);
243  }
244  }
245 
246  if (vm.count("mt-diagnostics") > 0) {
247  auto const dest = vm["mt-diagnostics"].as<std::string>();
248  std::regex const re_stdout{R"((STDOUT|cout))",
249  std::regex_constants::ECMAScript |
250  std::regex_constants::icase};
251  std::regex const re_stderr{R"((STDERR|cerr))",
252  std::regex_constants::ECMAScript |
253  std::regex_constants::icase};
254  if (std::regex_match(dest, re_stdout)) {
255  // Special handling since the 'cout' destination is already the
256  // default per above.
257  raw_config.put(
258  fhicl_key(dests_key, "STDOUT.categories.MTdiagnostics.limit"), -1);
259  return 0;
260  }
261 
262  auto const mt_dest_key = fhicl_key(dests_key, "MTdiagnostics");
263  if (std::regex_match(dest, re_stderr)) {
264  raw_config.put(fhicl_key(mt_dest_key, "type"), "cerr");
265  } else {
266  raw_config.put(fhicl_key(mt_dest_key, "type"), "file");
267  raw_config.put(fhicl_key(mt_dest_key, "filename"), dest);
268  }
269  raw_config.put(fhicl_key(mt_dest_key, "categories.MTdiagnostics.limit"),
270  -1);
271  raw_config.put(fhicl_key(mt_dest_key, "categories.default.limit"), 0);
272  }
273 
274  return 0;
275 }
int doProcessOptions(bpo::variables_map const &vm, fhicl::intermediate_table &raw_config) override
Float_t s
Definition: plot.C:23
bool exists_outside_prolog(fhicl::intermediate_table const &config, std::string const &key)
void add_opt(T &t, Args &&...args)
void erase(std::string const &name, bool in_prolog=false)
int doCheckOptions(bpo::variables_map const &vm) override
shims::map< std::string, extended_value > table_t
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
std::enable_if_t< std::is_convertible< T, std::string >::value, std::string > fhicl_key(T const &name)
Definition: fhicl_key.h:13
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool putEmptyTable(std::string const &name, bool in_prolog=false)
DebugOptionsHandler(bpo::options_description &desc, std::string const &basename)
T get(std::string const &name)
Float_t e
Definition: plot.C:34