ATLAS Offline Software
LoggedMessageSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 #include "GaudiKernel/Kernel.h"
7 #include "GaudiKernel/StatusCode.h"
8 #include "GaudiKernel/Message.h"
9 #include "LoggedMessageSvc.h"
10 
11 #include <sstream>
12 #include <iostream>
13 #include <fstream>
14 #include <utility>
15 #include <cstdlib>
16 
17 using namespace std;
18 
19 static const std::string levelNames[MSG::NUM_LEVELS] = {"NIL", "VERBOSE", "DEBUG", "INFO",
20  "WARNING", "ERROR", "FATAL", "ALWAYS"};
21 
22 // Constructor
23 LoggedMessageSvc::LoggedMessageSvc( const std::string& name, ISvcLocator* svcloc )
24  : base_class( name, svcloc ), m_keysUsed(false)
25  {
26  m_defaultStream = &std::cout;
27  m_outputLevel = MSG::INFO;
28  declareProperty( "Format", m_defaultFormat = Message::getDefaultFormat() );
29  declareProperty( "timeFormat", m_defaultTimeFormat = Message::getDefaultTimeFormat() );
30  declareProperty( "showStats", m_stats = false );
31  declareProperty( "statLevel", m_statLevel = 0 );
32 
33  // Special properties to control output level of individual sources
34  declareProperty( "setVerbose", m_thresholdProp[MSG::VERBOSE] );
35  declareProperty( "setDebug", m_thresholdProp[MSG::DEBUG] );
36  declareProperty( "setInfo", m_thresholdProp[MSG::INFO] );
37  declareProperty( "setWarning", m_thresholdProp[MSG::WARNING] );
38  declareProperty( "setError", m_thresholdProp[MSG::ERROR] );
39  declareProperty( "setFatal", m_thresholdProp[MSG::FATAL] );
40  declareProperty( "setAlways", m_thresholdProp[MSG::ALWAYS] );
41 
42  declareProperty( "useColors", m_color=false);
43  m_color.declareUpdateHandler(&LoggedMessageSvc::initColors, this);
44 
45  declareProperty( "fatalColorCode", m_logColors[MSG::FATAL] );
46  declareProperty( "errorColorCode", m_logColors[MSG::ERROR] );
47  declareProperty( "warningColorCode", m_logColors[MSG::WARNING] );
48  declareProperty( "infoColorCode", m_logColors[MSG::INFO] );
49  declareProperty( "debugColorCode", m_logColors[MSG::DEBUG] );
50  declareProperty( "verboseColorCode", m_logColors[MSG::VERBOSE] );
51  declareProperty( "alwaysColorCode", m_logColors[MSG::ALWAYS] );
52 
53  const int defaultLimit = 500;
54  declareProperty( "fatalLimit", m_msgLimit[MSG::FATAL] = defaultLimit );
55  declareProperty( "errorLimit", m_msgLimit[MSG::ERROR] = defaultLimit );
56  declareProperty( "warningLimit", m_msgLimit[MSG::WARNING] = defaultLimit );
57  declareProperty( "infoLimit", m_msgLimit[MSG::INFO] = defaultLimit );
58  declareProperty( "debugLimit", m_msgLimit[MSG::DEBUG] = defaultLimit );
59  declareProperty( "verboseLimit", m_msgLimit[MSG::VERBOSE] = defaultLimit );
60  declareProperty( "alwaysLimit", m_msgLimit[MSG::ALWAYS] = 0 );
61 
62  declareProperty( "defaultLimit", m_msgLimit[MSG::NIL] = defaultLimit );
63 
64  declareProperty( "enableSuppression", m_suppress = false );
65  declareProperty( "countInactive", m_inactCount = false )->declareUpdateHandler( &LoggedMessageSvc::setupInactCount, this );
66 #ifndef NDEBUG
67  // initialize the MsgStream static flag.
68  MsgStream::enableCountInactive(m_inactCount);
69 #endif
70 
71  declareProperty( "loggingLevel", m_logLevel = MSG::FATAL, "Message level above which all messages are saved" );
72  m_logLevel.declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
73 
74  declareProperty( "keywords", m_keywords, "keywords to scan messages for and save");
75  m_keywords.declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
76 
77  declareProperty( "loggedStreams",
79  "MessageStream sources we want to dump into a logfile" );
80 
81  for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
82  m_logColors[ic].declareUpdateHandler(&LoggedMessageSvc::setupColors, this);
83  m_msgLimit[ic].declareUpdateHandler(&LoggedMessageSvc::setupLimits, this);
84  m_thresholdProp[ic].declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
85  }
86 
87  for (int i=0; i<MSG::NUM_LEVELS; ++i) {
88  m_msgCount[i] = 0;
89  }
90 
91 }
92 
93 //#############################################################################
94 
96 {
97  // closing log-files, if any
100  for ( ; iStream != endStream; ++iStream ) {
101  delete iStream->second;
102  iStream->second = nullptr;
103  }
104 }
105 //#############################################################################
106 
107 
110  StatusCode sc;
112  if( sc.isFailure() ) return sc;
113  // hack since in Gaudi v30, msgSvc() now returns a const SmartIF<IMessageSvc>
114  // Release pointer to myself done in Service base class
115  SmartIF<IMessageSvc> &si ATLAS_THREAD_SAFE = const_cast<SmartIF<IMessageSvc>&> (msgSvc());
116  si.reset();
117 
118 #ifdef _WIN32
119  m_color = false;
120 #endif
121 
122  m_colMap["black"] = MSG::BLACK;
123  m_colMap["red"] = MSG::RED;
124  m_colMap["green"] = MSG::GREEN;
125  m_colMap["yellow"] = MSG::YELLOW;
126  m_colMap["blue"] = MSG::BLUE;
127  m_colMap["purple"] = MSG::PURPLE;
128  m_colMap["cyan"] = MSG::CYAN;
129  m_colMap["white"] = MSG::WHITE;
130 
131  // make sure the map of logged stream names is initialized
132  setupLogStreams();
133 
134  if (m_keywords.value().size() > 0) {
135  m_keysUsed = true;
136  }
137 
138  return StatusCode::SUCCESS;
139 }
140 
141 //#############################################################################
142 
145  m_state = Gaudi::StateMachine::OFFLINE;
146  return initialize();
147 }
148 
149 //#############################################################################
150 
151 void LoggedMessageSvc::initColors(Gaudi::Details::PropertyBase& /*prop*/) {
152 
153  if (m_color == true) {
154 
155  if (m_logColors[MSG::FATAL].value().size() == 0) {
156  vector<string> fatDef;
157  fatDef.push_back( "[94;101;1m" );
158  m_logColors[MSG::FATAL].set( fatDef );
159  } else {
161  }
162 
163  if (m_logColors[MSG::ERROR].value().size() == 0) {
164  vector<string> errDef;
165  errDef.push_back( "[97;101;1m" );
166  m_logColors[MSG::ERROR].set( errDef );
167  } else {
169  }
170 
171  if (m_logColors[MSG::WARNING].value().size() == 0) {
172  vector<string> warDef;
173  warDef.push_back( "[93;1m" );
174  m_logColors[MSG::WARNING].set( warDef );
175  } else {
177  }
178 
179  } else {
180 
181  // reset all color codes;
182  for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
183  vector<string> def;
184  m_logColors[ic].set( def );
185  }
186 
187  }
188 
189 }
190 
191 //#############################################################################
192 
193 void LoggedMessageSvc::setupColors(Gaudi::Details::PropertyBase& prop) {
194 
195  if (! m_color) return;
196 
197  int ic;
198  if (prop.name() == "fatalColorCode") {
199  ic = MSG::FATAL;
200  } else if (prop.name() == "errorColorCode") {
201  ic = MSG::ERROR;
202  } else if (prop.name() == "warningColorCode") {
203  ic = MSG::WARNING;
204  } else if (prop.name() == "infoColorCode") {
205  ic = MSG::INFO;
206  } else if (prop.name() == "debugColorCode") {
207  ic = MSG::DEBUG;
208  } else if (prop.name() == "verboseColorCode") {
209  ic = MSG::VERBOSE;
210  } else if (prop.name() == "alwaysColorCode") {
211  ic = MSG::ALWAYS;
212  } else {
213  cout << "ERROR: Unknown message color parameter: " << prop.name()
214  << endl;
215  return;
216  }
217 
218  string code;
219  vector<string>::const_iterator itr;
220  itr = m_logColors[ic].value().begin();
221 
222  if ( m_logColors[ic].value().size() == 1 ) {
223 
224  if (itr->empty() ) {
225  code = "";
226  } else if ((*itr)[0] == '[') {
227  code = "\033" + *itr;
228  } else {
229  code = "\033[" + colTrans(*itr, 90) + ";1m";
230  }
231 
232  } else if (m_logColors[ic].value().size() == 2) {
233  vector<string>::const_iterator itr2 = itr + 1;
234 
235  code = "\033[" + colTrans(*itr, 90) + ";"
236  + colTrans(*itr2, 100) + ";1m";
237 
238  }
239 
240  m_logColorCodes[ic] = std::move(code);
241 
242 }
243 //#############################################################################
244 
245 void LoggedMessageSvc::setupLimits(Gaudi::Details::PropertyBase& prop) {
246 
247  //int ic = 0;
248  if (prop.name() == "fatalLimit") {
249  //ic = MSG::FATAL;
250  } else if (prop.name() == "errorLimit") {
251  //ic = MSG::ERROR;
252  } else if (prop.name() == "warningLimit") {
253  //ic = MSG::WARNING;
254  } else if (prop.name() == "infoLimit") {
255  //ic = MSG::INFO;
256  } else if (prop.name() == "debugLimit") {
257  //ic = MSG::DEBUG;
258  } else if (prop.name() == "verboseLimit") {
259  //ic = MSG::VERBOSE;
260  } else if (prop.name() == "alwaysLimit") {
261  IntegerProperty *p = dynamic_cast<IntegerProperty*>(&prop);
262  if (p && p->value() != 0) {
263  cout << "LoggedMessageSvc ERROR: cannot suppress ALWAYS messages" << endl;
264  p->setValue(0);
265  }
266  //ic = MSG::ALWAYS;
267  } else if (prop.name() == "defaultLimit") {
268  for (int i = MSG::VERBOSE; i< MSG::NUM_LEVELS; ++i) {
269  if (i != MSG::ALWAYS) {
270  m_msgLimit[i] = m_msgLimit[MSG::NIL].value();
271  }
272  }
273  } else {
274  cout << "LoggedMessageSvc ERROR: Unknown message limit parameter: "
275  << prop.name() << endl;
276  return;
277  }
278 
279 }
280 //#############################################################################
281 
282 void LoggedMessageSvc::setupThreshold(Gaudi::Details::PropertyBase& prop) {
283 
284  int ic = 0;
285  if (prop.name() == "setFatal") {
286  ic = MSG::FATAL;
287  } else if (prop.name() == "setError") {
288  ic = MSG::ERROR;
289  } else if (prop.name() == "setWarning") {
290  ic = MSG::WARNING;
291  } else if (prop.name() == "setInfo") {
292  ic = MSG::INFO;
293  } else if (prop.name() == "setDebug") {
294  ic = MSG::DEBUG;
295  } else if (prop.name() == "setVerbose") {
296  ic = MSG::VERBOSE;
297  } else if (prop.name() == "setAlways") {
298  ic = MSG::ALWAYS;
299  } else if (prop.name() == "loggingLevel") {
300  IntegerProperty *iap = dynamic_cast<IntegerProperty*>( &prop );
301  if (iap)
302  m_logLevel = iap->value();
303  return;
304  } else if (prop.name() == "keywords") {
305  StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop );
306  if (sap!= nullptr && sap->value().size() > 0) {
307  m_keysUsed = true;
308  } else {
309  m_keysUsed = false;
310  }
311  return;
312  } else {
313  cerr << "LoggedMessageSvc ERROR: Unknown message theshold parameter: "
314  << prop.name() << endl;
315  return;
316  }
317 
318  StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop);
319  if (sap == nullptr) {
320  std::cerr << "could not dcast " << prop.name()
321  << " to a StringArrayProperty (which it should be!)" << endl;
322  return;
323  } else {
324  std::vector<std::string>::const_iterator itr;
325  for ( itr = sap->value().begin();
326  itr != sap->value().end();
327  ++itr) {
328  setOutputLevel( *itr, ic );
329  }
330  }
331 
332 }
333 
334 //#############################################################################
335 
336 void LoggedMessageSvc::setupInactCount(Gaudi::Details::PropertyBase& prop) {
337  if (prop.name() == "countInactive") {
338 #ifndef NDEBUG
339  BooleanProperty *p = dynamic_cast<BooleanProperty*>(&prop);
340  if (p)
341  MsgStream::enableCountInactive(p->value());
342 #endif
343  }
344 }
345 
346 //#############################################################################
349 
350  m_suppress = false;
351 
352  std::ostringstream os;
353 
354  if (m_stats) {
355  os << "Summarizing all message counts" << endl;
356  } else {
357  os << "Listing sources of suppressed message: " << endl;
358  }
359 
360  os << "=====================================================" << endl;
361  os << " Message Source | Level | Count" << endl;
362  os << "-----------------------------+---------+-------------" << endl;
363 
364 
365  bool found(false);
366 
367  std::lock_guard<std::mutex> lock(m_reportMutex);
368  std::map<std::string,MsgAry>::const_iterator itr;
369  for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
370  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
371  if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
372  (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
373  os << " ";
374  os.width(28);
375  os.setf(ios_base::left,ios_base::adjustfield);
376  os << itr->first;
377 
378  os << "|";
379 
380  os.width(8);
381  os.setf(ios_base::right,ios_base::adjustfield);
382  os << levelNames[ic];
383 
384  os << " |";
385 
386  os.width(9);
387  os << itr->second.msg[ic];
388 
389  os << endl;
390 
391  found = true;
392  }
393  }
394  }
395  os << "=====================================================" << endl;
396 
397  if (found || m_stats) {
398  cout << os.str();
399  }
400 
401 
402 #ifndef NDEBUG
403  if (m_inactCount.value()) {
404 
405  std::ostringstream os;
406  os << "Listing sources of Unprotected and Unseen messages\n";
407 
408  bool found(false);
409 
410  unsigned int ml(0);
411  std::map<std::string,MsgAry>::const_iterator itr;
412  for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
413  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
414  if (itr->second.msg[ic] != 0) {
415  if (itr->first.length() > ml) { ml = itr->first.length(); }
416  }
417  }
418  }
419 
420  for (unsigned int i=0; i<ml+25; ++i) {
421  os << "=";
422  }
423 
424  os << endl << " ";
425  os.width(ml+2);
426  os.setf(ios_base::left,ios_base::adjustfield);
427  os << "Message Source";
428  os.width(1);
429  os << "| Level | Count" << endl;
430 
431  for (unsigned int i=0; i<ml+3; ++i) {
432  os << "-";
433  }
434  os << "+---------+-----------" << endl;
435 
436 
437  for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
438  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
439  if (itr->second.msg[ic] != 0) {
440  os << " ";
441  os.width(ml+2);
442  os.setf(ios_base::left,ios_base::adjustfield);
443  os << itr->first;
444 
445  os << "|";
446 
447  os.width(8);
448  os.setf(ios_base::right,ios_base::adjustfield);
449  os << levelNames[ic];
450 
451  os << " |";
452 
453  os.width(9);
454  os << itr->second.msg[ic];
455 
456  os << endl;
457 
458  found = true;
459  }
460  }
461  }
462  for (unsigned int i=0; i<ml+25; ++i) {
463  os << "=";
464  }
465  os << endl;
466 
467  if (found) {
468  cout << os.str();
469  }
470  }
471 #endif
472 
473  return StatusCode::SUCCESS;
474 }
475 
476 //#############################################################################
477 std::string LoggedMessageSvc::colTrans(const std::string &col, int offset) {
478  ColorMap::const_iterator itr = m_colMap.find(col);
479  int icol;
480  if (itr != m_colMap.end()) {
481  icol = offset + itr->second;
482  } else {
483  icol = offset + 8;
484  }
485  std::ostringstream os1;
486 
487  os1 << icol;
488 
489  return os1.str();
490 
491 }
492 
493 //#############################################################################
494 // ---------------------------------------------------------------------------
495 // Routine: reportMessage
496 // Purpose: dispatches a message to the relevant streams.
497 // ---------------------------------------------------------------------------
498 //
499 
501  std::lock_guard<std::mutex> lock(m_reportMutex);
502 
503  int key = msg.getType();
504  int nmsg;
505 
506  m_msgCount[key] ++;
507 
508  if (outputLevel >= m_logLevel) {
509  m_msgLog[ outputLevel ].push_back( make_pair (msg.getSource(), msg.getMessage() ) );
510  }
511 
512  if (m_keysUsed) {
513  if (msg.getSource() != "AthenaSummarySvc") {
514  for (vector<string>::const_iterator itr=m_keywords.value().begin(); itr!= m_keywords.value().end(); ++itr) {
515  if (msg.getMessage().find( *itr ) != string::npos) {
516  m_msgKeyLog.push_back( LoggedMessage( outputLevel, msg.getSource(), msg.getMessage() ));
517  break;
518  }
519  }
520  }
521  }
522 
523  const Message *cmsg = &msg;
524  std::unique_ptr<Message> suppressed_msg;
525 
526  // processing logged streams
527  if ( !m_loggedStreams.empty() ) {
528  const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
529  if ( m_loggedStreams.end() != iLog ) {
530  (*iLog->second) << *cmsg << std::endl;
531  }
532  }
533 
534  if ( m_suppress.value() || m_stats.value() ) {
535 
537  m_sourceMap.find(msg.getSource());
538  if (itr != m_sourceMap.end()) {
539  itr->second.msg[key] += 1;
540  nmsg = itr->second.msg[key];
541  } else {
542  MsgAry A;
543  for (int i=0; i<MSG::NUM_LEVELS; ++i) {
544  A.msg[i] = 0;
545  }
546  A.msg[key] = 1;
547  m_sourceMap[msg.getSource()] = A;
548  nmsg = 1;
549  }
550 
551  if (m_suppress.value()) {
552 
553  if ( m_msgLimit[key] != 0 ) {
554  if (nmsg == m_msgLimit[key]) {
555  std::string str = levelNames[key] + " message limit (";
557  str += ") reached for ";
558  str += msg.getSource() + ". Suppressing further output.";
559  suppressed_msg = std::make_unique<Message>(msg.getSource(),MSG::WARNING,str);
560  suppressed_msg->setFormat(msg.getFormat());
561  cmsg = suppressed_msg.get();
562  } else if (nmsg > m_msgLimit[key]) {
563  return;
564  }
565  }
566  }
567 
568  }
569 
570  StreamMap::const_iterator first = m_streamMap.lower_bound( key );
571  if ( first != m_streamMap.end() ) {
572  StreamMap::const_iterator last = m_streamMap.upper_bound( key );
573  while( first != last ) {
574  std::ostream& stream = *( (*first).second.second );
575  stream << *cmsg << std::endl;
576  ++first;
577  }
578  }
579  else if ( key >= outputLevel ) {
580  msg.setFormat(m_defaultFormat);
581  msg.setTimeFormat(m_defaultTimeFormat);
582  if (!m_color) {
583  (*m_defaultStream) << *cmsg << std::endl << std::flush;
584  } else {
585  (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
586  << std::endl << std::flush;
587  }
588  }
589 }
590 
591 //#############################################################################
592 // ---------------------------------------------------------------------------
593 // Routine: reportMessage
594 // Purpose: dispatches a message to the relevant streams.
595 // ---------------------------------------------------------------------------
596 //
598  reportMessage(msg, outputLevel(msg.getSource()));
599 }
600 
601 //#############################################################################
602 // ---------------------------------------------------------------------------
603 // Routine: reportMessage
604 // Purpose: dispatches a message to the relevant streams.
605 // ---------------------------------------------------------------------------
606 //
608  int type,
609  std::string message) {
610  Message msg( std::move(source), type, std::move(message));
611  reportMessage( msg );
612 }
613 
614 //#############################################################################
615 // ---------------------------------------------------------------------------
616 // Routine: sendMessage
617 // Purpose: finds a message for a given status code and dispatches it.
618 // ---------------------------------------------------------------------------
619 //
620 
622  std::string_view source)
623 {
624  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
625 
626  MessageMap::const_iterator first = m_messageMap.lower_bound( key );
627  if ( first != m_messageMap.end() ) {
628  MessageMap::const_iterator last = m_messageMap.upper_bound( key );
629  while( first != last ) {
630  Message msg = (*first).second;
631  msg.setSource( source );
632  std::ostringstream os1;
633  os1 << "Status Code " << key.getCode() << std::ends;
634  Message stat_code1( std::string{source}, msg.getType(), os1.str() );
635  reportMessage( stat_code1 );
636  reportMessage( msg );
637  ++first;
638  }
639  }
640  else {
641  Message mesg = m_defaultMessage;
642  mesg.setSource( source );
643  std::ostringstream os2;
644  os2 << "Status Code " << key.getCode() << std::ends;
645  Message stat_code2( std::string{source}, mesg.getType(), os2.str() );
646  reportMessage( stat_code2 );
647  reportMessage( mesg );
648  }
649 }
650 
651 //#############################################################################
652 // ---------------------------------------------------------------------------
653 // Routine: insertStream
654 // Purpose: inserts a stream for a message type.
655 // ---------------------------------------------------------------------------
656 //
657 
659  std::string name,
660  std::ostream *stream)
661 {
662  typedef StreamMap::value_type value_type;
663  m_streamMap.insert( value_type( key, NamedStream( std::move(name), stream) ) );
664 }
665 
666 //#############################################################################
667 // ---------------------------------------------------------------------------
668 // Routine: eraseStream
669 // Purpose: erases all the streams for all the message types.
670 // ---------------------------------------------------------------------------
671 //
672 
674 {
675  m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
676 }
677 
678 //#############################################################################
679 // ---------------------------------------------------------------------------
680 // Routine: eraseStream
681 // Purpose: erases all the streams for a message type.
682 // ---------------------------------------------------------------------------
683 //
684 
685 void LoggedMessageSvc::eraseStream( int message_type )
686 {
687  m_streamMap.erase( message_type );
688 }
689 
690 //#############################################################################
691 // ---------------------------------------------------------------------------
692 // Routine: eraseStream
693 // Purpose: erases one stream for a message type.
694 // ---------------------------------------------------------------------------
695 //
696 
697 void LoggedMessageSvc::eraseStream( int key, std::ostream* stream ) {
698  if ( nullptr != stream ) {
699  bool changed = true;
700  while( changed ) {
701  changed = false;
702  StreamMap::iterator first = m_streamMap.lower_bound( key );
703  StreamMap::iterator last = m_streamMap.upper_bound( key );
704  while( first != last ) {
705  if ( (*first).second.second == stream ) {
706  m_streamMap.erase( first );
707  changed = true;
708  break;
709  }
710  }
711  }
712  }
713 }
714 
715 //#############################################################################
716 // ---------------------------------------------------------------------------
717 // Routine: eraseStream
718 // Purpose: erases one stream for all message types.
719 // ---------------------------------------------------------------------------
720 //
721 
722 void LoggedMessageSvc::eraseStream( std::ostream* stream ) {
723  if ( nullptr != stream ) {
724  bool changed = true;
725  while( changed ) {
726  changed = false;
728  while( first != m_streamMap.end() ) {
729  if ( (*first).second.second == stream ) {
730  m_streamMap.erase( first );
731  changed = true;
732  break;
733  }
734  }
735  }
736  }
737 }
738 
739 
740 //#############################################################################
741 // ---------------------------------------------------------------------------
742 // Routine: insertMessage
743 // Purpose: inserts a message for a status code.
744 // ---------------------------------------------------------------------------
745 //
746 
748 {
749  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
750 
751  m_messageMap.emplace( key, std::move( msg ) );
752 }
753 
754 //#############################################################################
755 // ---------------------------------------------------------------------------
756 // Routine: eraseMessage
757 // Purpose: erases all the messages for all the status codes.
758 // ---------------------------------------------------------------------------
759 //
760 
762 {
763  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
764 
765  m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
766 }
767 
768 //#############################################################################
769 // ---------------------------------------------------------------------------
770 // Routine: eraseMessage
771 // Purpose: erases all the messages for a status code.
772 // ---------------------------------------------------------------------------
773 //
774 
776 {
777  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
778 
779  m_messageMap.erase( key );
780 }
781 
782 //#############################################################################
783 // ---------------------------------------------------------------------------
784 // Routine: eraseMessage
785 // Purpose: erases one message for a status code.
786 // ---------------------------------------------------------------------------
787 //
788 
790 {
791  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
792 
793  bool changed = true;
794  while( changed ) {
795  changed = false;
796  MessageMap::iterator first = m_messageMap.lower_bound( key );
797  MessageMap::iterator last = m_messageMap.upper_bound( key );
798  while( first != last ) {
799  const Message& message = (*first).second;
800  if ( message == msg ) {
801  m_messageMap.erase( first );
802  changed = true;
803  break;
804  }
805  }
806  }
807 }
808 
809 // ---------------------------------------------------------------------------
811 // ---------------------------------------------------------------------------
812  return m_outputLevel;
813 }
814 // ---------------------------------------------------------------------------
815 int LoggedMessageSvc::outputLevel( std::string_view source ) const {
816 // ---------------------------------------------------------------------------
817  std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
818 
819  auto it = m_thresholdMap.find( source );
820  return it != m_thresholdMap.end() ? it->second : m_outputLevel.value();
821 }
822 
823 // ---------------------------------------------------------------------------
824 void LoggedMessageSvc::setOutputLevel(int new_level) {
825 // ---------------------------------------------------------------------------
826  m_outputLevel = new_level;
827 }
828 
829 // ---------------------------------------------------------------------------
830 void LoggedMessageSvc::setOutputLevel(std::string_view source, int level) {
831 // ---------------------------------------------------------------------------
832  std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
833 
834  // only write if we really have to...
835  auto i = m_thresholdMap.find( source );
836  if ( i == m_thresholdMap.end() ) {
837  m_thresholdMap.emplace( source, level );
838  } else if ( i->second != level ) {
839  i->second = level;
840  }
841 
842 }
843 
844 // ---------------------------------------------------------------------------
845 std::string LoggedMessageSvc::getLogColor(int logLevel) const {
846 // ---------------------------------------------------------------------------
847  if (logLevel < MSG::NUM_LEVELS) {
848  return m_logColorCodes[logLevel];
849  } else {
850  return "";
851  }
852 }
853 
854 // ---------------------------------------------------------------------------
856 
857  return m_msgCount[level];
858 
859 }
860 
861 // ---------------------------------------------------------------------------
862 void
864 
865  auto entry = m_inactiveMap.find( source );
866  if ( entry == m_inactiveMap.end() ) {
867  entry = m_inactiveMap.emplace( source, MsgAry{} ).first;
868  }
869  ++entry->second.msg[level];
870 }
871 
872 // ---------------------------------------------------------------------------
874 {
875  // reset state
876  for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
877  iLog != m_loggedStreams.end();
878  ++iLog ) {
879  delete iLog->second;
880  }
881  m_loggedStreams.clear();
882 
883  typedef std::map<std::string,std::string> StreamMap_t;
884  const StreamMap_t& streamMap = m_loggedStreamsName;
885  typedef StreamMap_t::const_iterator StreamMapIter;
886 
887  for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
888  iProp != iEnd;
889  ++iProp ) {
890 
891  const std::string sourceName = iProp->first;
892  const std::string outFileName = iProp->second;
893 
894  std::set<std::string> outFileNames;
895  for ( StreamMapIter jProp = streamMap.begin();
896  jProp != iEnd;
897  ++jProp ) {
898  if ( jProp->first != iProp->first ) {
899  outFileNames.insert( jProp->second );
900  }
901  }
902 
903  tee( sourceName, outFileName, outFileNames );
904 
905  }//> loop over property entries
906 
907  return;
908 }
909 
910 // ---------------------------------------------------------------------------
911 void LoggedMessageSvc::tee( const std::string& sourceName,
912  const std::string& outFileName,
913  const std::set<std::string>& outFileNames )
914 {
915  const std::ios_base::openmode openMode = std::ios_base::out |
916  std::ios_base::trunc;
917 
919  LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
920  if ( iStream != iEnd ) {
921  delete iStream->second;
922  iStream->second = nullptr;
923  m_loggedStreams.erase( iStream );
924  }
925 
926  // before creating a new ofstream, make sure there is no already existing
927  // one with the same file name...
928  iEnd = m_loggedStreams.end();
929  for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
930  if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
931  m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
932  return;
933  }
934  }
935 
936  std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
937 
938  if ( !out->good() ) {
939  out->close();
940  delete out;
941  return;
942  }
943 
944  m_loggedStreams[sourceName] = out;
945 
946  return;
947 }
948 
949 
950 //#############################################################################
951 // ---------------------------------------------------------------------------
952 // Routine: getMessages
953 // Purpose: get all messages of a certain MSG::Level
954 // ---------------------------------------------------------------------------
955 
956 std::vector< std::pair<std::string, std::string> >
958 {
959  std::lock_guard<std::mutex> lock(m_reportMutex);
960  return m_msgLog[ level ];
961 }
962 
963 
965  -> std::vector< LoggedMessage >
966 {
967  std::lock_guard<std::mutex> lock(m_reportMutex);
968  return m_msgKeyLog;
969 }
970 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
LoggedMessageSvc.h
LoggedMessageSvc::m_logColors
StringArrayProperty m_logColors[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:150
LoggedMessageSvc::insertStream
virtual void insertStream(int message_type, std::string name, std::ostream *stream) override
Definition: LoggedMessageSvc.cxx:658
LoggedMessageSvc::m_msgKeyLog
std::vector< LoggedMessage > m_msgKeyLog
Definition: LoggedMessageSvc.h:200
python.consts.BLACK
BLACK
Definition: consts.py:3
python.Constants.FATAL
int FATAL
Definition: Control/AthenaCommon/python/Constants.py:18
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:194
LoggedMessageSvc::finalize
virtual StatusCode finalize() override
Finalize Service.
Definition: LoggedMessageSvc.cxx:348
LoggedMessageSvc::m_colMap
ColorMap m_colMap
Definition: LoggedMessageSvc.h:170
LoggedMessageSvc::insertMessage
virtual void insertMessage(const StatusCode &code, Message message) override
Definition: LoggedMessageSvc.cxx:747
LoggedMessageSvc::m_color
BooleanProperty m_color
Definition: LoggedMessageSvc.h:147
LoggedMessageSvc::m_keysUsed
bool m_keysUsed
Definition: LoggedMessageSvc.h:201
LoggedMessageSvc::m_msgLog
std::vector< std::pair< std::string, std::string > > m_msgLog[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:199
LoggedMessageSvc::m_defaultMessage
Message m_defaultMessage
Default Message.
Definition: LoggedMessageSvc.h:140
initialize
void initialize()
Definition: run_EoverP.cxx:894
python.TrigPSCPythonDbSetup.logLevel
logLevel
If HLT PSK is set on command line read it from DB instead of COOL (ATR-25974)
Definition: TrigPSCPythonDbSetup.py:27
skel.it
it
Definition: skel.GENtoEVGEN.py:407
LoggedMessageSvc::initColors
void initColors(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:151
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
LoggedMessageSvc::outputLevel
virtual int outputLevel() const override
Definition: LoggedMessageSvc.cxx:810
athena.value
value
Definition: athena.py:124
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
LoggedMessageSvc::incrInactiveCount
virtual void incrInactiveCount(MSG::Level level, std::string_view src) override
Definition: LoggedMessageSvc.cxx:863
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
LoggedMessageSvc::m_loggedStreams
LoggedStreamsMap_t m_loggedStreams
Definition: LoggedMessageSvc.h:176
LoggedMessageSvc::MsgAry
Private helper class to keep the count of messages of a type (MSG::LEVEL).
Definition: LoggedMessageSvc.h:158
ReweightUtils.message
message
Definition: ReweightUtils.py:15
LoggedMessageSvc::m_stats
BooleanProperty m_stats
Definition: LoggedMessageSvc.h:148
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
atlasStyleMacro.icol
int icol
Definition: atlasStyleMacro.py:13
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
LoggedMessageSvc::m_inactiveMap
std::map< std::string, MsgAry, std::less<> > m_inactiveMap
Definition: LoggedMessageSvc.h:165
dqt_zlumi_alleff_HIST.A
A
Definition: dqt_zlumi_alleff_HIST.py:110
LoggedMessageSvc::reinitialize
virtual StatusCode reinitialize() override
Reinitialize Service.
Definition: LoggedMessageSvc.cxx:144
LoggedMessageSvc::m_thresholdMapMutex
std::mutex m_thresholdMapMutex
Mutex to synchronize multiple access to m_thresholdMap (.
Definition: LoggedMessageSvc.h:197
LoggedMessageSvc::m_msgCount
int m_msgCount[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:172
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
A
histSizes.code
code
Definition: histSizes.py:129
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
LoggedMessageSvc::initialize
virtual StatusCode initialize() override
Initialize Service.
Definition: LoggedMessageSvc.cxx:109
LoggedMessageSvc::messageCount
virtual int messageCount(MSG::Level logLevel) const override
Definition: LoggedMessageSvc.cxx:855
TrigConf::MSGTC::Level
Level
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:21
LoggedMessageSvc::setupLogStreams
void setupLogStreams()
Definition: LoggedMessageSvc.cxx:873
StdJOSetup.msgSvc
msgSvc
Provide convenience handles for various services.
Definition: StdJOSetup.py:36
TrigConf::MSGTC::ALWAYS
@ ALWAYS
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:29
lumiFormat.i
int i
Definition: lumiFormat.py:85
LoggedMessageSvc::LoggedMessageSvc
LoggedMessageSvc(const std::string &name, ISvcLocator *svcloc)
Definition: LoggedMessageSvc.cxx:23
LoggedMessageSvc::m_logLevel
IntegerProperty m_logLevel
Definition: LoggedMessageSvc.h:152
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
LoggedMessageSvc::m_messageMapMutex
std::recursive_mutex m_messageMapMutex
Mutex to synchronize multiple access to m_messageMap.
Definition: LoggedMessageSvc.h:193
LoggedMessageSvc::tee
void tee(const std::string &sourceName, const std::string &logFileName, const std::set< std::string > &declaredOutFileNames)
Definition: LoggedMessageSvc.cxx:911
LoggedMessageSvc::getKeyMessages
virtual std::vector< LoggedMessage > getKeyMessages() const override
Definition: LoggedMessageSvc.cxx:964
LoggedMessageSvc::m_msgLimit
IntegerProperty m_msgLimit[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:151
LoggedMessageSvc::m_suppress
BooleanProperty m_suppress
Definition: LoggedMessageSvc.h:166
LoggedMessageSvc::colTrans
std::string colTrans(const std::string &, int)
Definition: LoggedMessageSvc.cxx:477
LoggedMessageSvc::eraseStream
virtual void eraseStream() override
Definition: LoggedMessageSvc.cxx:673
LoggedMessageSvc::NamedStream
std::pair< std::string, std::ostream * > NamedStream
Definition: LoggedMessageSvc.h:41
LoggedMessageSvc::m_inactCount
BooleanProperty m_inactCount
Definition: LoggedMessageSvc.h:166
LoggedMessageSvc::m_sourceMap
std::map< std::string, MsgAry, std::less<> > m_sourceMap
Definition: LoggedMessageSvc.h:165
LoggedMessageSvc::setOutputLevel
virtual void setOutputLevel(int new_level) override
Definition: LoggedMessageSvc.cxx:824
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
python.CaloComputeNoiseConfig.defaultLimit
defaultLimit
Definition: CaloComputeNoiseConfig.py:146
grepfile.ic
int ic
Definition: grepfile.py:33
LoggedMessageSvc::m_thresholdMap
ThresholdMap m_thresholdMap
Output level threshold map.
Definition: LoggedMessageSvc.h:143
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
LoggedMessageSvc::m_loggedStreamsName
std::map< std::string, std::string > m_loggedStreamsName
Definition: LoggedMessageSvc.h:174
ReadFromCoolCompare.os2
os2
Definition: ReadFromCoolCompare.py:249
TrigConf::MSGTC::NUM_LEVELS
@ NUM_LEVELS
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:30
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
dumpNswErrorDb.outFileName
string outFileName
Definition: dumpNswErrorDb.py:131
checkTriggerxAOD.found
found
Definition: checkTriggerxAOD.py:328
LoggedMessageSvc::getLogColor
virtual std::string getLogColor(int logLevel) const override
Definition: LoggedMessageSvc.cxx:845
python.consts.RED
RED
Definition: consts.py:3
LoggedMessageSvc::setupThreshold
void setupThreshold(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:282
python.TrigPSCPythonDbSetup.outputLevel
outputLevel
Definition: TrigPSCPythonDbSetup.py:30
LoggedMessageSvc::m_defaultTimeFormat
std::string m_defaultTimeFormat
Default format for timestamps in the messages.
Definition: LoggedMessageSvc.h:145
python.consts.YELLOW
YELLOW
Definition: consts.py:3
python.consts.GREEN
GREEN
Definition: consts.py:3
LoggedMessageSvc::m_thresholdProp
StringArrayProperty m_thresholdProp[MSG::NUM_LEVELS]
Properties controling.
Definition: LoggedMessageSvc.h:146
LoggedMessageSvc::setupLimits
void setupLimits(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:245
python.Constants.INFO
int INFO
Definition: Control/AthenaCommon/python/Constants.py:15
LoggedMessageSvc::m_reportMutex
std::mutex m_reportMutex
Mutex to synchronize multiple threads printing.
Definition: LoggedMessageSvc.h:190
DeMoScan.first
bool first
Definition: DeMoScan.py:534
DEBUG
#define DEBUG
Definition: page_access.h:11
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
LoggedMessageSvc::m_defaultStream
std::ostream * m_defaultStream
Pointer to the output stream.
Definition: LoggedMessageSvc.h:139
LoggedMessageSvc::reportMessage
virtual void reportMessage(const Message &message) override
Definition: LoggedMessageSvc.cxx:597
copySelective.source
string source
Definition: copySelective.py:31
str
Definition: BTagTrackIpAccessor.cxx:11
LoggedMessageSvc::m_logColorCodes
std::string m_logColorCodes[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:155
LoggedMessageSvc::m_keywords
StringArrayProperty m_keywords
Definition: LoggedMessageSvc.h:153
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
TrigConf::MSGTC::NIL
@ NIL
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:22
LoggedMessageSvc::getMessages
virtual std::vector< std::pair< std::string, std::string > > getMessages(MSG::Level level) const override
Definition: LoggedMessageSvc.cxx:957
LoggedMessageSvc::m_streamMap
StreamMap m_streamMap
Stream map.
Definition: LoggedMessageSvc.h:141
LoggedMessageSvc::~LoggedMessageSvc
virtual ~LoggedMessageSvc()
Definition: LoggedMessageSvc.cxx:95
value_type
Definition: EDM_MasterSearch.h:11
LoggedMessageSvc::setupInactCount
void setupInactCount(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:336
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
LoggedMessageSvc::m_statLevel
UnsignedIntegerProperty m_statLevel
Definition: LoggedMessageSvc.h:149
python.consts.WHITE
WHITE
Definition: consts.py:3
LoggedMessageSvc::setupColors
void setupColors(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:193
run.Message
Message
Definition: run.py:57
LoggedMessageSvc::m_messageMap
MessageMap m_messageMap
Message map.
Definition: LoggedMessageSvc.h:142
python.logger.BLUE
BLUE
Definition: logger.py:15
LoggedMessageSvc::m_defaultFormat
std::string m_defaultFormat
Default format for the messages.
Definition: LoggedMessageSvc.h:144
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
LoggedMessageSvc::eraseMessage
virtual void eraseMessage() override
Definition: LoggedMessageSvc.cxx:761