ATLAS Offline Software
LoggedMessageSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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::map<std::string,MsgAry>::const_iterator itr;
368  for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
369  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
370  if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
371  (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
372  os << " ";
373  os.width(28);
374  os.setf(ios_base::left,ios_base::adjustfield);
375  os << itr->first;
376 
377  os << "|";
378 
379  os.width(8);
380  os.setf(ios_base::right,ios_base::adjustfield);
381  os << levelNames[ic];
382 
383  os << " |";
384 
385  os.width(9);
386  os << itr->second.msg[ic];
387 
388  os << endl;
389 
390  found = true;
391  }
392  }
393  }
394  os << "=====================================================" << endl;
395 
396  if (found || m_stats) {
397  cout << os.str();
398  }
399 
400 
401 #ifndef NDEBUG
402  if (m_inactCount.value()) {
403 
404  std::ostringstream os;
405  os << "Listing sources of Unprotected and Unseen messages\n";
406 
407  bool found(false);
408 
409  unsigned int ml(0);
410  std::map<std::string,MsgAry>::const_iterator itr;
411  for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
412  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
413  if (itr->second.msg[ic] != 0) {
414  if (itr->first.length() > ml) { ml = itr->first.length(); }
415  }
416  }
417  }
418 
419  for (unsigned int i=0; i<ml+25; ++i) {
420  os << "=";
421  }
422 
423  os << endl << " ";
424  os.width(ml+2);
425  os.setf(ios_base::left,ios_base::adjustfield);
426  os << "Message Source";
427  os.width(1);
428  os << "| Level | Count" << endl;
429 
430  for (unsigned int i=0; i<ml+3; ++i) {
431  os << "-";
432  }
433  os << "+---------+-----------" << endl;
434 
435 
436  for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
437  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
438  if (itr->second.msg[ic] != 0) {
439  os << " ";
440  os.width(ml+2);
441  os.setf(ios_base::left,ios_base::adjustfield);
442  os << itr->first;
443 
444  os << "|";
445 
446  os.width(8);
447  os.setf(ios_base::right,ios_base::adjustfield);
448  os << levelNames[ic];
449 
450  os << " |";
451 
452  os.width(9);
453  os << itr->second.msg[ic];
454 
455  os << endl;
456 
457  found = true;
458  }
459  }
460  }
461  for (unsigned int i=0; i<ml+25; ++i) {
462  os << "=";
463  }
464  os << endl;
465 
466  if (found) {
467  cout << os.str();
468  }
469  }
470 #endif
471 
472  return StatusCode::SUCCESS;
473 }
474 
475 //#############################################################################
476 std::string LoggedMessageSvc::colTrans(const std::string &col, int offset) {
477  ColorMap::const_iterator itr = m_colMap.find(col);
478  int icol;
479  if (itr != m_colMap.end()) {
480  icol = offset + itr->second;
481  } else {
482  icol = offset + 8;
483  }
484  std::ostringstream os1;
485 
486  os1 << icol;
487 
488  return os1.str();
489 
490 }
491 
492 //#############################################################################
493 // ---------------------------------------------------------------------------
494 // Routine: reportMessage
495 // Purpose: dispatches a message to the relevant streams.
496 // ---------------------------------------------------------------------------
497 //
498 
500  std::lock_guard<std::mutex> lock(m_reportMutex);
501 
502  int key = msg.getType();
503  int nmsg;
504 
505  m_msgCount[key] ++;
506 
507  if (outputLevel >= m_logLevel) {
508  m_msgLog[ outputLevel ].push_back( make_pair (msg.getSource(), msg.getMessage() ) );
509  }
510 
511  if (m_keysUsed) {
512  if (msg.getSource() != "AthenaSummarySvc") {
513  for (vector<string>::const_iterator itr=m_keywords.value().begin(); itr!= m_keywords.value().end(); ++itr) {
514  if (msg.getMessage().find( *itr ) != string::npos) {
515  m_msgKeyLog.push_back( LoggedMessage( outputLevel, msg.getSource(), msg.getMessage() ));
516  break;
517  }
518  }
519  }
520  }
521 
522  const Message *cmsg = &msg;
523  std::unique_ptr<Message> suppressed_msg;
524 
525  // processing logged streams
526  if ( !m_loggedStreams.empty() ) {
527  const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
528  if ( m_loggedStreams.end() != iLog ) {
529  (*iLog->second) << *cmsg << std::endl;
530  }
531  }
532 
533  if ( m_suppress.value() || m_stats.value() ) {
534 
536  m_sourceMap.find(msg.getSource());
537  if (itr != m_sourceMap.end()) {
538  itr->second.msg[key] += 1;
539  nmsg = itr->second.msg[key];
540  } else {
541  MsgAry A;
542  for (int i=0; i<MSG::NUM_LEVELS; ++i) {
543  A.msg[i] = 0;
544  }
545  A.msg[key] = 1;
546  m_sourceMap[msg.getSource()] = A;
547  nmsg = 1;
548  }
549 
550  if (m_suppress.value()) {
551 
552  if ( m_msgLimit[key] != 0 ) {
553  if (nmsg == m_msgLimit[key]) {
554  std::string str = levelNames[key] + " message limit (";
556  str += ") reached for ";
557  str += msg.getSource() + ". Suppressing further output.";
558  suppressed_msg = std::make_unique<Message>(msg.getSource(),MSG::WARNING,str);
559  suppressed_msg->setFormat(msg.getFormat());
560  cmsg = suppressed_msg.get();
561  } else if (nmsg > m_msgLimit[key]) {
562  return;
563  }
564  }
565  }
566 
567  }
568 
569  StreamMap::const_iterator first = m_streamMap.lower_bound( key );
570  if ( first != m_streamMap.end() ) {
571  StreamMap::const_iterator last = m_streamMap.upper_bound( key );
572  while( first != last ) {
573  std::ostream& stream = *( (*first).second.second );
574  stream << *cmsg << std::endl;
575  ++first;
576  }
577  }
578  else if ( key >= outputLevel ) {
579  msg.setFormat(m_defaultFormat);
580  msg.setTimeFormat(m_defaultTimeFormat);
581  if (!m_color) {
582  (*m_defaultStream) << *cmsg << std::endl << std::flush;
583  } else {
584  (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
585  << std::endl << std::flush;
586  }
587  }
588 }
589 
590 //#############################################################################
591 // ---------------------------------------------------------------------------
592 // Routine: reportMessage
593 // Purpose: dispatches a message to the relevant streams.
594 // ---------------------------------------------------------------------------
595 //
597  reportMessage(msg, outputLevel(msg.getSource()));
598 }
599 
600 //#############################################################################
601 // ---------------------------------------------------------------------------
602 // Routine: reportMessage
603 // Purpose: dispatches a message to the relevant streams.
604 // ---------------------------------------------------------------------------
605 //
607  int type,
608  std::string message) {
610  reportMessage( msg );
611 }
612 
613 //#############################################################################
614 // ---------------------------------------------------------------------------
615 // Routine: sendMessage
616 // Purpose: finds a message for a given status code and dispatches it.
617 // ---------------------------------------------------------------------------
618 //
619 
621  std::string_view source)
622 {
623  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
624 
625  MessageMap::const_iterator first = m_messageMap.lower_bound( key );
626  if ( first != m_messageMap.end() ) {
627  MessageMap::const_iterator last = m_messageMap.upper_bound( key );
628  while( first != last ) {
629  Message msg = (*first).second;
630  msg.setSource( source );
631  std::ostringstream os1;
632  os1 << "Status Code " << key.getCode() << std::ends;
633  Message stat_code1( std::string{source}, msg.getType(), os1.str() );
634  reportMessage( stat_code1 );
635  reportMessage( msg );
636  ++first;
637  }
638  }
639  else {
640  Message mesg = m_defaultMessage;
641  mesg.setSource( source );
642  std::ostringstream os2;
643  os2 << "Status Code " << key.getCode() << std::ends;
644  Message stat_code2( std::string{source}, mesg.getType(), os2.str() );
645  reportMessage( stat_code2 );
646  reportMessage( mesg );
647  }
648 }
649 
650 //#############################################################################
651 // ---------------------------------------------------------------------------
652 // Routine: insertStream
653 // Purpose: inserts a stream for a message type.
654 // ---------------------------------------------------------------------------
655 //
656 
658  std::string name,
659  std::ostream *stream)
660 {
661  typedef StreamMap::value_type value_type;
662  m_streamMap.insert( value_type( key, NamedStream( std::move(name), stream) ) );
663 }
664 
665 //#############################################################################
666 // ---------------------------------------------------------------------------
667 // Routine: eraseStream
668 // Purpose: erases all the streams for all the message types.
669 // ---------------------------------------------------------------------------
670 //
671 
673 {
674  m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
675 }
676 
677 //#############################################################################
678 // ---------------------------------------------------------------------------
679 // Routine: eraseStream
680 // Purpose: erases all the streams for a message type.
681 // ---------------------------------------------------------------------------
682 //
683 
684 void LoggedMessageSvc::eraseStream( int message_type )
685 {
686  m_streamMap.erase( message_type );
687 }
688 
689 //#############################################################################
690 // ---------------------------------------------------------------------------
691 // Routine: eraseStream
692 // Purpose: erases one stream for a message type.
693 // ---------------------------------------------------------------------------
694 //
695 
696 void LoggedMessageSvc::eraseStream( int key, std::ostream* stream ) {
697  if ( nullptr != stream ) {
698  bool changed = true;
699  while( changed ) {
700  changed = false;
701  StreamMap::iterator first = m_streamMap.lower_bound( key );
702  StreamMap::iterator last = m_streamMap.upper_bound( key );
703  while( first != last ) {
704  if ( (*first).second.second == stream ) {
705  m_streamMap.erase( first );
706  changed = true;
707  break;
708  }
709  }
710  }
711  }
712 }
713 
714 //#############################################################################
715 // ---------------------------------------------------------------------------
716 // Routine: eraseStream
717 // Purpose: erases one stream for all message types.
718 // ---------------------------------------------------------------------------
719 //
720 
721 void LoggedMessageSvc::eraseStream( std::ostream* stream ) {
722  if ( nullptr != stream ) {
723  bool changed = true;
724  while( changed ) {
725  changed = false;
727  while( first != m_streamMap.end() ) {
728  if ( (*first).second.second == stream ) {
729  m_streamMap.erase( first );
730  changed = true;
731  break;
732  }
733  }
734  }
735  }
736 }
737 
738 
739 //#############################################################################
740 // ---------------------------------------------------------------------------
741 // Routine: insertMessage
742 // Purpose: inserts a message for a status code.
743 // ---------------------------------------------------------------------------
744 //
745 
747 {
748  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
749 
750  m_messageMap.emplace( key, std::move( msg ) );
751 }
752 
753 //#############################################################################
754 // ---------------------------------------------------------------------------
755 // Routine: eraseMessage
756 // Purpose: erases all the messages for all the status codes.
757 // ---------------------------------------------------------------------------
758 //
759 
761 {
762  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
763 
764  m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
765 }
766 
767 //#############################################################################
768 // ---------------------------------------------------------------------------
769 // Routine: eraseMessage
770 // Purpose: erases all the messages for a status code.
771 // ---------------------------------------------------------------------------
772 //
773 
775 {
776  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
777 
778  m_messageMap.erase( key );
779 }
780 
781 //#############################################################################
782 // ---------------------------------------------------------------------------
783 // Routine: eraseMessage
784 // Purpose: erases one message for a status code.
785 // ---------------------------------------------------------------------------
786 //
787 
789 {
790  std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
791 
792  bool changed = true;
793  while( changed ) {
794  changed = false;
795  MessageMap::iterator first = m_messageMap.lower_bound( key );
796  MessageMap::iterator last = m_messageMap.upper_bound( key );
797  while( first != last ) {
798  const Message& message = (*first).second;
799  if ( message == msg ) {
800  m_messageMap.erase( first );
801  changed = true;
802  break;
803  }
804  }
805  }
806 }
807 
808 // ---------------------------------------------------------------------------
810 // ---------------------------------------------------------------------------
811  return m_outputLevel;
812 }
813 // ---------------------------------------------------------------------------
814 int LoggedMessageSvc::outputLevel( std::string_view source ) const {
815 // ---------------------------------------------------------------------------
816  std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
817 
818  auto it = m_thresholdMap.find( source );
819  return it != m_thresholdMap.end() ? it->second : m_outputLevel.value();
820 }
821 
822 // ---------------------------------------------------------------------------
823 void LoggedMessageSvc::setOutputLevel(int new_level) {
824 // ---------------------------------------------------------------------------
825  m_outputLevel = new_level;
826 }
827 
828 // ---------------------------------------------------------------------------
829 void LoggedMessageSvc::setOutputLevel(std::string_view source, int level) {
830 // ---------------------------------------------------------------------------
831  std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
832 
833  // only write if we really have to...
834  auto i = m_thresholdMap.find( source );
835  if ( i == m_thresholdMap.end() ) {
836  m_thresholdMap.emplace( source, level );
837  } else if ( i->second != level ) {
838  i->second = level;
839  }
840 
841 }
842 
843 // ---------------------------------------------------------------------------
844 std::string LoggedMessageSvc::getLogColor(int logLevel) const {
845 // ---------------------------------------------------------------------------
846  if (logLevel < MSG::NUM_LEVELS) {
847  return m_logColorCodes[logLevel];
848  } else {
849  return "";
850  }
851 }
852 
853 // ---------------------------------------------------------------------------
855 
856  return m_msgCount[level];
857 
858 }
859 
860 // ---------------------------------------------------------------------------
861 void
863 
864  auto entry = m_inactiveMap.find( source );
865  if ( entry == m_inactiveMap.end() ) {
866  entry = m_inactiveMap.emplace( source, MsgAry{} ).first;
867  }
868  ++entry->second.msg[level];
869 }
870 
871 // ---------------------------------------------------------------------------
873 {
874  // reset state
875  for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
876  iLog != m_loggedStreams.end();
877  ++iLog ) {
878  delete iLog->second;
879  }
880  m_loggedStreams.clear();
881 
882  typedef std::map<std::string,std::string> StreamMap_t;
883  const StreamMap_t& streamMap = m_loggedStreamsName;
884  typedef StreamMap_t::const_iterator StreamMapIter;
885 
886  for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
887  iProp != iEnd;
888  ++iProp ) {
889 
890  const std::string sourceName = iProp->first;
891  const std::string outFileName = iProp->second;
892 
893  std::set<std::string> outFileNames;
894  for ( StreamMapIter jProp = streamMap.begin();
895  jProp != iEnd;
896  ++jProp ) {
897  if ( jProp->first != iProp->first ) {
898  outFileNames.insert( jProp->second );
899  }
900  }
901 
902  tee( sourceName, outFileName, outFileNames );
903 
904  }//> loop over property entries
905 
906  return;
907 }
908 
909 // ---------------------------------------------------------------------------
910 void LoggedMessageSvc::tee( const std::string& sourceName,
911  const std::string& outFileName,
912  const std::set<std::string>& outFileNames )
913 {
914  const std::ios_base::openmode openMode = std::ios_base::out |
915  std::ios_base::trunc;
916 
918  LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
919  if ( iStream != iEnd ) {
920  delete iStream->second;
921  iStream->second = nullptr;
922  m_loggedStreams.erase( iStream );
923  }
924 
925  // before creating a new ofstream, make sure there is no already existing
926  // one with the same file name...
927  iEnd = m_loggedStreams.end();
928  for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
929  if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
930  m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
931  return;
932  }
933  }
934 
935  std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
936 
937  if ( !out->good() ) {
938  out->close();
939  delete out;
940  return;
941  }
942 
943  m_loggedStreams[sourceName] = out;
944 
945  return;
946 }
947 
948 
949 //#############################################################################
950 // ---------------------------------------------------------------------------
951 // Routine: getMessages
952 // Purpose: get all messages of a certain MSG::Level
953 // ---------------------------------------------------------------------------
954 
955 const std::vector< std::pair<std::string, std::string> >&
957 
958  return m_msgLog[ level ];
959 
960 }
961 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
LoggedMessageSvc.h
LoggedMessageSvc::m_logColors
StringArrayProperty m_logColors[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:149
LoggedMessageSvc::insertStream
virtual void insertStream(int message_type, std::string name, std::ostream *stream) override
Definition: LoggedMessageSvc.cxx:657
LoggedMessageSvc::m_msgKeyLog
std::vector< LoggedMessage > m_msgKeyLog
Definition: LoggedMessageSvc.h:199
python.consts.BLACK
BLACK
Definition: consts.py:3
python.Constants.FATAL
int FATAL
Definition: Control/AthenaCommon/python/Constants.py:19
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:186
LoggedMessageSvc::finalize
virtual StatusCode finalize() override
Finalize Service.
Definition: LoggedMessageSvc.cxx:348
LoggedMessageSvc::m_colMap
ColorMap m_colMap
Definition: LoggedMessageSvc.h:169
LoggedMessageSvc::insertMessage
virtual void insertMessage(const StatusCode &code, Message message) override
Definition: LoggedMessageSvc.cxx:746
LoggedMessageSvc::m_color
BooleanProperty m_color
Definition: LoggedMessageSvc.h:146
LoggedMessageSvc::m_keysUsed
bool m_keysUsed
Definition: LoggedMessageSvc.h:200
LoggedMessageSvc::m_msgLog
std::vector< std::pair< std::string, std::string > > m_msgLog[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:198
LoggedMessageSvc::m_defaultMessage
Message m_defaultMessage
Default Message.
Definition: LoggedMessageSvc.h:139
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:396
LoggedMessageSvc::initColors
void initColors(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:151
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
LoggedMessageSvc::outputLevel
virtual int outputLevel() const override
Definition: LoggedMessageSvc.cxx:809
athena.value
value
Definition: athena.py:124
LoggedMessageSvc::incrInactiveCount
virtual void incrInactiveCount(MSG::Level level, std::string_view src) override
Definition: LoggedMessageSvc.cxx:862
LoggedMessageSvc::m_loggedStreams
LoggedStreamsMap_t m_loggedStreams
Definition: LoggedMessageSvc.h:175
LoggedMessageSvc::MsgAry
Private helper class to keep the count of messages of a type (MSG::LEVEL).
Definition: LoggedMessageSvc.h:157
ReweightUtils.message
message
Definition: ReweightUtils.py:15
LoggedMessageSvc::m_stats
BooleanProperty m_stats
Definition: LoggedMessageSvc.h:147
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
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:164
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:196
LoggedMessageSvc::m_msgCount
int m_msgCount[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:171
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
DumpGeoConfig.outFileName
string outFileName
Definition: DumpGeoConfig.py:252
A
histSizes.code
code
Definition: histSizes.py:129
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
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:854
TrigConf::MSGTC::Level
Level
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:21
LoggedMessageSvc::setupLogStreams
void setupLogStreams()
Definition: LoggedMessageSvc.cxx:872
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:151
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:192
LoggedMessageSvc::tee
void tee(const std::string &sourceName, const std::string &logFileName, const std::set< std::string > &declaredOutFileNames)
Definition: LoggedMessageSvc.cxx:910
CaloGetLC_CL_W_OOC_Config.defaultLimit
defaultLimit
Definition: CaloGetLC_CL_W_OOC_Config.py:80
LoggedMessageSvc::m_msgLimit
IntegerProperty m_msgLimit[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:150
LoggedMessageSvc::m_suppress
BooleanProperty m_suppress
Definition: LoggedMessageSvc.h:165
LoggedMessageSvc::colTrans
std::string colTrans(const std::string &, int)
Definition: LoggedMessageSvc.cxx:476
LoggedMessageSvc::eraseStream
virtual void eraseStream() override
Definition: LoggedMessageSvc.cxx:672
LoggedMessageSvc::NamedStream
std::pair< std::string, std::ostream * > NamedStream
Definition: LoggedMessageSvc.h:41
LoggedMessageSvc::m_inactCount
BooleanProperty m_inactCount
Definition: LoggedMessageSvc.h:165
LoggedMessageSvc::m_sourceMap
std::map< std::string, MsgAry, std::less<> > m_sourceMap
Definition: LoggedMessageSvc.h:164
LoggedMessageSvc::setOutputLevel
virtual void setOutputLevel(int new_level) override
Definition: LoggedMessageSvc.cxx:823
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
grepfile.ic
int ic
Definition: grepfile.py:33
LoggedMessageSvc::m_thresholdMap
ThresholdMap m_thresholdMap
Output level threshold map.
Definition: LoggedMessageSvc.h:142
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
LoggedMessageSvc::m_loggedStreamsName
std::map< std::string, std::string > m_loggedStreamsName
Definition: LoggedMessageSvc.h:173
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:221
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
LoggedMessageSvc::getMessages
virtual const std::vector< std::pair< std::string, std::string > > & getMessages(MSG::Level level) const override
Definition: LoggedMessageSvc.cxx:956
LoggedMessageSvc::getLogColor
virtual std::string getLogColor(int logLevel) const override
Definition: LoggedMessageSvc.cxx:844
query_example.col
col
Definition: query_example.py:7
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:144
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:145
LoggedMessageSvc::setupLimits
void setupLimits(Gaudi::Details::PropertyBase &prop)
Definition: LoggedMessageSvc.cxx:245
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
LoggedMessageSvc::m_reportMutex
std::mutex m_reportMutex
Mutex to synchronize multiple threads printing.
Definition: LoggedMessageSvc.h:189
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:536
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:138
LoggedMessageSvc::reportMessage
virtual void reportMessage(const Message &message) override
Definition: LoggedMessageSvc.cxx:596
copySelective.source
string source
Definition: copySelective.py:32
str
Definition: BTagTrackIpAccessor.cxx:11
LoggedMessageSvc::m_logColorCodes
std::string m_logColorCodes[MSG::NUM_LEVELS]
Definition: LoggedMessageSvc.h:154
LoggedMessageSvc::m_keywords
StringArrayProperty m_keywords
Definition: LoggedMessageSvc.h:152
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
TrigConf::MSGTC::NIL
@ NIL
Definition: Trigger/TrigConfiguration/TrigConfBase/TrigConfBase/MsgStream.h:22
LoggedMessageSvc::m_streamMap
StreamMap m_streamMap
Stream map.
Definition: LoggedMessageSvc.h:140
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:148
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:141
python.logger.BLUE
BLUE
Definition: logger.py:15
LoggedMessageSvc::m_defaultFormat
std::string m_defaultFormat
Default format for the messages.
Definition: LoggedMessageSvc.h:143
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
LoggedMessageSvc::eraseMessage
virtual void eraseMessage() override
Definition: LoggedMessageSvc.cxx:760