CMS 3D CMS Logo

ThreadSafeLogMessageLoggerScribe.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------
2 //
3 // ThreadSafeLogMessageLoggerScribe.cc
4 //
5 // NOTE: This was originally copied from MessageLoggerScribe but removed
6 // the potential use of the ThreadQueue. MessageLoggerScribe was not
7 // modified since it was decided we might have to keep the old behaviour
8 // around for 'legacy' reasons.
9 //
10 // ----------------------------------------------------------------------
11 
16 
20 #include "FWCore/MessageLogger/interface/MessageDrop.h" // change log 37
21 #include "FWCore/MessageLogger/interface/ELseverityLevel.h" // change log 37
22 
25 
28 
29 #include <algorithm>
30 #include <cassert>
31 #include <fstream>
32 #include <string>
33 #include <csignal>
34 
35 using std::cerr;
36 using namespace edm::messagelogger;
37 
38 namespace edm {
39  namespace service {
40 
41  ThreadSafeLogMessageLoggerScribe::ThreadSafeLogMessageLoggerScribe()
42  : m_admin_p(std::make_shared<ELadministrator>()),
43  m_early_dest(m_admin_p->attach(std::make_shared<ELoutput>(std::cerr, false))),
44  m_clean_slate_configuration(true),
45  m_active(true),
46  m_purge_mode(false),
47  m_count(0),
48  m_messageBeingSent(false),
49  m_waitingThreshold(100),
50  m_tooManyWaitingMessagesCount(0) {}
51 
53  //if there are any waiting message, finish them off
54  ErrorObj* errorobj_p = nullptr;
55  std::vector<std::string> categories;
56  while (m_waitingMessages.try_pop(errorobj_p)) {
57  if (not m_purge_mode) {
58  categories.clear();
59  parseCategories(errorobj_p->xid().id, categories);
60  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
61  errorobj_p->setID(categories[icat]);
62  m_admin_p->log(*errorobj_p); // route the message text
63  }
64  }
65  delete errorobj_p;
66  }
67 
68  m_admin_p->finish();
69  }
70 
73  void* operand) {
74  switch (opcode) { // interpret the work item
75  default: {
76  assert(false); // can't happen (we certainly hope!)
77  break;
78  }
80  break;
81  }
83  ErrorObj* errorobj_p = static_cast<ErrorObj*>(operand);
84  try {
85  if (m_active && !m_purge_mode) {
86  log(errorobj_p);
87  }
88  } catch (cms::Exception& e) {
89  ++m_count;
90  std::cerr << "ThreadSafeLogMessageLoggerScribe caught " << m_count << " cms::Exceptions, text = \n"
91  << e.what() << "\n";
92 
93  if (m_count > 25) {
94  cerr << "MessageLogger will no longer be processing "
95  << "messages due to errors (entering purge mode).\n";
96  m_purge_mode = true;
97  }
98  } catch (...) {
99  std::cerr << "ThreadSafeLogMessageLoggerScribe caught an unknown exception and "
100  << "will no longer be processing "
101  << "messages. (entering purge mode)\n";
102  m_purge_mode = true;
103  }
104  break;
105  }
106  case MessageLoggerQ::CONFIGURE: { // changelog 17
107  auto job_pset_p = std::unique_ptr<edm::ParameterSet>(
108  static_cast<edm::ParameterSet*>(operand)); // propagate_const<T> has no reset() function
109  validate(*job_pset_p);
110  configure_errorlog(*job_pset_p);
111  break;
112  }
114  assert(operand == nullptr);
115  try {
117  } catch (cms::Exception& e) {
118  std::cerr << "ThreadSafeLogMessageLoggerScribe caught exception "
119  << "during summarize:\n"
120  << e.what() << "\n";
121  } catch (...) {
122  std::cerr << "ThreadSafeLogMessageLoggerScribe caught unkonwn exception type "
123  << "during summarize. (Ignored)\n";
124  }
125  break;
126  }
127  case MessageLoggerQ::JOBMODE: { // change log 24
128  std::string* jobMode_p = static_cast<std::string*>(operand);
129  JobMode jm = MessageLoggerDefaults::mode(*jobMode_p);
131  // Note - since m_messageLoggerDefaults is a value_ptr,
132  // there is no concern about deleting here.
133  delete jobMode_p; // dispose of the message text
134  // which will have been new-ed
135  // in MessageLogger.cc (service version)
136  break;
137  }
139  assert(operand == nullptr);
140  m_active = false;
141  break;
142  }
143  case MessageLoggerQ::FLUSH_LOG_Q: { // changelog 26
144  break;
145  }
146  case MessageLoggerQ::GROUP_STATS: { // change log 27
147  std::string* cat_p = static_cast<std::string*>(operand);
149  delete cat_p; // dispose of the message text
150  break;
151  }
152  case MessageLoggerQ::FJR_SUMMARY: { // changelog 29
153  std::map<std::string, double>* smp = static_cast<std::map<std::string, double>*>(operand);
155  break;
156  }
157  } // switch
158 
159  } // ThreadSafeLogMessageLoggerScribe::runCommand(opcode, operand)
160 
162  bool expected = false;
163  std::unique_ptr<ErrorObj> obj(errorobj_p);
164  if (m_messageBeingSent.compare_exchange_strong(expected, true)) {
165  std::vector<std::string> categories;
166  parseCategories(errorobj_p->xid().id, categories);
167  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
168  errorobj_p->setID(categories[icat]);
169  m_admin_p->log(*errorobj_p); // route the message text
170  }
171  //process any waiting messages
172  errorobj_p = nullptr;
173  while (not m_purge_mode and m_waitingMessages.try_pop(errorobj_p)) {
174  obj.reset(errorobj_p);
175  categories.clear();
176  parseCategories(errorobj_p->xid().id, categories);
177  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
178  errorobj_p->setID(categories[icat]);
179  m_admin_p->log(*errorobj_p); // route the message text
180  }
181  }
182  m_messageBeingSent.store(false);
183  } else {
184  if (m_waitingMessages.unsafe_size() < m_waitingThreshold) {
185  obj.release();
186  m_waitingMessages.push(errorobj_p);
187  } else {
189  }
190  }
191  }
192 
193  namespace {
194  bool usingOldConfig(edm::ParameterSet const& pset) {
195  if (not pset.exists("files") and
196  ((pset.exists("destinations") or pset.existsAs<std::vector<std::string>>("statistics", true) or
197  pset.existsAs<std::vector<std::string>>("statistics", false) or pset.exists("categories")))) {
198  return true;
199  }
200  return false;
201  }
202 
203  std::set<std::string> findCategoriesInDestination(edm::ParameterSet const& pset) {
204  auto psets = pset.getParameterNamesForType<edm::ParameterSet>(false);
205  auto itFound = std::find(psets.begin(), psets.end(), "default");
206  if (itFound != psets.end()) {
207  psets.erase(itFound);
208  }
209 
210  return std::set<std::string>(psets.begin(), psets.end());
211  }
212  std::vector<std::string> findAllCategories(edm::ParameterSet const& pset) {
213  std::set<std::string> categories;
214 
215  auto psets = pset.getParameterNamesForType<edm::ParameterSet>(false);
216  auto itFound = std::find(psets.begin(), psets.end(), "default");
217  if (itFound != psets.end()) {
218  categories = findCategoriesInDestination(pset.getUntrackedParameter<edm::ParameterSet>("default"));
219  psets.erase(itFound);
220  }
221 
222  itFound = std::find(psets.begin(), psets.end(), "cout");
223  if (itFound != psets.end()) {
224  categories.merge(findCategoriesInDestination(pset.getUntrackedParameter<edm::ParameterSet>("cout")));
225  psets.erase(itFound);
226  }
227 
228  itFound = std::find(psets.begin(), psets.end(), "cerr");
229  if (itFound != psets.end()) {
230  categories.merge(findCategoriesInDestination(pset.getUntrackedParameter<edm::ParameterSet>("cerr")));
231  psets.erase(itFound);
232  }
233 
234  auto const& files = pset.getUntrackedParameter<edm::ParameterSet>("files");
235  for (auto const& name : files.getParameterNamesForType<edm::ParameterSet>(false)) {
236  categories.merge(findCategoriesInDestination(files.getUntrackedParameter<edm::ParameterSet>(name)));
237  }
238  categories.insert(psets.begin(), psets.end());
239 
240  return std::vector<std::string>(categories.begin(), categories.end());
241  }
242 
243  } // namespace
244 
246  std::string const& psetname) const {
247  // Determine the destination file name to use if no explicit filename is
248  // supplied in the cfg.
249  std::string const empty_String;
250  std::string filename = psetname;
251  std::string filename_default = getAparameter<std::string>(dest_pset, "output", empty_String);
252  if (filename_default == empty_String) {
253  filename_default = m_messageLoggerDefaults->output(psetname); // change log 31
254  if (filename_default == empty_String) {
255  filename_default = filename;
256  }
257  }
258 
259  std::string explicit_filename = getAparameter<std::string>(dest_pset, "filename", filename_default);
260  if (explicit_filename != empty_String)
261  filename = explicit_filename;
262  std::string explicit_extension = getAparameter<std::string>(dest_pset, "extension", empty_String);
263  if (explicit_extension != empty_String) {
264  if (explicit_extension[0] == '.') {
265  filename += explicit_extension;
266  } else {
267  filename = filename + "." + explicit_extension;
268  }
269  }
270 
271  // Attach a default extension of .log if there is no extension on a file
272  if ((filename != "cout") && (filename != "cerr")) {
273  if (filename.find('.') == std::string::npos) {
274  filename += ".log";
275  }
276  }
277  return filename;
278  }
279 
281  {
282  auto preconfiguration_message =
283  job_pset.getUntrackedParameter<std::string>("generate_preconfiguration_message");
284  if (not preconfiguration_message.empty()) {
285  // To test a preconfiguration message without first going thru the
286  // configuration we are about to do, we issue the message (so it sits
287  // on the queue), then copy the processing that the LOG_A_MESSAGE case
288  // does. We suppress the timestamp to allow for automated unit testing.
289  m_early_dest->suppressTime();
290  LogError("preconfiguration") << preconfiguration_message;
291  }
292  }
293  if (!m_stream_ps.empty()) {
294  LogWarning("multiLogConfig") << "The message logger has been configured multiple times";
295  m_clean_slate_configuration = false; // Change Log 22
296  }
297  m_waitingThreshold = job_pset.getUntrackedParameter<unsigned int>("waiting_threshold");
298 
299  auto defaults = parseDefaults(job_pset);
300  auto categories = findAllCategories(job_pset);
301 
302  // Initialize unversal suppression variables
307 
308  m_early_dest->setThreshold(ELhighestSeverity);
309 
310  auto cout_dest = job_pset.getUntrackedParameter<edm::ParameterSet>("cout");
311  if (cout_dest.getUntrackedParameter<bool>("enable")) {
312  auto dest_ctrl = makeDestinationCtrl("cout");
313  configure_dest(job_pset, defaults, categories, dest_ctrl, cout_dest, "cout");
314  }
315 
316  auto cerr_dest = job_pset.getUntrackedParameter<edm::ParameterSet>("cerr");
317  if (cerr_dest.getUntrackedParameter<bool>("enable")) {
318  auto dest_ctrl = makeDestinationCtrl("cerr");
319  configure_dest(job_pset, defaults, categories, dest_ctrl, cerr_dest, "cerr");
320  }
321 
322  auto const& files = job_pset.getUntrackedParameter<edm::ParameterSet>("files");
323  for (auto const& name : files.getParameterNamesForType<edm::ParameterSet>(false)) {
324  auto const& dest_pset = files.getUntrackedParameter<edm::ParameterSet>(name);
325  auto const actual_filename = destinationFileName(dest_pset, name);
326 
327  // Check that this is not a duplicate name
328  if (m_stream_ps.find(actual_filename) != m_stream_ps.end()) {
330  throw cms::Exception("DuplicateDestination")
331  << "Duplicate name for a MessageLogger Destination: " << actual_filename << "\n"
332  << "Please modify the configuration to use unique file names.";
333  } else {
334  LogWarning("duplicateDestination")
335  << "Duplicate name for a MessageLogger Destination: " << actual_filename << "\n"
336  << "Only original configuration instructions are used";
337  continue;
338  }
339  }
340 
341  auto dest_ctrl = makeDestinationCtrl(actual_filename);
342  configure_dest(job_pset, defaults, categories, dest_ctrl, dest_pset, name);
343  }
344  //NOTE: statistics destinations MUST BE last in the list else they can be fooled into
345  // thinking a message has been ignored just because a later destination which uses it
346  // falls later in the list.
347  for (auto const& name : files.getParameterNamesForType<edm::ParameterSet>(false)) {
348  auto const& dest_pset = files.getUntrackedParameter<edm::ParameterSet>(name);
349  auto const actual_filename = destinationFileName(dest_pset, name);
350  if (getAparameter<bool>(dest_pset, "enableStatistics", false)) {
351  configure_statistics_dest(job_pset, defaults, categories, dest_pset, name, actual_filename);
352  }
353  }
354  if (cout_dest.getUntrackedParameter<bool>("enable") and
355  getAparameter<bool>(cout_dest, "enableStatistics", true)) {
356  configure_statistics_dest(job_pset, defaults, categories, cout_dest, "cout", "cout");
357  }
358  if (cerr_dest.getUntrackedParameter<bool>("enable") and
359  getAparameter<bool>(cerr_dest, "enableStatistics", true)) {
360  configure_statistics_dest(job_pset, defaults, categories, cerr_dest, "cerr", "cerr");
361  }
362  }
363 
365  if (not usingOldConfig(job_pset)) {
366  configure_errorlog_new(job_pset);
367  return;
368  }
369  const vString empty_vString;
370  const std::string empty_String;
371  const edm::ParameterSet empty_PSet;
372 
373  // The following is present to test pre-configuration message handling:
374  std::string preconfiguration_message =
375  getAparameter<std::string>(job_pset, "generate_preconfiguration_message", empty_String);
376  if (preconfiguration_message != empty_String) {
377  // To test a preconfiguration message without first going thru the
378  // configuration we are about to do, we issue the message (so it sits
379  // on the queue), then copy the processing that the LOG_A_MESSAGE case
380  // does. We suppress the timestamp to allow for automated unit testing.
381  m_early_dest->suppressTime();
382  LogError("preconfiguration") << preconfiguration_message;
383  }
384 
385  if (!m_stream_ps.empty()) {
386  LogWarning("multiLogConfig") << "The message logger has been configured multiple times";
387  m_clean_slate_configuration = false; // Change Log 22
388  }
389  m_waitingThreshold = getAparameter<unsigned int>(job_pset, "waiting_threshold", 100);
390  auto defaults = parseDefaults(job_pset);
391  // grab list of categories
392  vString categories = getAparameter<vString>(job_pset, "categories", empty_vString);
393  // grab list of hardwired categories (hardcats) -- these are to be added
394  // to the list of categories -- change log 24
395  {
396  std::vector<std::string> hardcats = m_messageLoggerDefaults->categories;
397  // combine the lists, not caring about possible duplicates (for now)
398  copy_all(hardcats, std::back_inserter(categories));
399  } // no longer need hardcats
400 
401  auto destination_names = configure_ordinary_destinations(job_pset, defaults, categories);
402  configure_statistics(job_pset, defaults, categories, destination_names);
403  } // ThreadSafeLogMessageLoggerScribe::configure_errorlog()
404 
406  std::shared_ptr<ELdestination> dest_ctrl;
407  if (filename == "cout") {
408  dest_ctrl = m_admin_p->attach(std::make_shared<ELoutput>(std::cout));
409  m_stream_ps["cout"] = &std::cout;
410  } else if (filename == "cerr") {
411  m_early_dest->setThreshold(ELzeroSeverity);
412  dest_ctrl = m_early_dest;
413  m_stream_ps["cerr"] = &std::cerr;
414  } else {
415  auto os_sp = std::make_shared<std::ofstream>(filename.c_str());
416  m_file_ps.push_back(os_sp);
417  dest_ctrl = m_admin_p->attach(std::make_shared<ELoutput>(*os_sp));
418  m_stream_ps[filename] = os_sp.get();
419  }
420  return dest_ctrl;
421  }
422 
423  namespace {
424  void setGlobalThresholds(ELseverityLevel threshold_sev) {
425  if (threshold_sev <= ELseverityLevel::ELsev_success) {
427  }
428  if (threshold_sev <= ELseverityLevel::ELsev_info) {
430  }
431  if (threshold_sev <= ELseverityLevel::ELsev_fwkInfo) {
433  }
434  if (threshold_sev <= ELseverityLevel::ELsev_warning) {
436  }
437  }
438  } // namespace
439 
441  edm::ParameterSet const& job_pset) {
442  const edm::ParameterSet empty_PSet;
444  // grab default limit/interval/timespan common to all destinations/categories:
445  edm::ParameterSet default_pset = getAparameter<edm::ParameterSet>(job_pset, "default", empty_PSet);
446  returnValue.limit_ = getAparameter<int>(
448  returnValue.reportEvery_ = getAparameter<int>(
450  returnValue.timespan_ = getAparameter<int>(
452  std::string default_threshold = getAparameter<std::string>(job_pset, "threshold", std::string());
453  returnValue.threshold_ = getAparameter<std::string>(default_pset, "threshold", default_threshold);
454  returnValue.noLineBreaks_ = getAparameter<bool>(default_pset, "noLineBreaks", false);
455  returnValue.lineLength_ = getAparameter<int>(default_pset, "lineLength", 80);
456  returnValue.noTimeStamps_ = getAparameter<bool>(default_pset, "noTimeStamps", false);
457 
458  return returnValue;
459  }
460 
463  vString const& categories,
464  std::shared_ptr<ELdestination> dest_ctrl,
465  edm::ParameterSet const& dest_pset,
466  std::string const& filename) {
467  vString const empty_vString;
468  edm::ParameterSet const empty_PSet;
469  std::string const empty_String;
470 
471  // Defaults: // change log 3a
472  const std::string COMMON_DEFAULT_THRESHOLD = "INFO";
473 
474  vString const severities = {{"WARNING", "INFO", "FWKINFO", "ERROR", "DEBUG"}};
475 
476  // grab default threshold common to all destinations
477  std::string const default_threshold = getAparameter<std::string>(job_pset, "threshold", empty_String);
478  // change log 3a
479  // change log 24
480 
481  // grab default limit/interval/timespan common to all destinations/categories:
482  edm::ParameterSet const default_pset = getAparameter<edm::ParameterSet>(job_pset, "default", empty_PSet);
483 
484  // See if this is just a placeholder // change log 9
485  bool is_placeholder = getAparameter<bool>(dest_pset, "placeholder", false);
486  if (is_placeholder)
487  return;
488 
489  // grab this destination's default limit/interval/timespan:
490  edm::ParameterSet dest_default_pset = getAparameter<edm::ParameterSet>(dest_pset, "default", empty_PSet);
491  int dest_default_limit = getAparameter<int>(dest_default_pset, "limit", defaults.limit_);
492  int dest_default_interval = getAparameter<int>(dest_default_pset, "reportEvery", defaults.reportEvery_);
493  // change log 6
494  int dest_default_timespan = getAparameter<int>(dest_default_pset, "timespan", defaults.timespan_);
495  // change log 1a
496  if (dest_default_limit != defaults.NO_VALUE_SET) {
497  if (dest_default_limit < 0)
498  dest_default_limit = 2000000000;
499  dest_ctrl->setLimit("*", dest_default_limit);
500  } // change log 1b, 2a, 2b
501  if (dest_default_interval != defaults.NO_VALUE_SET) { // change log 6
502  dest_ctrl->setInterval("*", dest_default_interval);
503  }
504  if (dest_default_timespan != defaults.NO_VALUE_SET) {
505  if (dest_default_timespan < 0)
506  dest_default_timespan = 2000000000;
507  dest_ctrl->setTimespan("*", dest_default_timespan);
508  } // change log 1b, 2a, 2b
509 
510  // establish this destination's threshold:
511  std::string dest_threshold = getAparameter<std::string>(dest_pset, "threshold", default_threshold);
512  if (dest_threshold == empty_String) {
513  dest_threshold = default_threshold;
514  }
515  if (dest_threshold == empty_String) { // change log 34
516  dest_threshold = defaults.threshold_;
517  }
518  if (dest_threshold == empty_String) {
519  dest_threshold = m_messageLoggerDefaults->threshold(filename);
520  }
521  if (dest_threshold == empty_String)
522  dest_threshold = COMMON_DEFAULT_THRESHOLD;
523  ELseverityLevel threshold_sev(dest_threshold);
524  dest_ctrl->setThreshold(threshold_sev);
525  // change log 37
526  setGlobalThresholds(threshold_sev);
527 
528  // establish this destination's limit/interval/timespan for each category:
529  for (vString::const_iterator id_it = categories.begin(); id_it != categories.end(); ++id_it) {
530  std::string msgID = *id_it;
531  edm::ParameterSet default_category_pset =
532  getAparameter<edm::ParameterSet>(default_pset, msgID, empty_PSet); // change log 5
533  edm::ParameterSet category_pset = getAparameter<edm::ParameterSet>(dest_pset, msgID, default_category_pset);
534 
535  int category_default_limit = getAparameter<int>(default_category_pset, "limit", defaults.NO_VALUE_SET);
536  int limit = getAparameter<int>(category_pset, "limit", category_default_limit);
537  if (limit == defaults.NO_VALUE_SET)
538  limit = dest_default_limit;
539  // change log 7
540  int category_default_interval = getAparameter<int>(default_category_pset, "reportEvery", defaults.NO_VALUE_SET);
541  int interval = getAparameter<int>(category_pset, "reportEvery", category_default_interval);
542  if (interval == defaults.NO_VALUE_SET)
543  interval = dest_default_interval;
544  // change log 6 and then 7
545  int category_default_timespan = getAparameter<int>(default_category_pset, "timespan", defaults.NO_VALUE_SET);
546  int timespan = getAparameter<int>(category_pset, "timespan", category_default_timespan);
547  if (timespan == defaults.NO_VALUE_SET)
548  timespan = dest_default_timespan;
549  // change log 7
550 
551  const std::string& category = msgID;
552  if (limit == defaults.NO_VALUE_SET) { // change log 24
554  }
555  if (interval == defaults.NO_VALUE_SET) { // change log 24
557  }
558  if (timespan == defaults.NO_VALUE_SET) { // change log 24
560  }
561 
562  if (limit != defaults.NO_VALUE_SET) {
563  if (limit < 0)
564  limit = 2000000000;
565  dest_ctrl->setLimit(msgID, limit);
566  } // change log 2a, 2b
567  if (interval != defaults.NO_VALUE_SET) {
568  dest_ctrl->setInterval(msgID, interval);
569  } // change log 6
570  if (timespan != defaults.NO_VALUE_SET) {
571  if (timespan < 0)
572  timespan = 2000000000;
573  dest_ctrl->setTimespan(msgID, timespan);
574  } // change log 2a, 2b
575 
576  } // for
577 
578  // establish this destination's limit for each severity:
579  for (vString::const_iterator sev_it = severities.begin(); sev_it != severities.end(); ++sev_it) {
580  std::string sevID = *sev_it;
581  ELseverityLevel severity(sevID);
582  edm::ParameterSet default_sev_pset = getAparameter<edm::ParameterSet>(default_pset, sevID, empty_PSet);
583  edm::ParameterSet sev_pset = getAparameter<edm::ParameterSet>(dest_pset, sevID, default_sev_pset);
584  // change log 5
585  int limit = getAparameter<int>(sev_pset, "limit", defaults.NO_VALUE_SET);
586  if (limit == defaults.NO_VALUE_SET) { // change log 24
587  limit = m_messageLoggerDefaults->sev_limit(filename, sevID);
588  }
589  if (limit != defaults.NO_VALUE_SET) {
590  if (limit < 0)
591  limit = 2000000000; // change log 38
592  dest_ctrl->setLimit(severity, limit);
593  }
594  int interval = getAparameter<int>(sev_pset, "reportEvery", defaults.NO_VALUE_SET);
595  if (interval == defaults.NO_VALUE_SET) { // change log 24
596  interval = m_messageLoggerDefaults->sev_reportEvery(filename, sevID);
597  }
598  if (interval != defaults.NO_VALUE_SET)
599  dest_ctrl->setInterval(severity, interval);
600  // change log 2
601  int timespan = getAparameter<int>(sev_pset, "timespan", defaults.NO_VALUE_SET);
602  if (timespan == defaults.NO_VALUE_SET) { // change log 24
603  timespan = m_messageLoggerDefaults->sev_timespan(filename, sevID);
604  }
605  if (timespan != defaults.NO_VALUE_SET) {
606  if (timespan < 0)
607  timespan = 2000000000; // change log 38
608  dest_ctrl->setTimespan(severity, timespan);
609  }
610  } // for
611 
612  // establish this destination's linebreak policy:
613  // change log 5
614  bool noLineBreaks = getAparameter<bool>(dest_pset, "noLineBreaks", defaults.noLineBreaks_);
615  if (noLineBreaks) {
616  dest_ctrl->setLineLength(32000);
617  } else {
618  // change log 5
619  int lineLen = getAparameter<int>(dest_pset, "lineLength", defaults.lineLength_);
620  dest_ctrl->setLineLength(lineLen);
621  }
622 
623  // if indicated, suppress time stamps in this destination's output
624  bool suppressTime = getAparameter<bool>(dest_pset, "noTimeStamps", defaults.noTimeStamps_);
625  if (suppressTime) {
626  dest_ctrl->suppressTime();
627  }
628 
629  } // ThreadSafeLogMessageLoggerScribe::configure_dest()
630 
632  edm::ParameterSet const& job_pset, ConfigurableDefaults const& defaults, vString const& categories) {
633  vString const empty_vString;
634  std::string const empty_String;
635  edm::ParameterSet const empty_PSet;
636 
637  // Initialize unversal suppression variables
642 
643  // grab list of destinations:
644  vString destinations = getAparameter<vString>(job_pset, "destinations", empty_vString);
645 
646  // Use the default list of destinations if and only if the grabbed list is
647  // empty // change log 24
648  if (destinations.empty()) {
649  destinations = m_messageLoggerDefaults->destinations;
650  }
651 
652  // dial down the early destination if other dest's are supplied:
653  if (!destinations.empty())
654  m_early_dest->setThreshold(ELhighestSeverity);
655 
656  // establish each destination:
657  std::vector<std::string> ordinary_destination_filenames;
658  for (vString::const_iterator it = destinations.begin(); it != destinations.end(); ++it) {
659  std::string filename = *it;
660  const std::string& psetname = filename;
661 
662  // check that this destination is not just a placeholder // change log 11
663  edm::ParameterSet dest_pset = getAparameter<edm::ParameterSet>(job_pset, psetname, empty_PSet);
664  bool is_placeholder = getAparameter<bool>(dest_pset, "placeholder", false);
665  if (is_placeholder)
666  continue;
667 
668  // Modify the file name if extension or name is explicitly specified
669  // change log 14
670 
671  // Although for an ordinary destination there is no output attribute
672  // for the cfg (you can use filename instead) we provide output() for
673  // uniformity with the statistics destinations. The "right way" to
674  // work this would have been to provide a filename() method, along with
675  // an extension() method. We recognize the potential name confusion here
676  // (filename(filename))!
677 
678  auto const actual_filename = destinationFileName(dest_pset, psetname);
679 
680  // Check that this is not a duplicate name // change log 18
681  if (m_stream_ps.find(actual_filename) != m_stream_ps.end()) {
682  if (m_clean_slate_configuration) { // change log 22
683  // throw edm::Exception ( edm::errors::Configuration )
684  LogError("duplicateDestination") // change log 35
685  << "Duplicate name for a MessageLogger Destination: " << actual_filename << "\n"
686  << "Only the first configuration instructions are used";
687  continue;
688  } else {
689  LogWarning("duplicateDestination")
690  << "Duplicate name for a MessageLogger Destination: " << actual_filename << "\n"
691  << "Only original configuration instructions are used";
692  continue;
693  }
694  }
695 
696  ordinary_destination_filenames.push_back(actual_filename);
697 
698  // attach the current destination, keeping a control handle to it:
699  std::shared_ptr<ELdestination> dest_ctrl = makeDestinationCtrl(actual_filename);
700  // now configure this destination:
701  configure_dest(job_pset, defaults, categories, dest_ctrl, dest_pset, psetname);
702 
703  } // for [it = destinations.begin() to end()]
704 
705  return ordinary_destination_filenames;
706  } // configure_ordinary_destinations
707 
710  vString const& categories,
711  edm::ParameterSet const& stat_pset,
712  std::string const& psetname,
713  std::string const& filename) {
714  auto os_p = m_stream_ps[filename];
715 
716  auto stat = std::make_shared<ELstatistics>(*os_p);
717  m_admin_p->attach(stat);
718  m_statisticsDestControls.push_back(stat);
719  bool reset = getAparameter<bool>(stat_pset, "resetStatistics", false);
720  if (not reset) {
721  //check for old syntax
722  reset = getAparameter<bool>(stat_pset, "reset", false);
723  }
724  m_statisticsResets.push_back(reset);
725 
726  // now configure this destination:
727  configure_dest(job_pset, defaults, categories, stat, stat_pset, psetname);
728 
729  std::string dest_threshold = getAparameter<std::string>(stat_pset, "statisticsThreshold", std::string());
730  if (not dest_threshold.empty()) {
731  ELseverityLevel threshold_sev(dest_threshold);
732  stat->setThreshold(threshold_sev);
733 
734  setGlobalThresholds(threshold_sev);
735  }
736 
737  // and suppress the desire to do an extra termination summary just because
738  // of end-of-job info messages
739  stat->noTerminationSummary();
740  }
741 
744  vString const& categories,
745  vString const& ordinary_destination_filenames) {
746  vString const empty_vString;
747  std::string const empty_String;
748  edm::ParameterSet const empty_PSet;
749 
750  // grab list of statistics destinations:
751  vString statistics = getAparameter<vString>(job_pset, "statistics", empty_vString);
752 
753  bool no_statistics_configured = statistics.empty(); // change log 24
754 
755  if (no_statistics_configured) {
756  // Read the list of staistics destinations from hardwired defaults,
757  // but only if there is also no list of ordinary destinations.
758  // (If a cfg specifies destinations, and no statistics, assume that
759  // is what the user wants.)
760  vString destinations = getAparameter<vString>(job_pset, "destinations", empty_vString);
761  if (destinations.empty()) {
762  statistics = m_messageLoggerDefaults->statistics;
763  no_statistics_configured = statistics.empty();
764  } else {
765  for (auto const& dest : destinations) {
766  edm::ParameterSet stat_pset = getAparameter<edm::ParameterSet>(job_pset, dest, empty_PSet);
767  if (getAparameter<bool>(stat_pset, "enableStatistics", false)) {
768  statistics.push_back(dest);
769  }
770  }
771  }
772  }
773 
774  // establish each statistics destination:
775  for (auto const& psetname : statistics) {
776  // check that this destination is not just a placeholder // change log 20
777  edm::ParameterSet stat_pset = getAparameter<edm::ParameterSet>(job_pset, psetname, empty_PSet);
778  bool is_placeholder = getAparameter<bool>(stat_pset, "placeholder", false);
779  if (is_placeholder)
780  continue;
781 
782  // Determine the destination file name
783  std::string filename = getAparameter<std::string>(stat_pset, "output", empty_String);
784  if (filename == empty_String) {
785  filename = m_messageLoggerDefaults->output(psetname); // change log 31
786  if (filename == empty_String) {
787  filename = psetname;
788  }
789  }
790 
791  // Modify the file name if extension or name is explicitly specified
792  // change log 14 -- probably suspenders and a belt, because ouput option
793  // is present, but uniformity is nice.
794 
795  std::string explicit_filename = getAparameter<std::string>(stat_pset, "filename", filename);
796  if (explicit_filename != empty_String)
797  filename = explicit_filename;
798  std::string explicit_extension = getAparameter<std::string>(stat_pset, "extension", empty_String);
799  if (explicit_extension != empty_String) {
800  if (explicit_extension[0] == '.') {
801  filename += explicit_extension;
802  } else {
803  filename = filename + "." + explicit_extension;
804  }
805  }
806 
807  // Attach a default extension of .log if there is no extension on a file
808  // change log 18 - this had been done in concert with attaching destination
809 
810  std::string actual_filename = filename; // change log 4
811  if ((filename != "cout") && (filename != "cerr")) { // change log 23
812  const std::string::size_type npos = std::string::npos;
813  if (filename.find('.') == npos) {
814  actual_filename += ".log";
815  }
816  }
817 
818  // Check that this is not a duplicate name -
819  // unless it is an ordinary destination (which stats can share)
820  if (!search_all(ordinary_destination_filenames, actual_filename)) {
821  if (m_stream_ps.find(actual_filename) != m_stream_ps.end()) {
822  if (m_clean_slate_configuration) { // change log 22
824  << "Duplicate name for a MessageLogger Statistics Destination: " << actual_filename << "\n";
825  } else {
826  LogWarning("duplicateDestination")
827  << "Duplicate name for a MessageLogger Statistics Destination: " << actual_filename << "\n"
828  << "Only original configuration instructions are used";
829  continue;
830  }
831  }
832  }
833 
834  // create (if statistics file does not match any destination file name)
835  // or note (if statistics file matches a destination file name) the ostream.
836  // But if no statistics destinations were provided in the config, do not
837  // create a new destination for this hardwired statistics - only act if
838  // it is matches a destination. (shange log 24)
839  bool statistics_destination_is_real = !no_statistics_configured;
840  std::ostream* os_p;
841  if (m_stream_ps.find(actual_filename) == m_stream_ps.end()) {
842  if (actual_filename == "cout") {
843  os_p = &std::cout;
844  } else if (actual_filename == "cerr") {
845  os_p = &std::cerr;
846  } else {
847  auto os_sp = std::make_shared<std::ofstream>(actual_filename.c_str());
848  m_file_ps.push_back(os_sp);
849  os_p = os_sp.get();
850  }
851  m_stream_ps[actual_filename] = os_p;
852  } else {
853  statistics_destination_is_real = true; // change log 24
854  }
855 
856  if (statistics_destination_is_real) { // change log 24
857  // attach the statistics destination, keeping a control handle to it:
858 
859  configure_statistics_dest(job_pset, defaults, categories, stat_pset, psetname, actual_filename);
860  }
861 
862  } // for [it = statistics.begin() to end()]
863 
864  } // configure_statistics
865 
866  void ThreadSafeLogMessageLoggerScribe::parseCategories(std::string const& s, std::vector<std::string>& cats) {
867  const std::string::size_type npos = std::string::npos;
869  while (i != npos) {
870  std::string::size_type j = s.find('|', i);
871  cats.push_back(s.substr(i, j - i));
872  i = j;
873  while ((i != npos) && (s[i] == '|'))
874  ++i;
875  // the above handles cases of || and also | at end of string
876  }
877  // Note: This algorithm assigns, as desired, one null category if it
878  // encounters an empty categories string
879  }
880 
883  for (unsigned int i = 0; i != m_statisticsDestControls.size(); ++i) {
885  if (m_statisticsResets[i])
886  m_statisticsDestControls[i]->wipe();
887  }
888  auto dropped = m_tooManyWaitingMessagesCount.load();
889  if (m_statisticsDestControls.empty() and dropped != 0) {
890  if (m_stream_ps.find("cerr") != m_stream_ps.end()) {
891  std::cerr << "MessageLogger: dropped waiting message count " << dropped << "\n";
892  }
893  if (m_stream_ps.find("cout") != m_stream_ps.end()) {
894  std::cout << "MessageLogger: dropped waiting message count " << dropped << "\n";
895  }
896  }
897  }
898 
899  void ThreadSafeLogMessageLoggerScribe::triggerFJRmessageSummary(std::map<std::string, double>& sm) // ChangeLog 29
900  {
901  if (m_statisticsDestControls.empty()) {
902  sm["NoStatisticsDestinationsConfigured"] = 0.0;
903  } else {
904  m_statisticsDestControls[0]->summaryForJobReport(sm);
905  }
906  }
907 
908  namespace {
911 
912  topDesc.addUntracked<bool>("messageSummaryToJobReport", false);
913  topDesc.addUntracked<std::string>("generate_preconfiguration_message", "");
914  topDesc.addUntracked<unsigned int>("waiting_threshold", 100);
915  topDesc.addUntracked<std::vector<std::string>>("suppressDebug", {});
916  topDesc.addUntracked<std::vector<std::string>>("suppressInfo", {});
917  topDesc.addUntracked<std::vector<std::string>>("suppressFwkInfo", {});
918  topDesc.addUntracked<std::vector<std::string>>("suppressWarning", {});
919  topDesc.addUntracked<std::vector<std::string>>("suppressError", {});
920  topDesc.addUntracked<std::vector<std::string>>("debugModules", {});
921 
923  category.addUntracked<int>("reportEvery", 1);
925  ->setComment(
926  "Set a limit on the number of messages of this category. The default value is used to denote no "
927  "limit.");
928  category.addOptionalUntracked<int>("timespan");
929 
930  edm::ParameterSetDescription destination_base;
931  destination_base.addOptionalUntracked<bool>("noLineBreaks");
932  destination_base.addOptionalUntracked<bool>("noTimeStamps");
933  destination_base.addOptionalUntracked<int>("lineLength");
934  destination_base.addOptionalUntracked<std::string>("threshold");
935  destination_base.addOptionalUntracked<std::string>("statisticsThreshold");
936 
938  catnode.setComment("Specialize either a category or any of 'DEBUG', 'INFO', 'FWKINFO', 'WARNING' or 'ERROR'");
939  destination_base.addNode(catnode);
940 
941  edm::ParameterSetDescription destination_noStats(destination_base);
942  destination_noStats.addUntracked<bool>("enableStatistics", false);
943  destination_noStats.addUntracked<bool>("resetStatistics", false);
944 
945  {
946  edm::ParameterSetDescription default_pset;
947  default_pset.addUntracked<int>("reportEvery", 1);
949  ->setComment(
950  "Set a limit on the number of messages of this category. The default value is used to denote no "
951  "limit.");
952  default_pset.addOptionalUntracked<int>("timespan");
953  default_pset.addUntracked<bool>("noLineBreaks", false);
954  default_pset.addUntracked<bool>("noTimeStamps", false);
955  default_pset.addUntracked<int>("lineLength", 80);
956  default_pset.addUntracked<std::string>("threshold", "INFO");
957  default_pset.addUntracked<std::string>("statisticsThreshold", "INFO");
958  default_pset.addNode(catnode);
959 
960  edm::ParameterSetDescription cerr_destination(destination_base);
961  cerr_destination.addUntracked<bool>("enableStatistics", true);
962  cerr_destination.addUntracked<bool>("resetStatistics", false);
963  cerr_destination.addUntracked<bool>("enable", true);
964 
965  edm::ParameterSetDescription cout_destination(destination_noStats);
966  cout_destination.addUntracked<bool>("enable", false);
967 
968  edm::ParameterSetDescription fileDestination(destination_noStats);
969 
970  fileDestination.addOptionalUntracked<std::string>("output");
971  fileDestination.addOptionalUntracked<std::string>("filename");
972  fileDestination.addOptionalUntracked<std::string>("extension");
975  "*", edm::RequireZeroOrMore, false, fileDestination);
976  files.addNode(fileWildcard);
977 
978  std::map<std::string, edm::ParameterSetDescription> standards = {
979  {"cerr", cerr_destination}, {"cout", cout_destination}, {"default", default_pset}, {"files", files}};
980 
982  topDesc.addNode(psets);
983  }
984 
985  config.addDefault(topDesc);
986  }
987  } // namespace
988 
990  // See if old config API is being used
991  if (usingOldConfig(pset))
992  return;
993  if (not pset.exists("files") and
994  ((pset.exists("destinations") or pset.existsAs<std::vector<std::string>>("statistics", true) or
995  pset.existsAs<std::vector<std::string>>("statistics", false) or pset.exists("categories")))) {
996  return;
997  }
998 
999  ConfigurationDescriptions config{"MessageLogger", "MessageLogger"};
1001 
1002  config.validate(pset, "MessageLogger");
1003  }
1004 
1005  } // end of namespace service
1006 } // end of namespace edm
void runCommand(MessageLoggerQ::OpCode opcode, void *operand) override
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
std::string destinationFileName(edm::ParameterSet const &, std::string const &) const
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
Definition: config.py:1
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
constexpr const ELseverityLevel ELhighestSeverity
uint16_t size_type
void triggerFJRmessageSummary(std::map< std::string, double > &sm)
static bool debugAlwaysSuppressed
Definition: MessageDrop.h:71
T getUntrackedParameter(std::string const &, T const &) const
std::vector< edm::propagate_const< std::shared_ptr< std::ofstream > > > m_file_ps
oneapi::tbb::concurrent_queue< ErrorObj * > m_waitingMessages
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
static ConfigurableDefaults parseDefaults(edm::ParameterSet const &job_pset)
void configure_statistics_dest(edm::ParameterSet const &job_pset, ConfigurableDefaults const &defaults, vString const &categories, edm::ParameterSet const &stat_pset, std::string const &psetname, std::string const &filename)
const ELextendedID & xid() const
Definition: ErrorObj.cc:142
static void noteGroupedCategory(std::string const &cat)
std::map< std::string, edm::propagate_const< std::ostream * > > m_stream_ps
static bool warningAlwaysSuppressed
Definition: MessageDrop.h:74
edm::propagate_const< std::shared_ptr< ELadministrator > > m_admin_p
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::string id
Definition: ELextendedID.h:29
std::vector< std::shared_ptr< ELstatistics > > m_statisticsDestControls
bool search_all(ForwardSequence const &s, Datum const &d)
Definition: Algorithms.h:36
static edm::JobMode mode(std::string const &jm)
constexpr const ELseverityLevel ELzeroSeverity
static bool fwkInfoAlwaysSuppressed
Definition: MessageDrop.h:73
HLT enums.
JobMode
Definition: JobMode.h:15
Func copy_all(ForwardSequence &s, Func f)
wrappers for copy
Definition: Algorithms.h:20
std::vector< std::string > configure_ordinary_destinations(edm::ParameterSet const &, ConfigurableDefaults const &defaults, vString const &categories)
virtual void setID(std::string_view ID)
Definition: ErrorObj.cc:169
void parseCategories(std::string const &s, std::vector< std::string > &cats)
void configure_statistics(edm::ParameterSet const &, ConfigurableDefaults const &defaults, vString const &categories, std::vector< std::string > const &destination_names)
ParameterDescriptionBase * addOptionalUntracked(U const &iLabel, T const &value)
std::shared_ptr< ELdestination > makeDestinationCtrl(std::string const &filename)
Log< level::Warning, false > LogWarning
void configure_dest(edm::ParameterSet const &job_pset, ConfigurableDefaults const &, vString const &categories, std::shared_ptr< ELdestination > dest_ctrl, edm::ParameterSet const &dest_pset, std::string const &filename)
static bool infoAlwaysSuppressed
Definition: MessageDrop.h:72
void reset(double vett[256])
Definition: TPedValues.cc:11
def move(src, dest)
Definition: eostools.py:511