MessageSvc.cpp
Go to the documentation of this file.
1 #ifdef _WIN32
2 // Avoid conflicts between windows and the message service.
3 #define NOMSG
4 #define NOGDI
5 #endif
6 
7 #include "GaudiKernel/Kernel.h"
8 #include "GaudiKernel/StatusCode.h"
9 #include "GaudiKernel/Message.h"
10 #include "MessageSvc.h"
11 
12 #include <sstream>
13 #include <iostream>
14 #include <fstream>
15 
16 
17 namespace {
18 
19  // erase_if functions for containers which do NOT invalidate iterators
20  // after the erase point, eg.std::{unordered_}{,multi}map, std::{forward_,}list.
21  // To be explicit: this does NOT work with std::vector.
22 
23  // TODO: replace with std::experimental::erase_if (Libraries Fundamental TS v2)
24 
25  template < typename Container, typename Iterator, typename Predicate >
26  void erase_if( Container& c, Iterator first, Iterator last, Predicate pred) {
27  while ( first!=last ) {
28  if ( pred(*first) ) first = c.erase(first);
29  else ++first;
30  }
31  }
32 
33  template< typename Container, typename Predicate >
34  void erase_if( Container& c, Predicate pred ) {
35  return erase_if(c, std::begin(c), std::end(c),
36  std::forward<Predicate>(pred) );
37  }
38 
39  template< typename Container, typename Iterator, typename Predicate >
40  void erase_if( Container& c, std::pair<Iterator,Iterator> range, Predicate pred ) {
41  return erase_if(c, std::move(range.first), std::move(range.second),
42  std::forward<Predicate>(pred) );
43  }
44 
45 }
46 
47 // Instantiation of a static factory class used by clients to create
48 // instances of this service
50 
51 static const std::string levelNames[MSG::NUM_LEVELS] = {
52  "NIL", "VERBOSE", "DEBUG", "INFO",
53  "WARNING", "ERROR", "FATAL", "ALWAYS"
54 };
55 
56 // Constructor
57 MessageSvc::MessageSvc( const std::string& name, ISvcLocator* svcloc )
58  : base_class( name, svcloc ) {
59  m_defaultStream = &std::cout;
60  declareProperty( "Format", m_defaultFormat = Message::getDefaultFormat() );
61  declareProperty( "timeFormat", m_defaultTimeFormat = Message::getDefaultTimeFormat() );
62  declareProperty( "showStats", m_stats = false );
63  declareProperty( "statLevel", m_statLevel = 0 );
64 
65  // Special properties to control output level of individual sources
66  declareProperty( "setVerbose", m_thresholdProp[MSG::VERBOSE] );
67  declareProperty( "setDebug", m_thresholdProp[MSG::DEBUG] );
68  declareProperty( "setInfo", m_thresholdProp[MSG::INFO] );
69  declareProperty( "setWarning", m_thresholdProp[MSG::WARNING] );
70  declareProperty( "setError", m_thresholdProp[MSG::ERROR] );
71  declareProperty( "setFatal", m_thresholdProp[MSG::FATAL] );
72  declareProperty( "setAlways", m_thresholdProp[MSG::ALWAYS] );
73 
74  declareProperty( "useColors", m_color=false)->declareUpdateHandler(&MessageSvc::initColors, this);
75 
76  declareProperty( "fatalColorCode", m_logColors[MSG::FATAL] );
77  declareProperty( "errorColorCode", m_logColors[MSG::ERROR] );
78  declareProperty( "warningColorCode", m_logColors[MSG::WARNING] );
79  declareProperty( "infoColorCode", m_logColors[MSG::INFO] );
80  declareProperty( "debugColorCode", m_logColors[MSG::DEBUG] );
81  declareProperty( "verboseColorCode", m_logColors[MSG::VERBOSE] );
82  declareProperty( "alwaysColorCode", m_logColors[MSG::ALWAYS] );
83 
84  const int defaultLimit = 500;
85  declareProperty( "fatalLimit", m_msgLimit[MSG::FATAL] = defaultLimit );
86  declareProperty( "errorLimit", m_msgLimit[MSG::ERROR] = defaultLimit );
87  declareProperty( "warningLimit", m_msgLimit[MSG::WARNING] = defaultLimit );
88  declareProperty( "infoLimit", m_msgLimit[MSG::INFO] = defaultLimit );
89  declareProperty( "debugLimit", m_msgLimit[MSG::DEBUG] = defaultLimit );
90  declareProperty( "verboseLimit", m_msgLimit[MSG::VERBOSE] = defaultLimit );
91  declareProperty( "alwaysLimit", m_msgLimit[MSG::ALWAYS] = 0 );
92 
93  declareProperty( "defaultLimit", m_msgLimit[MSG::NIL] = defaultLimit );
94 
95  declareProperty( "enableSuppression", m_suppress = false );
96  declareProperty( "countInactive", m_inactCount = false )->declareUpdateHandler( &MessageSvc::setupInactCount, this );
97 #ifndef NDEBUG
98  // initialize the MsgStream static flag.
100 #endif
101 
102  declareProperty( "loggedStreams",
104  "MessageStream sources we want to dump into a logfile" );
105 
106  for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
110  }
111 
113 }
114 
115 //#############################################################################
116 
117 
120  StatusCode sc;
121  sc = Service::initialize();
122  if( sc.isFailure() ) return sc;
123  // Set my own properties
124  sc = setProperties();
125  if (sc.isFailure()) return sc;
126 
127 #ifdef _WIN32
128  m_color = false;
129 #endif
130 
131  //NOTE: m_colMap is used _before_ it is filled here,
132  // i.e. while it is still empty.
133  // Moving this initialization 'up' by eg. just
134  // having a 'static const' colMap does not leave
135  // the results invariant...
136  m_colMap["black"] = MSG::BLACK;
137  m_colMap["red"] = MSG::RED;
138  m_colMap["green"] = MSG::GREEN;
139  m_colMap["yellow"] = MSG::YELLOW;
140  m_colMap["blue"] = MSG::BLUE;
141  m_colMap["purple"] = MSG::PURPLE;
142  m_colMap["cyan"] = MSG::CYAN;
143  m_colMap["white"] = MSG::WHITE;
144 
145  // make sure the map of logged stream names is initialized
146  setupLogStreams();
147 
148  return StatusCode::SUCCESS;
149 }
150 
151 //#############################################################################
152 
156  return initialize();
157 }
158 
159 //#############################################################################
160 
162 
163  if (m_color) {
164  static const std::array<std::pair<MSG::Level,std::vector<std::string>>,3> tbl{
165  { { MSG::FATAL, { { "[94;101;1m" } } },
166  { MSG::ERROR, { { "[97;101;1m" } } },
167  { MSG::WARNING, { { "[93;1m" } } } } };
168 
169  for (const auto& p : tbl ) {
170  auto &lC = m_logColors[p.first];
171  if (lC.value().empty()) {
172  lC.set(p.second);
173  } else {
175  }
176  }
177 
178  } else {
179 
180  // reset all color codes;
181  for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
182  m_logColors[ic].set( { } );
183  }
184 
185  }
186 
187 }
188 
189 //#############################################################################
190 
192 
193  if (! m_color) return;
194 
195  static const std::array<std::pair<const char*,MSG::Level>,7> tbl {
196  { {"fatalColorCode", MSG::FATAL },
197  {"errorColorCode", MSG::ERROR },
198  {"warningColorCode", MSG::WARNING },
199  {"infoColorCode", MSG::INFO },
200  {"debugColorCode", MSG::DEBUG },
201  {"verboseColorCode", MSG::VERBOSE },
202  {"alwaysColorCode", MSG::ALWAYS } } };
203 
204  auto i = std::find_if( std::begin(tbl),std::end(tbl),
205  [&](const std::pair<const char*,MSG::Level>& t) {
206  return prop.name() == t.first;
207  } );
208  if (i==std::end(tbl)) {
209  std::cout << "ERROR: Unknown message color parameter: " << prop.name()
210  << std::endl;
211  return;
212  }
213  int ic = i->second;
214 
215  std::string code;
216  auto itr = m_logColors[ic].value().begin();
217 
218  if ( m_logColors[ic].value().size() == 1 ) {
219 
220  if (itr->empty()) {
221  code = "";
222  } else if (itr->compare(0,1,"[") == 0) {
223  code = "\033" + *itr;
224  } else {
225  code = "\033[" + colTrans(*itr, 90) + ";1m";
226  }
227 
228  } else if (m_logColors[ic].value().size() == 2) {
229  auto itr2 = itr + 1;
230 
231  code = "\033[" + colTrans(*itr, 90) + ";"
232  + colTrans(*itr2, 100) + ";1m";
233 
234  }
235 
236  m_logColorCodes[ic] = code;
237 
238 }
239 //#############################################################################
240 
242  // Just report problems in the settings of the limits and unknown limit parameters
243  if (prop.name() == "alwaysLimit") {
244  IntegerProperty *p = dynamic_cast<IntegerProperty*>(&prop);
245  if (p && p->value() != 0) {
246  std::cout << "MessageSvc ERROR: cannot suppress ALWAYS messages" << std::endl;
247  p->setValue(0);
248  }
249  } else if (prop.name() == "defaultLimit") {
250  for (int i = MSG::VERBOSE; i< MSG::NUM_LEVELS; ++i) {
251  if (i != MSG::ALWAYS) {
253  }
254  }
255  } else if (prop.name() != "fatalLimit" &&
256  prop.name() != "errorLimit" &&
257  prop.name() != "warningLimit" &&
258  prop.name() == "infoLimit" &&
259  prop.name() == "debugLimit" &&
260  prop.name() == "verboseLimit") {
261  std::cout << "MessageSvc ERROR: Unknown message limit parameter: "
262  << prop.name() << std::endl;
263  return;
264  }
265 }
266 //#############################################################################
267 
269 
270  static const std::array<std::pair<const char*,MSG::Level>,7> tbl{
271  { { "setFatal", MSG::FATAL },
272  { "setError", MSG::ERROR },
273  { "setWarning", MSG::WARNING },
274  { "setInfo", MSG::INFO },
275  { "setDebug", MSG::DEBUG },
276  { "setVerbose", MSG::VERBOSE },
277  { "setAlways", MSG::ALWAYS } } };
278 
279  auto i = std::find_if( std::begin(tbl),std::end(tbl),
280  [&](const std::pair<const char*,MSG::Level>& t) {
281  return prop.name() == t.first;
282  } );
283  if (i==std::end(tbl)) {
284  std::cerr << "MessageSvc ERROR: Unknown message threshold parameter: "
285  << prop.name() << std::endl;
286  return;
287  }
288  int ic = i->second;
289 
290  StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop);
291  if (!sap) {
292  std::cerr << "could not dcast " << prop.name()
293  << " to a StringArrayProperty (which it should be!)" << std::endl;
294  } else {
295  for ( auto& i : sap->value() ) setOutputLevel( i, ic );
296  }
297 
298 }
299 
300 //#############################################################################
301 
302 #ifdef NDEBUG
304 #else
306  if (prop.name() == "countInactive") {
307  BooleanProperty *p = dynamic_cast<BooleanProperty*>(&prop);
308  if (p)
310  }
311 }
312 #endif
313 
314 
315 //#############################################################################
318 
319  m_suppress = false;
320 
321  {
322  std::ostringstream os;
323 
324  if (m_stats) {
325  os << "Summarizing all message counts" << std::endl;
326  } else {
327  os << "Listing sources of suppressed message: " << std::endl;
328  }
329 
330  os << "=====================================================" << std::endl;
331  os << " Message Source | Level | Count" << std::endl;
332  os << "-----------------------------+---------+-------------" << std::endl;
333 
334 
335  bool found(false);
336 
337  for (auto itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
338  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
339  if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
340  (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
341  os << " ";
342  os.width(28);
343  os.setf(std::ios_base::left,std::ios_base::adjustfield);
344  os << itr->first;
345  os << "|";
346 
347  os.width(8);
348  os.setf(std::ios_base::right,std::ios_base::adjustfield);
349  os << levelNames[ic];
350  os << " |";
351 
352  os.width(9);
353  os << itr->second.msg[ic];
354  os << std::endl;
355 
356  found = true;
357  }
358  }
359  }
360  os << "=====================================================" << std::endl;
361  if (found || m_stats) std::cout << os.str();
362  }
363 
364 #ifndef NDEBUG
365  if (m_inactCount.value()) {
366 
367  std::ostringstream os;
368  os << "Listing sources of Unprotected and Unseen messages\n";
369 
370  bool found(false);
371 
372  unsigned int ml(0);
373  for (const auto& itr : m_inactiveMap) {
374  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
375  if (itr.second.msg[ic] != 0 && itr.first.length() > ml) {
376  ml = itr.first.length();
377  }
378  }
379  }
380 
381  for (unsigned int i=0; i<ml+25; ++i) os << "=";
382 
383  os << std::endl << " ";
384  os.width(ml+2);
385  os.setf(std::ios_base::left,std::ios_base::adjustfield);
386  os << "Message Source";
387  os.width(1);
388  os << "| Level | Count" << std::endl;
389 
390  for (unsigned int i=0; i<ml+3; ++i) os << "-";
391  os << "+---------+-----------" << std::endl;
392 
393 
394  for (auto itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
395  for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
396  if (itr->second.msg[ic] != 0) {
397  os << " ";
398  os.width(ml+2);
399  os.setf(std::ios_base::left,std::ios_base::adjustfield);
400  os << itr->first;
401 
402  os << "|";
403 
404  os.width(8);
405  os.setf(std::ios_base::right,std::ios_base::adjustfield);
406  os << levelNames[ic];
407 
408  os << " |";
409 
410  os.width(9);
411  os << itr->second.msg[ic];
412 
413  os << std::endl;
414 
415  found = true;
416  }
417  }
418  }
419  for (unsigned int i=0; i<ml+25; ++i) os << "=";
420  os << std::endl;
421 
422  if (found) std::cout << os.str();
423  }
424 #endif
425 
426  return StatusCode::SUCCESS;
427 }
428 
429 //#############################################################################
430 std::string MessageSvc::colTrans(std::string col, int offset) {
431  auto itr = m_colMap.find(col);
432  int icol = offset + ( (itr != m_colMap.end()) ? itr->second : 8 );
433  return std::to_string( icol );
434 }
435 
436 //#############################################################################
437 // ---------------------------------------------------------------------------
438 // Routine: reportMessage
439 // Purpose: dispatches a message to the relevant streams.
440 // ---------------------------------------------------------------------------
441 //
442 void MessageSvc::reportMessage( const Message& msg, int outputLevel ) {
443  std::unique_lock<std::recursive_mutex> lock(m_reportMutex);
444  i_reportMessage(msg, outputLevel);
445 }
446 
447 void MessageSvc::i_reportMessage( const Message& msg, int outputLevel ) {
448  int key = msg.getType();
449 
450  ++m_msgCount[key];
451 
452  const Message *cmsg = &msg;
453 
454  // processing logged streams
455  if ( !m_loggedStreams.empty() ) {
456  auto iLog = m_loggedStreams.find( msg.getSource() );
457  if ( m_loggedStreams.end() != iLog ) {
458  (*iLog->second) << *cmsg << std::endl;
459  }
460  }
461 
462  if ( m_suppress.value() || m_stats.value() ) {
463 
464  // Increase the counter of 'key' type of messages for the source and
465  // get the new value.
466  const int nmsg = ++(m_sourceMap[msg.getSource()].msg[key]);
467 
468  if (m_suppress.value() && m_msgLimit[key] != 0 ) {
469  if (nmsg > m_msgLimit[key]) return;
470  if (nmsg == m_msgLimit[key]) {
471  std::string txt = levelNames[key] + " message limit ("
472  + std::to_string( m_msgLimit[key].value() )
473  + ") reached for " + msg.getSource() + ". Suppressing further output.";
474  cmsg = new Message(msg.getSource(), MSG::WARNING, std::move(txt));
475  cmsg->setFormat(msg.getFormat());
476  }
477  }
478  }
479 
480  auto range = m_streamMap.equal_range( key );
481  if ( range.first != m_streamMap.end() ) {
482  std::for_each( range.first,range.second, [&](StreamMap::const_reference sm) {
483  *sm.second.second << *cmsg << std::endl;
484  });
485  } else if ( key >= outputLevel ) {
488  if (!m_color) {
489  (*m_defaultStream) << *cmsg << std::endl << std::flush;
490  } else {
491  (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
492  << std::endl << std::flush;
493  }
494  }
495 
496  if (cmsg != &msg) { delete cmsg; }
497 
498 }
499 
500 //#############################################################################
501 // ---------------------------------------------------------------------------
502 // Routine: reportMessage
503 // Purpose: dispatches a message to the relevant streams.
504 // ---------------------------------------------------------------------------
505 //
507  reportMessage(msg, outputLevel(msg.getSource()));
508 }
509 
510 //#############################################################################
511 // ---------------------------------------------------------------------------
512 // Routine: reportMessage
513 // Purpose: dispatches a message to the relevant streams.
514 // ---------------------------------------------------------------------------
515 //
516 void MessageSvc::reportMessage (const char* source,
517  int type,
518  const char* message) {
519  reportMessage( Message{ source, type, message } );
520 }
521 
522 //#############################################################################
523 // ---------------------------------------------------------------------------
524 // Routine: reportMessage
525 // Purpose: dispatches a message to the relevant streams.
526 // ---------------------------------------------------------------------------
527 //
528 void MessageSvc::reportMessage (const std::string& source,
529  int type,
530  const std::string& message) {
531  reportMessage( Message{source, type, message} );
532 }
533 
534 //#############################################################################
535 // ---------------------------------------------------------------------------
536 // Routine: sendMessage
537 // Purpose: finds a message for a given status code and dispatches it.
538 // ---------------------------------------------------------------------------
539 //
541  const std::string& source)
542 {
543  std::unique_lock<std::recursive_mutex> lock(m_messageMapMutex);
544  i_reportMessage(code, source);
545 }
546 
548  const std::string& source)
549 {
550  int level = outputLevel(source);
551  auto report = [&](Message mesg) {
552  mesg.setSource( source );
553  Message stat_code( source, mesg.getType(), "Status Code " + std::to_string( code.getCode() ) );
554  i_reportMessage( std::move(stat_code), level );
555  i_reportMessage( std::move(mesg), level );
556  };
557 
558  auto range = m_messageMap.equal_range( code );
559  if ( range.first != m_messageMap.end() ) {
560  std::for_each( range.first, range.second,
561  [&](MessageMap::const_reference sm) { report(sm.second); } );
562  } else {
563  report(m_defaultMessage);
564  }
565 }
566 
567 //#############################################################################
568 // ---------------------------------------------------------------------------
569 // Routine: insertStream
570 // Purpose: inserts a stream for a message type.
571 // ---------------------------------------------------------------------------
572 //
573 
575  const std::string& name,
576  std::ostream *stream)
577 {
578  m_streamMap.emplace( key, NamedStream(name,stream) );
579 }
580 
581 //#############################################################################
582 // ---------------------------------------------------------------------------
583 // Routine: eraseStream
584 // Purpose: erases all the streams for all the message types.
585 // ---------------------------------------------------------------------------
586 //
587 
589 {
590  m_streamMap.clear();
591 }
592 
593 //#############################################################################
594 // ---------------------------------------------------------------------------
595 // Routine: eraseStream
596 // Purpose: erases all the streams for a message type.
597 // ---------------------------------------------------------------------------
598 //
599 
600 void MessageSvc::eraseStream( int message_type )
601 {
602  m_streamMap.erase( message_type );
603 }
604 
605 //#############################################################################
606 // ---------------------------------------------------------------------------
607 // Routine: eraseStream
608 // Purpose: erases one stream for a message type.
609 // ---------------------------------------------------------------------------
610 //
611 
612 void MessageSvc::eraseStream( int key, std::ostream* stream ) {
613  if ( stream ) {
614  erase_if( m_streamMap, m_streamMap.equal_range(key),
615  [&](StreamMap::const_reference j)
616  { return j.second.second == stream; } );
617  }
618 }
619 
620 //#############################################################################
621 // ---------------------------------------------------------------------------
622 // Routine: eraseStream
623 // Purpose: erases one stream for all message types.
624 // ---------------------------------------------------------------------------
625 //
626 
627 void MessageSvc::eraseStream( std::ostream* stream ) {
628  if ( stream ) {
629  erase_if( m_streamMap, [&](StreamMap::const_reference j)
630  { return j.second.second == stream; } );
631  }
632 }
633 
634 //#############################################################################
635 // ---------------------------------------------------------------------------
636 // Routine: insertMessage
637 // Purpose: inserts a message for a status code.
638 // ---------------------------------------------------------------------------
639 //
640 
642 {
643  std::unique_lock<std::recursive_mutex> lock(m_messageMapMutex);
644  m_messageMap.emplace( key, msg );
645 }
646 
647 //#############################################################################
648 // ---------------------------------------------------------------------------
649 // Routine: eraseMessage
650 // Purpose: erases all the messages for all the status codes.
651 // ---------------------------------------------------------------------------
652 //
653 
655 {
656  std::unique_lock<std::recursive_mutex> lock(m_messageMapMutex);
657  m_messageMap.clear();
658 }
659 
660 //#############################################################################
661 // ---------------------------------------------------------------------------
662 // Routine: eraseMessage
663 // Purpose: erases all the messages for a status code.
664 // ---------------------------------------------------------------------------
665 //
666 
668 {
669  std::unique_lock<std::recursive_mutex> lock(m_messageMapMutex);
670  m_messageMap.erase( key );
671 }
672 
673 //#############################################################################
674 // ---------------------------------------------------------------------------
675 // Routine: eraseMessage
676 // Purpose: erases one message for a status code.
677 // ---------------------------------------------------------------------------
678 //
679 
680 void MessageSvc::eraseMessage( const StatusCode& key, const Message& msg )
681 {
682  std::unique_lock<std::recursive_mutex> lock(m_messageMapMutex);
683 
684  erase_if( m_messageMap, m_messageMap.equal_range(key),
685  [&](MessageMap::const_reference j) { return j.second==msg; } ) ;
686 }
687 
688 // ---------------------------------------------------------------------------
690 // ---------------------------------------------------------------------------
691  return m_outputLevel;
692 }
693 
694 // ---------------------------------------------------------------------------
695 int MessageSvc::outputLevel( const std::string& source ) const {
696 // ---------------------------------------------------------------------------
697  std::unique_lock<std::recursive_mutex> lock(m_thresholdMapMutex);
698  auto it = m_thresholdMap.find( source );
699  return ( it != m_thresholdMap.end() ) ? it->second : m_outputLevel.value();
700 }
701 
702 // ---------------------------------------------------------------------------
703 void MessageSvc::setOutputLevel(int new_level) {
704 // ---------------------------------------------------------------------------
705  m_outputLevel = new_level;
706 }
707 
708 // ---------------------------------------------------------------------------
709 void MessageSvc::setOutputLevel(const std::string& source, int level) {
710 // ---------------------------------------------------------------------------
711  std::unique_lock<std::recursive_mutex> lock(m_thresholdMapMutex);
712 
713  m_thresholdMap[source] = level;
714 }
715 
716 // ---------------------------------------------------------------------------
717 std::string MessageSvc::getLogColor(int logLevel) const {
718 // ---------------------------------------------------------------------------
719  return (logLevel < MSG::NUM_LEVELS) ? m_logColorCodes[logLevel] : "" ;
720 }
721 
722 // ---------------------------------------------------------------------------
724 
725  return m_msgCount[level];
726 
727 }
728 
729 // ---------------------------------------------------------------------------
730 void
731 MessageSvc::incrInactiveCount(MSG::Level level, const std::string& source) {
732 
733  ++(m_inactiveMap[source].msg[level]);
734 
735 }
736 
737 // ---------------------------------------------------------------------------
739 {
740  // reset state
741  m_loggedStreams.clear();
742 
743  for ( auto& iProp : m_loggedStreamsName ) {
744 
745  std::set<std::string> outFileNames;
746  for ( auto& jProp : m_loggedStreamsName ) {
747  if ( jProp.first != iProp.first ) {
748  outFileNames.insert( jProp.second );
749  }
750  }
751  tee( iProp.first, iProp.second, outFileNames );
752 
753  }//> loop over property entries
754 }
755 
756 // ---------------------------------------------------------------------------
757 void MessageSvc::tee( const std::string& sourceName,
758  const std::string& outFileName,
759  const std::set<std::string>& outFileNames )
760 {
761  const std::ios_base::openmode openMode = std::ios_base::out |
762  std::ios_base::trunc;
763 
764  auto iStream = m_loggedStreams.find( sourceName );
765  if ( iStream != std::end(m_loggedStreams) ) {
766  m_loggedStreams.erase( iStream );
767  }
768 
769  // before creating a new ofstream, make sure there is no already existing
770  // one with the same file name...
771  for (auto& iStream : m_loggedStreams ) {
772  if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
773  m_loggedStreams[sourceName] = m_loggedStreams[iStream.first];
774  return;
775  }
776  }
777 
778  auto out = std::make_shared<std::ofstream>( outFileName, openMode );
779  if ( out->good() ) m_loggedStreams[sourceName] = std::move(out);
780 
781 }
IntegerProperty m_msgLimit[MSG::NUM_LEVELS]
Definition: MessageSvc.h:148
const std::string & getFormat() const
Get the format string.
Definition: Message.cpp:176
tuple c
Definition: gaudirun.py:391
std::string colTrans(std::string, int)
Definition: MessageSvc.cpp:430
StatusCode initialize() override
Definition: Service.cpp:63
GAUDI_API void fill(AIDA::IHistogram1D *histo, const double value, const double weight=1.0)
simple function to fill AIDA::IHistogram1D objects
Definition: Fill.cpp:36
string to_string(const T &value)
Definition: mergesort.cpp:40
std::ostream * m_defaultStream
Pointer to the output stream.
Definition: MessageSvc.h:136
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
StreamMap m_streamMap
Stream map.
Definition: MessageSvc.h:138
std::array< int, MSG::NUM_LEVELS > m_msgCount
Definition: MessageSvc.h:167
unsigned long getCode() const
Get the status code by value.
Definition: StatusCode.h:93
virtual Property & declareUpdateHandler(std::function< void(Property &)> fun)
set new callback for update
Definition: Property.cpp:72
const std::string & name() const
property name
Definition: Property.h:45
virtual void i_reportMessage(const Message &msg, int outputLevel)
Internal implementation of reportMessage(const Message&,int) without lock.
Definition: MessageSvc.cpp:447
ColorMap m_colMap
Definition: MessageSvc.h:165
Message m_defaultMessage
Default Message.
Definition: MessageSvc.h:137
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:45
MessageMap m_messageMap
Message map.
Definition: MessageSvc.h:139
void setupLimits(Property &prop)
Definition: MessageSvc.cpp:241
void setupInactCount(Property &prop)
Definition: MessageSvc.cpp:305
STL namespace.
void setupLogStreams()
Definition: MessageSvc.cpp:738
bool setValue(const TYPE &value) override
implementation of PropertyWithValue::setValue
Definition: Property.h:406
MessageSvc(const std::string &name, ISvcLocator *svcloc)
Definition: MessageSvc.cpp:57
bool set(const TYPE &value)
update the value of the property/check the verifier
Definition: Property.h:434
std::recursive_mutex m_messageMapMutex
Mutex to synchronize multiple access to m_messageMap.
Definition: MessageSvc.h:187
int getType() const
Get the message type.
Definition: Message.cpp:93
StatusCode reinitialize() override
Reinitialize Service.
Definition: MessageSvc.cpp:154
std::pair< std::string, std::ostream * > NamedStream
Definition: MessageSvc.h:32
void eraseMessage() override
Definition: MessageSvc.cpp:654
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
UnsignedIntegerProperty m_statLevel
Definition: MessageSvc.h:146
void eraseStream() override
Definition: MessageSvc.cpp:588
void incrInactiveCount(MSG::Level level, const std::string &src) override
Definition: MessageSvc.cpp:731
std::map< std::string, std::shared_ptr< std::ostream > > m_loggedStreams
Definition: MessageSvc.h:170
std::map< std::string, MsgAry > m_sourceMap
Definition: MessageSvc.h:160
std::string getLogColor(int logLevel) const override
Definition: MessageSvc.cpp:717
void setOutputLevel(int new_level) override
Definition: MessageSvc.cpp:703
StatusCode initialize() override
Initialize Service.
Definition: MessageSvc.cpp:119
NamedRange_< CONTAINER > range(const CONTAINER &cnt, std::string name)
simple function to create the named range form arbitrary container
Definition: NamedRange.h:130
ThresholdMap m_thresholdMap
Output level threshold map.
Definition: MessageSvc.h:140
static const std::string getDefaultTimeFormat()
Get the default time format string.
Definition: Message.cpp:226
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:47
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
static const std::string getDefaultFormat()
Get the default format string.
Definition: Message.cpp:187
void reportMessage(const Message &message) override
Definition: MessageSvc.cpp:506
def lock(file)
Definition: locker.py:16
std::recursive_mutex m_reportMutex
Mutex to synchronize multiple threads printing.
Definition: MessageSvc.h:184
const TYPE & value() const
explicit conversion
Definition: Property.h:341
StringArrayProperty m_thresholdProp[MSG::NUM_LEVELS]
Properties controlling.
Definition: MessageSvc.h:143
void setFormat(std::string msg) const
Set the format string.
Definition: Message.cpp:200
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
The Message class.
Definition: Message.h:14
StatusCode finalize() override
Finalize Service.
Definition: MessageSvc.cpp:317
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition: Iterator.h:18
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
std::string m_defaultFormat
Default format for the messages.
Definition: MessageSvc.h:141
Print levels enumeration.
Definition: IMessageSvc.h:14
void setTimeFormat(std::string timeFormat) const
Set the time format string.
Definition: Message.cpp:239
void setupColors(Property &prop)
Definition: MessageSvc.cpp:191
std::map< std::string, MsgAry > m_inactiveMap
Definition: MessageSvc.h:160
void initColors(Property &prop)
Definition: MessageSvc.cpp:161
std::string m_logColorCodes[MSG::NUM_LEVELS]
Definition: MessageSvc.h:150
const std::string & getSource() const
Get the message source.
Definition: Message.cpp:115
int messageCount(MSG::Level logLevel) const override
Definition: MessageSvc.cpp:723
BooleanProperty m_color
Definition: MessageSvc.h:144
BooleanProperty m_inactCount
Definition: MessageSvc.h:161
int outputLevel() const override
Definition: MessageSvc.cpp:689
void tee(const std::string &sourceName, const std::string &logFileName, const std::set< std::string > &declaredOutFileNames)
Definition: MessageSvc.cpp:757
BooleanProperty m_stats
Definition: MessageSvc.h:145
std::map< std::string, std::string > m_loggedStreamsName
Definition: MessageSvc.h:169
void insertMessage(const StatusCode &code, const Message &message) override
Definition: MessageSvc.cpp:641
list i
Definition: ana.py:128
BooleanProperty m_suppress
Definition: MessageSvc.h:161
void setupThreshold(Property &prop)
Definition: MessageSvc.cpp:268
static GAUDI_API bool enableCountInactive(bool value=true)
Enable/disable the count of inactive messages.
Definition: MsgStream.cpp:32
std::string m_defaultTimeFormat
Default format for timestamps in the messages.
Definition: MessageSvc.h:142
void insertStream(int message_type, const std::string &name, std::ostream *stream) override
Definition: MessageSvc.cpp:574
string type
Definition: gaudirun.py:151
StringArrayProperty m_logColors[MSG::NUM_LEVELS]
Definition: MessageSvc.h:147
std::recursive_mutex m_thresholdMapMutex
Mutex to synchronize multiple access to m_thresholdMap (.
Definition: MessageSvc.h:191