ATLAS Offline Software
Loading...
Searching...
No Matches
LoggedMessageSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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#include <print>
17
18using namespace std;
19
20static const std::string levelNames[MSG::NUM_LEVELS] = {"NIL", "VERBOSE", "DEBUG", "INFO",
21 "WARNING", "ERROR", "FATAL", "ALWAYS"};
22
23// Constructor
24LoggedMessageSvc::LoggedMessageSvc( const std::string& name, ISvcLocator* svcloc )
25 : base_class( name, svcloc ), m_keysUsed(false)
26 {
27 m_defaultStream = &std::cout;
28 m_outputLevel = MSG::INFO;
29 declareProperty( "Format", m_defaultFormat = Message::getDefaultFormat() );
30 declareProperty( "timeFormat", m_defaultTimeFormat = Message::getDefaultTimeFormat() );
31 declareProperty( "showStats", m_stats = false );
32 declareProperty( "statLevel", m_statLevel = 0 );
33
34 // Special properties to control output level of individual sources
35 declareProperty( "setVerbose", m_thresholdProp[MSG::VERBOSE] );
36 declareProperty( "setDebug", m_thresholdProp[MSG::DEBUG] );
37 declareProperty( "setInfo", m_thresholdProp[MSG::INFO] );
38 declareProperty( "setWarning", m_thresholdProp[MSG::WARNING] );
39 declareProperty( "setError", m_thresholdProp[MSG::ERROR] );
40 declareProperty( "setFatal", m_thresholdProp[MSG::FATAL] );
41 declareProperty( "setAlways", m_thresholdProp[MSG::ALWAYS] );
42
43 declareProperty( "useColors", m_color=false);
44 m_color.declareUpdateHandler(&LoggedMessageSvc::initColors, this);
45
46 declareProperty( "fatalColorCode", m_logColors[MSG::FATAL] );
47 declareProperty( "errorColorCode", m_logColors[MSG::ERROR] );
48 declareProperty( "warningColorCode", m_logColors[MSG::WARNING] );
49 declareProperty( "infoColorCode", m_logColors[MSG::INFO] );
50 declareProperty( "debugColorCode", m_logColors[MSG::DEBUG] );
51 declareProperty( "verboseColorCode", m_logColors[MSG::VERBOSE] );
52 declareProperty( "alwaysColorCode", m_logColors[MSG::ALWAYS] );
53
54 const int defaultLimit = 500;
55 declareProperty( "fatalLimit", m_msgLimit[MSG::FATAL] = defaultLimit );
56 declareProperty( "errorLimit", m_msgLimit[MSG::ERROR] = defaultLimit );
57 declareProperty( "warningLimit", m_msgLimit[MSG::WARNING] = defaultLimit );
58 declareProperty( "infoLimit", m_msgLimit[MSG::INFO] = defaultLimit );
59 declareProperty( "debugLimit", m_msgLimit[MSG::DEBUG] = defaultLimit );
60 declareProperty( "verboseLimit", m_msgLimit[MSG::VERBOSE] = defaultLimit );
61 declareProperty( "alwaysLimit", m_msgLimit[MSG::ALWAYS] = 0 );
62
63 declareProperty( "defaultLimit", m_msgLimit[MSG::NIL] = defaultLimit );
64
65 declareProperty( "enableSuppression", m_suppress = false );
66 declareProperty( "countInactive", m_inactCount = false )->declareUpdateHandler( &LoggedMessageSvc::setupInactCount, this );
67#ifndef NDEBUG
68 // initialize the MsgStream static flag.
69 MsgStream::enableCountInactive(m_inactCount);
70#endif
71
72 declareProperty( "loggingLevel", m_logLevel = MSG::FATAL, "Message level above which all messages are saved" );
73 m_logLevel.declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
74
75 declareProperty( "keywords", m_keywords, "keywords to scan messages for and save");
76 m_keywords.declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
77
78 declareProperty( "loggedStreams",
80 "MessageStream sources we want to dump into a logfile" );
81
82 for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
83 m_logColors[ic].declareUpdateHandler(&LoggedMessageSvc::setupColors, this);
84 m_msgLimit[ic].declareUpdateHandler(&LoggedMessageSvc::setupLimits, this);
85 m_thresholdProp[ic].declareUpdateHandler(&LoggedMessageSvc::setupThreshold, this);
86 }
87
88 for (int i=0; i<MSG::NUM_LEVELS; ++i) {
89 m_msgCount[i] = 0;
90 }
91
92}
93
94//#############################################################################
95
97{
98 // closing log-files, if any
99 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.begin();
100 LoggedStreamsMap_t::iterator endStream = m_loggedStreams.end();
101 for ( ; iStream != endStream; ++iStream ) {
102 delete iStream->second;
103 iStream->second = nullptr;
104 }
105}
106//#############################################################################
107
108
111 StatusCode sc;
112 sc = base_class::initialize();
113 if( sc.isFailure() ) return sc;
114 // hack since in Gaudi v30, msgSvc() now returns a const SmartIF<IMessageSvc>
115 // Release pointer to myself done in Service base class
116 SmartIF<IMessageSvc> &si ATLAS_THREAD_SAFE = const_cast<SmartIF<IMessageSvc>&> (msgSvc());
117 si.reset();
118
119#ifdef _WIN32
120 m_color = false;
121#endif
122
123 m_colMap["black"] = MSG::BLACK;
124 m_colMap["red"] = MSG::RED;
125 m_colMap["green"] = MSG::GREEN;
126 m_colMap["yellow"] = MSG::YELLOW;
127 m_colMap["blue"] = MSG::BLUE;
128 m_colMap["purple"] = MSG::PURPLE;
129 m_colMap["cyan"] = MSG::CYAN;
130 m_colMap["white"] = MSG::WHITE;
131
132 // make sure the map of logged stream names is initialized
134
135 if (m_keywords.value().size() > 0) {
136 m_keysUsed = true;
137 }
138
139 return StatusCode::SUCCESS;
140}
141
142//#############################################################################
143
146 m_state = Gaudi::StateMachine::OFFLINE;
147 return initialize();
148}
149
150//#############################################################################
151
152void LoggedMessageSvc::initColors(Gaudi::Details::PropertyBase& /*prop*/) {
153
154 if (m_color == true) {
155
156 if (m_logColors[MSG::FATAL].value().size() == 0) {
157 vector<string> fatDef;
158 fatDef.push_back( "[94;101;1m" );
159 m_logColors[MSG::FATAL].set( fatDef );
160 } else {
162 }
163
164 if (m_logColors[MSG::ERROR].value().size() == 0) {
165 vector<string> errDef;
166 errDef.push_back( "[97;101;1m" );
167 m_logColors[MSG::ERROR].set( errDef );
168 } else {
170 }
171
172 if (m_logColors[MSG::WARNING].value().size() == 0) {
173 vector<string> warDef;
174 warDef.push_back( "[93;1m" );
175 m_logColors[MSG::WARNING].set( warDef );
176 } else {
178 }
179
180 } else {
181
182 // reset all color codes;
183 for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) {
184 vector<string> def;
185 m_logColors[ic].set( def );
186 }
187
188 }
189
190}
191
192//#############################################################################
193
194void LoggedMessageSvc::setupColors(Gaudi::Details::PropertyBase& prop) {
195
196 if (! m_color) return;
197
198 int ic;
199 if (prop.name() == "fatalColorCode") {
200 ic = MSG::FATAL;
201 } else if (prop.name() == "errorColorCode") {
202 ic = MSG::ERROR;
203 } else if (prop.name() == "warningColorCode") {
204 ic = MSG::WARNING;
205 } else if (prop.name() == "infoColorCode") {
206 ic = MSG::INFO;
207 } else if (prop.name() == "debugColorCode") {
208 ic = MSG::DEBUG;
209 } else if (prop.name() == "verboseColorCode") {
210 ic = MSG::VERBOSE;
211 } else if (prop.name() == "alwaysColorCode") {
212 ic = MSG::ALWAYS;
213 } else {
214 std::println ("ERROR: Unknown message color parameter: {}", prop.name());
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
245void 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 std::println ("LoggedMessageSvc ERROR: cannot suppress ALWAYS messages");
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 std::println ("LoggedMessageSvc ERROR: Unknown message limit parameter: {}",
275 prop.name());
276 return;
277 }
278
279}
280//#############################################################################
281
282void 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 std::println (cerr, "LoggedMessageSvc ERROR: Unknown message theshold parameter: {}",
314 prop.name());
315 return;
316 }
317
318 StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop);
319 if (sap == nullptr) {
320 std::println (std::cerr, "could not dcast {} to a StringArrayProperty (which it should be!)",
321 prop.name());
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
336void 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#define PR(FMT, ...) std::println(os, FMT __VA_OPT__(,) __VA_ARGS__)
353
354 {
355 std::ostringstream os;
356
357 if (m_stats) {
358 PR ("Summarizing all message counts");
359 } else {
360 PR ("Listing sources of suppressed message: ");
361 }
362
363 PR ("=====================================================");
364 PR (" Message Source | Level | Count");
365 PR ("-----------------------------+---------+-------------");
366
367
368 bool found(false);
369
370 std::lock_guard<std::mutex> lock(m_reportMutex);
371 std::map<std::string,MsgAry>::const_iterator itr;
372 for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) {
373 for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
374 if ( (itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
375 (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value()) ) {
376 PR (" {:<28}|{:>8}|{:>9}",
377 itr->first, levelNames[ic], itr->second.msg[ic]);
378
379 found = true;
380 }
381 }
382 }
383 PR ("=====================================================");
384
385 if (found || m_stats) {
386 cout << os.str();
387 }
388 }
389
390
391#ifndef NDEBUG
392 if (m_inactCount.value()) {
393
394 std::ostringstream os;
395 PR ("Listing sources of Unprotected and Unseen messages");
396
397 bool found(false);
398
399 unsigned int ml(0);
400 std::map<std::string,MsgAry>::const_iterator itr;
401 for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
402 for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
403 if (itr->second.msg[ic] != 0) {
404 if (itr->first.length() > ml) { ml = itr->first.length(); }
405 }
406 }
407 }
408
409 for (unsigned int i=0; i<ml+25; ++i) {
410 os << "=";
411 }
412
413 PR("");
414 PR(" {:<{}}| Level | Count", "MessageSource", ml+2);
415
416 for (unsigned int i=0; i<ml+3; ++i) {
417 os << "-";
418 }
419 PR ("+---------+-----------");
420
421
422 for (itr=m_inactiveMap.begin(); itr!=m_inactiveMap.end(); ++itr) {
423 for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
424 if (itr->second.msg[ic] != 0) {
425 PR (" {:<{}}|{:>8}|{:>9}",
426 itr->first, ml+2, levelNames[ic], itr->second.msg[ic]);
427 found = true;
428 }
429 }
430 }
431 for (unsigned int i=0; i<ml+25; ++i) {
432 os << "=";
433 }
434 PR("");
435
436 if (found) {
437 cout << os.str();
438 }
439 }
440#endif
441#undef PR
442
443 return StatusCode::SUCCESS;
444}
445
446//#############################################################################
447std::string LoggedMessageSvc::colTrans(const std::string &col, int offset) {
448 ColorMap::const_iterator itr = m_colMap.find(col);
449 int icol;
450 if (itr != m_colMap.end()) {
451 icol = offset + itr->second;
452 } else {
453 icol = offset + 8;
454 }
455 return std::to_string (icol);
456
457}
458
459//#############################################################################
460// ---------------------------------------------------------------------------
461// Routine: reportMessage
462// Purpose: dispatches a message to the relevant streams.
463// ---------------------------------------------------------------------------
464//
465
467 std::lock_guard<std::mutex> lock(m_reportMutex);
468
469 int key = msg.getType();
470 int nmsg;
471
472 m_msgCount[key] ++;
473
474 if (outputLevel >= m_logLevel) {
475 m_msgLog[ outputLevel ].push_back( make_pair (msg.getSource(), msg.getMessage() ) );
476 }
477
478 if (m_keysUsed) {
479 if (msg.getSource() != "AthenaSummarySvc") {
480 for (vector<string>::const_iterator itr=m_keywords.value().begin(); itr!= m_keywords.value().end(); ++itr) {
481 if (msg.getMessage().find( *itr ) != string::npos) {
482 m_msgKeyLog.push_back( LoggedMessage( outputLevel, msg.getSource(), msg.getMessage() ));
483 break;
484 }
485 }
486 }
487 }
488
489 const Message *cmsg = &msg;
490 std::unique_ptr<Message> suppressed_msg;
491
492 // processing logged streams
493 if ( !m_loggedStreams.empty() ) {
494 const LoggedStreamsMap_t::iterator iLog = m_loggedStreams.find( msg.getSource() );
495 if ( m_loggedStreams.end() != iLog ) {
496 (*iLog->second) << *cmsg << std::endl;
497 }
498 }
499
500 if ( m_suppress.value() || m_stats.value() ) {
501
502 std::map<std::string,MsgAry>::iterator itr =
503 m_sourceMap.find(msg.getSource());
504 if (itr != m_sourceMap.end()) {
505 itr->second.msg[key] += 1;
506 nmsg = itr->second.msg[key];
507 } else {
508 MsgAry A;
509 for (int i=0; i<MSG::NUM_LEVELS; ++i) {
510 A.msg[i] = 0;
511 }
512 A.msg[key] = 1;
513 m_sourceMap[msg.getSource()] = A;
514 nmsg = 1;
515 }
516
517 if (m_suppress.value()) {
518
519 if ( m_msgLimit[key] != 0 ) {
520 if (nmsg == m_msgLimit[key]) {
521 std::string str = levelNames[key] + " message limit (";
522 str += std::to_string( m_msgLimit[key].value() );
523 str += ") reached for ";
524 str += msg.getSource() + ". Suppressing further output.";
525 suppressed_msg = std::make_unique<Message>(msg.getSource(),MSG::WARNING,str);
526 suppressed_msg->setFormat(msg.getFormat());
527 cmsg = suppressed_msg.get();
528 } else if (nmsg > m_msgLimit[key]) {
529 return;
530 }
531 }
532 }
533
534 }
535
536 StreamMap::const_iterator first = m_streamMap.lower_bound( key );
537 if ( first != m_streamMap.end() ) {
538 StreamMap::const_iterator last = m_streamMap.upper_bound( key );
539 while( first != last ) {
540 std::ostream& stream = *( (*first).second.second );
541 stream << *cmsg << std::endl;
542 ++first;
543 }
544 }
545 else if ( key >= outputLevel ) {
546 msg.setFormat(m_defaultFormat);
547 msg.setTimeFormat(m_defaultTimeFormat);
548 if (!m_color) {
549 (*m_defaultStream) << *cmsg << std::endl << std::flush;
550 } else {
551 (*m_defaultStream) << m_logColorCodes[key] << *cmsg << "\033[m"
552 << std::endl << std::flush;
553 }
554 }
555}
556
557//#############################################################################
558// ---------------------------------------------------------------------------
559// Routine: reportMessage
560// Purpose: dispatches a message to the relevant streams.
561// ---------------------------------------------------------------------------
562//
563void LoggedMessageSvc::reportMessage( const Message& msg ) {
564 reportMessage(msg, outputLevel(msg.getSource()));
565}
566
567//#############################################################################
568// ---------------------------------------------------------------------------
569// Routine: reportMessage
570// Purpose: dispatches a message to the relevant streams.
571// ---------------------------------------------------------------------------
572//
573void LoggedMessageSvc::reportMessage (std::string source,
574 int type,
575 std::string message) {
576 Message msg( std::move(source), type, std::move(message));
578}
579
580//#############################################################################
581// ---------------------------------------------------------------------------
582// Routine: sendMessage
583// Purpose: finds a message for a given status code and dispatches it.
584// ---------------------------------------------------------------------------
585//
586
587void LoggedMessageSvc::reportMessage (const StatusCode& key,
588 std::string_view source)
589{
590 std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
591
592 MessageMap::const_iterator first = m_messageMap.lower_bound( key );
593 if ( first != m_messageMap.end() ) {
594 MessageMap::const_iterator last = m_messageMap.upper_bound( key );
595 while( first != last ) {
596 Message msg = (*first).second;
597 msg.setSource( source );
598 std::ostringstream os1;
599 os1 << "Status Code " << key.getCode() << std::ends;
600 Message stat_code1( std::string{source}, msg.getType(), os1.str() );
601 reportMessage( stat_code1 );
603 ++first;
604 }
605 }
606 else {
607 Message mesg = m_defaultMessage;
608 mesg.setSource( source );
609 std::ostringstream os2;
610 os2 << "Status Code " << key.getCode() << std::ends;
611 Message stat_code2( std::string{source}, mesg.getType(), os2.str() );
612 reportMessage( stat_code2 );
613 reportMessage( mesg );
614 }
615}
616
617//#############################################################################
618// ---------------------------------------------------------------------------
619// Routine: insertStream
620// Purpose: inserts a stream for a message type.
621// ---------------------------------------------------------------------------
622//
623
625 std::string name,
626 std::ostream *stream)
627{
628 typedef StreamMap::value_type value_type;
629 m_streamMap.insert( value_type( key, NamedStream( std::move(name), stream) ) );
630}
631
632//#############################################################################
633// ---------------------------------------------------------------------------
634// Routine: eraseStream
635// Purpose: erases all the streams for all the message types.
636// ---------------------------------------------------------------------------
637//
638
640{
641 m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() );
642}
643
644//#############################################################################
645// ---------------------------------------------------------------------------
646// Routine: eraseStream
647// Purpose: erases all the streams for a message type.
648// ---------------------------------------------------------------------------
649//
650
651void LoggedMessageSvc::eraseStream( int message_type )
652{
653 m_streamMap.erase( message_type );
654}
655
656//#############################################################################
657// ---------------------------------------------------------------------------
658// Routine: eraseStream
659// Purpose: erases one stream for a message type.
660// ---------------------------------------------------------------------------
661//
662
663void LoggedMessageSvc::eraseStream( int key, std::ostream* stream ) {
664 if ( nullptr != stream ) {
665 bool changed = true;
666 while( changed ) {
667 changed = false;
668 StreamMap::iterator first = m_streamMap.lower_bound( key );
669 StreamMap::iterator last = m_streamMap.upper_bound( key );
670 while( first != last ) {
671 if ( (*first).second.second == stream ) {
672 m_streamMap.erase( first );
673 changed = true;
674 break;
675 }
676 }
677 }
678 }
679}
680
681//#############################################################################
682// ---------------------------------------------------------------------------
683// Routine: eraseStream
684// Purpose: erases one stream for all message types.
685// ---------------------------------------------------------------------------
686//
687
688void LoggedMessageSvc::eraseStream( std::ostream* stream ) {
689 if ( nullptr != stream ) {
690 bool changed = true;
691 while( changed ) {
692 changed = false;
693 StreamMap::iterator first = m_streamMap.begin();
694 while( first != m_streamMap.end() ) {
695 if ( (*first).second.second == stream ) {
696 m_streamMap.erase( first );
697 changed = true;
698 break;
699 }
700 }
701 }
702 }
703}
704
705
706//#############################################################################
707// ---------------------------------------------------------------------------
708// Routine: insertMessage
709// Purpose: inserts a message for a status code.
710// ---------------------------------------------------------------------------
711//
712
713void LoggedMessageSvc::insertMessage( const StatusCode& key, Message msg )
714{
715 std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
716
717 m_messageMap.emplace( key, std::move( msg ) );
718}
719
720//#############################################################################
721// ---------------------------------------------------------------------------
722// Routine: eraseMessage
723// Purpose: erases all the messages for all the status codes.
724// ---------------------------------------------------------------------------
725//
726
728{
729 std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
730
731 m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() );
732}
733
734//#############################################################################
735// ---------------------------------------------------------------------------
736// Routine: eraseMessage
737// Purpose: erases all the messages for a status code.
738// ---------------------------------------------------------------------------
739//
740
741void LoggedMessageSvc::eraseMessage( const StatusCode& key )
742{
743 std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
744
745 m_messageMap.erase( key );
746}
747
748//#############################################################################
749// ---------------------------------------------------------------------------
750// Routine: eraseMessage
751// Purpose: erases one message for a status code.
752// ---------------------------------------------------------------------------
753//
754
755void LoggedMessageSvc::eraseMessage( const StatusCode& key, const Message& msg )
756{
757 std::lock_guard<std::recursive_mutex> lock(m_messageMapMutex);
758
759 bool changed = true;
760 while( changed ) {
761 changed = false;
762 MessageMap::iterator first = m_messageMap.lower_bound( key );
763 MessageMap::iterator last = m_messageMap.upper_bound( key );
764 while( first != last ) {
765 const Message& message = (*first).second;
766 if ( message == msg ) {
767 m_messageMap.erase( first );
768 changed = true;
769 break;
770 }
771 }
772 }
773}
774
775// ---------------------------------------------------------------------------
777// ---------------------------------------------------------------------------
778 return m_outputLevel;
779}
780// ---------------------------------------------------------------------------
781int LoggedMessageSvc::outputLevel( std::string_view source ) const {
782// ---------------------------------------------------------------------------
783 std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
784
785 auto it = m_thresholdMap.find( source );
786 return it != m_thresholdMap.end() ? it->second : m_outputLevel.value();
787}
788
789// ---------------------------------------------------------------------------
791// ---------------------------------------------------------------------------
792 m_outputLevel = new_level;
793}
794
795// ---------------------------------------------------------------------------
796void LoggedMessageSvc::setOutputLevel(std::string_view source, int level) {
797// ---------------------------------------------------------------------------
798 std::lock_guard<std::mutex> lock(m_thresholdMapMutex);
799
800 // only write if we really have to...
801 auto i = m_thresholdMap.find( source );
802 if ( i == m_thresholdMap.end() ) {
803 m_thresholdMap.emplace( source, level );
804 } else if ( i->second != level ) {
805 i->second = level;
806 }
807
808}
809
810// ---------------------------------------------------------------------------
811std::string LoggedMessageSvc::getLogColor(int logLevel) const {
812// ---------------------------------------------------------------------------
813 if (logLevel < MSG::NUM_LEVELS) {
814 return m_logColorCodes[logLevel];
815 } else {
816 return "";
817 }
818}
819
820// ---------------------------------------------------------------------------
821int LoggedMessageSvc::messageCount( MSG::Level level) const {
822
823 return m_msgCount[level];
824
825}
826
827// ---------------------------------------------------------------------------
828void
829LoggedMessageSvc::incrInactiveCount(MSG::Level level, std::string_view source) {
830
831 auto entry = m_inactiveMap.find( source );
832 if ( entry == m_inactiveMap.end() ) {
833 entry = m_inactiveMap.emplace( source, MsgAry{} ).first;
834 }
835 ++entry->second.msg[level];
836}
837
838// ---------------------------------------------------------------------------
840{
841 // reset state
842 for ( LoggedStreamsMap_t::iterator iLog = m_loggedStreams.begin();
843 iLog != m_loggedStreams.end();
844 ++iLog ) {
845 delete iLog->second;
846 }
847 m_loggedStreams.clear();
848
849 typedef std::map<std::string,std::string> StreamMap_t;
850 const StreamMap_t& streamMap = m_loggedStreamsName;
851 typedef StreamMap_t::const_iterator StreamMapIter;
852
853 for ( StreamMapIter iProp = streamMap.begin(), iEnd = streamMap.end();
854 iProp != iEnd;
855 ++iProp ) {
856
857 const std::string sourceName = iProp->first;
858 const std::string outFileName = iProp->second;
859
860 std::set<std::string> outFileNames;
861 for ( StreamMapIter jProp = streamMap.begin();
862 jProp != iEnd;
863 ++jProp ) {
864 if ( jProp->first != iProp->first ) {
865 outFileNames.insert( jProp->second );
866 }
867 }
868
869 tee( sourceName, outFileName, outFileNames );
870
871 }//> loop over property entries
872
873 return;
874}
875
876// ---------------------------------------------------------------------------
877void LoggedMessageSvc::tee( const std::string& sourceName,
878 const std::string& outFileName,
879 const std::set<std::string>& outFileNames )
880{
881 const std::ios_base::openmode openMode = std::ios_base::out |
882 std::ios_base::trunc;
883
884 LoggedStreamsMap_t::iterator iEnd = m_loggedStreams.end();
885 LoggedStreamsMap_t::iterator iStream = m_loggedStreams.find( sourceName );
886 if ( iStream != iEnd ) {
887 delete iStream->second;
888 iStream->second = nullptr;
889 m_loggedStreams.erase( iStream );
890 }
891
892 // before creating a new ofstream, make sure there is no already existing
893 // one with the same file name...
894 iEnd = m_loggedStreams.end();
895 for ( iStream = m_loggedStreams.begin(); iStream != iEnd; ++iStream ) {
896 if ( outFileNames.find( outFileName ) != outFileNames.end() ) {
897 m_loggedStreams[sourceName] = m_loggedStreams[iStream->first];
898 return;
899 }
900 }
901
902 std::ofstream * out = new std::ofstream( outFileName.c_str(), openMode );
903
904 if ( !out->good() ) {
905 out->close();
906 delete out;
907 return;
908 }
909
910 m_loggedStreams[sourceName] = out;
911
912 return;
913}
914
915
916//#############################################################################
917// ---------------------------------------------------------------------------
918// Routine: getMessages
919// Purpose: get all messages of a certain MSG::Level
920// ---------------------------------------------------------------------------
921
922std::vector< std::pair<std::string, std::string> >
923LoggedMessageSvc::getMessages( MSG::Level level) const
924{
925 std::lock_guard<std::mutex> lock(m_reportMutex);
926 return m_msgLog[ level ];
927}
928
929
931 -> std::vector< LoggedMessage >
932{
933 std::lock_guard<std::mutex> lock(m_reportMutex);
934 return m_msgKeyLog;
935}
936
static constexpr std::string levelNames[MSG::NUM_LEVELS]
#define PR(FMT,...)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t sc
size_t size() const
Number of registered mappings.
#define ATLAS_THREAD_SAFE
MessageMap m_messageMap
Message map.
void initColors(Gaudi::Details::PropertyBase &prop)
virtual void insertStream(int message_type, std::string name, std::ostream *stream) override
virtual int messageCount(MSG::Level logLevel) const override
LoggedStreamsMap_t m_loggedStreams
void setupLimits(Gaudi::Details::PropertyBase &prop)
virtual void eraseStream() override
LoggedMessageSvc(const std::string &name, ISvcLocator *svcloc)
StreamMap m_streamMap
Stream map.
void setupColors(Gaudi::Details::PropertyBase &prop)
UnsignedIntegerProperty m_statLevel
void tee(const std::string &sourceName, const std::string &logFileName, const std::set< std::string > &declaredOutFileNames)
virtual StatusCode initialize() override
Initialize Service.
std::mutex m_reportMutex
Mutex to synchronize multiple threads printing.
virtual void setOutputLevel(int new_level) override
std::vector< LoggedMessage > m_msgKeyLog
BooleanProperty m_color
std::pair< std::string, std::ostream * > NamedStream
virtual std::string getLogColor(int logLevel) const override
IntegerProperty m_msgLimit[MSG::NUM_LEVELS]
virtual StatusCode reinitialize() override
Reinitialize Service.
std::vector< std::pair< std::string, std::string > > m_msgLog[MSG::NUM_LEVELS]
std::map< std::string, MsgAry, std::less<> > m_sourceMap
BooleanProperty m_inactCount
Message m_defaultMessage
Default Message.
virtual StatusCode finalize() override
Finalize Service.
ThresholdMap m_thresholdMap
Output level threshold map.
virtual std::vector< std::pair< std::string, std::string > > getMessages(MSG::Level level) const override
std::mutex m_thresholdMapMutex
Mutex to synchronize multiple access to m_thresholdMap (.
int m_msgCount[MSG::NUM_LEVELS]
StringArrayProperty m_thresholdProp[MSG::NUM_LEVELS]
Properties controling.
std::string m_defaultTimeFormat
Default format for timestamps in the messages.
virtual void reportMessage(const Message &message) override
StringArrayProperty m_logColors[MSG::NUM_LEVELS]
std::string colTrans(const std::string &, int)
std::map< std::string, MsgAry, std::less<> > m_inactiveMap
virtual void insertMessage(const StatusCode &code, Message message) override
virtual int outputLevel() const override
std::ostream * m_defaultStream
Pointer to the output stream.
std::map< std::string, std::string > m_loggedStreamsName
IntegerProperty m_logLevel
void setupThreshold(Gaudi::Details::PropertyBase &prop)
void setupInactCount(Gaudi::Details::PropertyBase &prop)
virtual std::vector< LoggedMessage > getKeyMessages() const override
std::string m_logColorCodes[MSG::NUM_LEVELS]
BooleanProperty m_stats
std::string m_defaultFormat
Default format for the messages.
StringArrayProperty m_keywords
virtual void incrInactiveCount(MSG::Level level, std::string_view src) override
BooleanProperty m_suppress
std::recursive_mutex m_messageMapMutex
Mutex to synchronize multiple access to m_messageMap.
virtual void eraseMessage() override
STL namespace.
hold the test vectors and ease the comparison
Private helper class to keep the count of messages of a type (MSG::LEVEL).
MsgStream & msg
Definition testRead.cxx:32