The Gaudi Framework  master (905e8f18)
Loading...
Searching...
No Matches
MessageSvc.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11
12#include "MessageSvc.h"
14#include <GaudiKernel/Kernel.h>
15#include <GaudiKernel/Message.h>
17#include <GaudiKernel/System.h>
18
19#include <fstream>
20#include <iostream>
21#include <sstream>
22
23namespace {
24
25 // erase_if functions for containers which do NOT invalidate iterators
26 // after the erase point, eg.std::{unordered_}{,multi}map, std::{forward_,}list.
27 // To be explicit: this does NOT work with std::vector.
28
29 // TODO: replace with std::experimental::erase_if (Libraries Fundamental TS v2)
30
31 template <typename Container, typename Iterator, typename Predicate>
32 void erase_if( Container& c, Iterator first, Iterator last, Predicate pred ) {
33 while ( first != last ) {
34 if ( pred( *first ) )
35 first = c.erase( first );
36 else
37 ++first;
38 }
39 }
40
41 template <typename Container, typename Iterator, typename Predicate>
42 void erase_if( Container& c, std::pair<Iterator, Iterator> range, Predicate pred ) {
43 return erase_if( c, std::move( range.first ), std::move( range.second ), std::forward<Predicate>( pred ) );
44 }
45
46 std::string colTrans( std::string_view col, int offset ) {
47 int icol = ( col == "black" ? MSG::BLACK
48 : col == "red" ? MSG::RED
49 : col == "green" ? MSG::GREEN
50 : col == "yellow" ? MSG::YELLOW
51 : col == "blue" ? MSG::BLUE
52 : col == "purple" ? MSG::PURPLE
53 : col == "cyan" ? MSG::CYAN
54 : col == "white" ? MSG::WHITE
55 : 8 );
56 return std::to_string( icol + offset );
57 }
58} // namespace
59
61
62static const std::string levelNames[MSG::NUM_LEVELS] = { "NIL", "VERBOSE", "DEBUG", "INFO",
63 "WARNING", "ERROR", "FATAL", "ALWAYS" };
64
65MessageSvc::MessageSvc( const std::string& name, ISvcLocator* svcloc ) : base_class( name, svcloc ) {
66
67 m_outputLevel.declareUpdateHandler( [svcloc]( Gaudi::Details::PropertyBase& ) {
68 SmartIF<IAppMgrUI> app = svcloc;
69 if ( app ) app->outputLevelUpdate();
70 } );
71
72#ifndef NDEBUG
73 // initialize the MsgStream static flag.
75#endif
76
77 for ( int ic = 0; ic < MSG::NUM_LEVELS; ++ic ) {
78 m_logColors[ic].declareUpdateHandler( &MessageSvc::setupColors, this );
79 m_msgLimit[ic].declareUpdateHandler( &MessageSvc::setupLimits, this );
80 m_thresholdProp[ic].declareUpdateHandler( &MessageSvc::setupThreshold, this );
81 }
82
83 m_logColors[MSG::FATAL].set( { "blue", "red" } );
84 m_logColors[MSG::ERROR].set( { "white", "red" } );
85 m_logColors[MSG::WARNING].set( { "yellow" } );
86
87 std::fill( std::begin( m_msgCount ), std::end( m_msgCount ), 0 );
88}
89
92 if ( sc.isFailure() ) return sc;
93
94 // make sure the map of logged stream names is initialized
96
98}
99
107
109 const auto& pname = prop.name();
110 int level =
111 ( pname == "fatalColorCode" ? MSG::FATAL
112 : pname == "errorColorCode" ? MSG::ERROR
113 : pname == "warningColorCode" ? MSG::WARNING
114 : pname == "infoColorCode" ? MSG::INFO
115 : pname == "debugColorCode" ? MSG::DEBUG
116 : pname == "verboseColorCode" ? MSG::VERBOSE
117 : pname == "alwaysColorCode"
119 : ( throw GaudiException( "ERROR: Unknown message color parameter: " + pname, name(), StatusCode::FAILURE ),
120 -1 ) );
121
122 auto& code = m_logColorCodes[level];
123
124 const auto& col_desc = m_logColors[level].value();
125
126 if ( col_desc.size() == 1 ) {
127 const std::string& desc = col_desc[0];
128 if ( desc.empty() ) {
129 code = "";
130 } else if ( desc[0] == '[' ) {
131 code = "\033" + desc;
132 } else {
133 code = "\033[" + colTrans( desc, 90 ) + ";1m";
134 }
135 } else if ( col_desc.size() == 2 ) {
136 code = "\033[" + colTrans( col_desc[0], 90 ) + ";" + colTrans( col_desc[1], 100 ) + ";1m";
137 } else { // empty desc: no color
138 code = "";
139 }
140}
141
143 // Just report problems in the settings of the limits and unknown limit parameters
144 if ( prop.name() == "alwaysLimit" ) {
145 Gaudi::Property<int>* p = dynamic_cast<Gaudi::Property<int>*>( &prop );
146 if ( p && p->value() != 0 ) {
147 std::cout << "MessageSvc ERROR: cannot suppress ALWAYS messages" << std::endl;
148 p->setValue( 0 );
149 }
150 } else if ( prop.name() == "defaultLimit" ) {
151 for ( int i = MSG::VERBOSE; i < MSG::NUM_LEVELS; ++i ) {
152 if ( i != MSG::ALWAYS ) { m_msgLimit[i] = m_msgLimit[MSG::NIL].value(); }
153 }
154 } else if ( prop.name() != "fatalLimit" && prop.name() != "errorLimit" && prop.name() != "warningLimit" &&
155 prop.name() == "infoLimit" && prop.name() == "debugLimit" && prop.name() == "verboseLimit" ) {
156 std::cout << "MessageSvc ERROR: Unknown message limit parameter: " << prop.name() << std::endl;
157 return;
158 }
159}
160
162
163 static const std::array<std::pair<const char*, MSG::Level>, 7> tbl{ { { "setFatal", MSG::FATAL },
164 { "setError", MSG::ERROR },
165 { "setWarning", MSG::WARNING },
166 { "setInfo", MSG::INFO },
167 { "setDebug", MSG::DEBUG },
168 { "setVerbose", MSG::VERBOSE },
169 { "setAlways", MSG::ALWAYS } } };
170
171 auto i = std::find_if( std::begin( tbl ), std::end( tbl ),
172 [&]( const std::pair<const char*, MSG::Level>& t ) { return prop.name() == t.first; } );
173 if ( i == std::end( tbl ) ) {
174 std::cerr << "MessageSvc ERROR: Unknown message threshold parameter: " << prop.name() << std::endl;
175 return;
176 }
177 int ic = i->second;
178
180 if ( !sap ) {
181 std::cerr << "could not dcast " << prop.name()
182 << " to a Gaudi::Property<std::vector<std::string>> (which it should be!)" << std::endl;
183 } else {
184 for ( auto& i : sap->value() ) setOutputLevel( i, ic );
185 }
186}
187
188#ifdef NDEBUG
190#else
192 if ( prop.name() == "countInactive" ) {
193 Gaudi::Property<bool>* p = dynamic_cast<Gaudi::Property<bool>*>( &prop );
194 if ( p ) MsgStream::enableCountInactive( p->value() );
195 }
196}
197#endif
198
200 m_suppress = false;
201
202 {
203 std::ostringstream os;
204
205 if ( m_stats ) {
206 os << "Summarizing all message counts" << std::endl;
207 } else {
208 os << "Listing sources of suppressed message: " << std::endl;
209 }
210
211 os << "=====================================================" << std::endl;
212 os << " Message Source | Level | Count" << std::endl;
213 os << "-----------------------------+---------+-------------" << std::endl;
214
215 bool found( false );
216
217 for ( auto itr = m_sourceMap.begin(); itr != m_sourceMap.end(); ++itr ) {
218 for ( unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic ) {
219 if ( ( itr->second.msg[ic] >= m_msgLimit[ic] && m_msgLimit[ic] != 0 ) ||
220 ( m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value() ) ) {
221 os << " ";
222 os.width( 28 );
223 os.setf( std::ios_base::left, std::ios_base::adjustfield );
224 os << itr->first;
225 os << "|";
226
227 os.width( 8 );
228 os.setf( std::ios_base::right, std::ios_base::adjustfield );
229 os << levelNames[ic];
230 os << " |";
231
232 os.width( 9 );
233 os << itr->second.msg[ic];
234 os << std::endl;
235
236 found = true;
237 }
238 }
239 }
240 os << "=====================================================" << std::endl;
241 if ( found || m_stats ) std::cout << os.str() << std::flush;
242 }
243
244#ifndef NDEBUG
245 if ( m_inactCount.value() ) {
246
247 std::ostringstream os;
248 os << "Listing sources of Unprotected and Unseen messages\n";
249
250 bool found( false );
251
252 unsigned int ml( 0 );
253 for ( const auto& itr : m_inactiveMap ) {
254 for ( unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic ) {
255 if ( itr.second.msg[ic] != 0 && itr.first.length() > ml ) { ml = itr.first.length(); }
256 }
257 }
258
259 for ( unsigned int i = 0; i < ml + 25; ++i ) os << "=";
260
261 os << std::endl << " ";
262 os.width( ml + 2 );
263 os.setf( std::ios_base::left, std::ios_base::adjustfield );
264 os << "Message Source";
265 os.width( 1 );
266 os << "| Level | Count" << std::endl;
267
268 for ( unsigned int i = 0; i < ml + 3; ++i ) os << "-";
269 os << "+---------+-----------" << std::endl;
270
271 for ( auto itr = m_inactiveMap.begin(); itr != m_inactiveMap.end(); ++itr ) {
272 for ( unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic ) {
273 if ( itr->second.msg[ic] != 0 ) {
274 os << " ";
275 os.width( ml + 2 );
276 os.setf( std::ios_base::left, std::ios_base::adjustfield );
277 os << itr->first;
278
279 os << "|";
280
281 os.width( 8 );
282 os.setf( std::ios_base::right, std::ios_base::adjustfield );
283 os << levelNames[ic];
284
285 os << " |";
286
287 os.width( 9 );
288 os << itr->second.msg[ic];
289
290 os << std::endl;
291
292 found = true;
293 }
294 }
295 }
296 for ( unsigned int i = 0; i < ml + 25; ++i ) os << "=";
297 os << std::endl;
298
299 if ( found ) std::cout << os.str() << std::flush;
300 }
301#endif
302
303 return StatusCode::SUCCESS;
304}
305
307 auto lock = std::scoped_lock{ m_reportMutex };
309}
310
312 int key = msg.getType();
313
314 ++m_msgCount[key];
315
316 const Message* cmsg = &msg;
317
318 // processing logged streams
319 if ( !m_loggedStreams.empty() ) {
320 auto iLog = m_loggedStreams.find( msg.getSource() );
321 if ( m_loggedStreams.end() != iLog ) { ( *iLog->second ) << *cmsg << std::endl; }
322 }
323
324 if ( m_suppress || m_stats.value() ) {
325
326 // Increase the counter of 'key' type of messages for the source and
327 // get the new value.
328 const int nmsg = ++( m_sourceMap[msg.getSource()].msg[key] );
329
330 if ( m_suppress && m_msgLimit[key] != 0 ) {
331 if ( nmsg > m_msgLimit[key] ) return;
332 if ( nmsg == m_msgLimit[key] ) {
333 std::string txt = levelNames[key] + " message limit (" + std::to_string( m_msgLimit[key].value() ) +
334 ") reached for " + msg.getSource() + ". Suppressing further output.";
335 cmsg = new Message( msg.getSource(), MSG::WARNING, std::move( txt ) );
336 cmsg->setFormat( msg.getFormat() );
337 }
338 }
339 }
340
341 auto range = m_streamMap.equal_range( key );
342 if ( range.first != m_streamMap.end() ) {
343 std::for_each( range.first, range.second,
344 [&]( StreamMap::const_reference sm ) { *sm.second.second << *cmsg << std::endl; } );
345 } else if ( key >= outputLevel ) {
346 msg.setFormat( m_defaultFormat );
347 msg.setTimeFormat( m_defaultTimeFormat );
348 if ( !m_color ) {
349 ( *m_defaultStream ) << *cmsg << std::endl << std::flush;
350 } else {
351 ( *m_defaultStream ) << m_logColorCodes[key] << *cmsg << "\033[m" << std::endl << std::flush;
352 }
353 }
354
355 if ( cmsg != &msg ) { delete cmsg; } // cppcheck-suppress autovarInvalidDeallocation; false positive
356}
357
359
360StatusCode MessageSvc::setPropertyRepr( const std::string& n, const std::string& r ) {
361 auto lock = std::scoped_lock{ m_reportMutex };
362 return Service::setPropertyRepr( n, r );
363}
364
365void MessageSvc::reportMessage( std::string source, int type, std::string message ) {
366 reportMessage( Message{ std::move( source ), type, std::move( message ) } );
367}
368
369void MessageSvc::reportMessage( const StatusCode& code, std::string_view source ) {
370 auto lock = std::scoped_lock{ m_messageMapMutex };
371 i_reportMessage( code, source );
372}
373
374void MessageSvc::i_reportMessage( const StatusCode& code, std::string_view source ) {
375 int level = outputLevel( source );
376 auto report = [&]( Message mesg ) {
377 mesg.setSource( source );
378 Message stat_code( std::string{ source }, mesg.getType(), "Status Code " + std::to_string( code.getCode() ) );
379 i_reportMessage( std::move( stat_code ), level );
380 i_reportMessage( std::move( mesg ), level );
381 };
382
383 auto range = m_messageMap.equal_range( code );
384 if ( range.first != m_messageMap.end() ) {
385 std::for_each( range.first, range.second, [&]( MessageMap::const_reference sm ) { report( sm.second ); } );
386 } else {
387 report( m_defaultMessage );
388 }
389}
390
391void MessageSvc::insertStream( int key, std::string name, std::ostream* stream ) {
392 m_streamMap.emplace( key, NamedStream( std::move( name ), stream ) );
393}
394
396
397void MessageSvc::eraseStream( int message_type ) { m_streamMap.erase( message_type ); }
398
399void MessageSvc::eraseStream( int key, std::ostream* stream ) {
400 if ( stream ) {
401 erase_if( m_streamMap, m_streamMap.equal_range( key ),
402 [&]( StreamMap::const_reference j ) { return j.second.second == stream; } );
403 }
404}
405
406void MessageSvc::eraseStream( std::ostream* stream ) {
407 if ( stream ) {
408 erase_if( m_streamMap, [&]( StreamMap::const_reference j ) { return j.second.second == stream; } );
409 }
410}
411
413 auto lock = std::scoped_lock{ m_messageMapMutex };
414 m_messageMap.emplace( key, std::move( msg ) );
415}
416
418 auto lock = std::scoped_lock{ m_messageMapMutex };
419 m_messageMap.clear();
420}
421
423 auto lock = std::scoped_lock{ m_messageMapMutex };
424 m_messageMap.erase( key );
425}
426
427void MessageSvc::eraseMessage( const StatusCode& key, const Message& msg ) {
428 auto lock = std::scoped_lock{ m_messageMapMutex };
429
430 erase_if( m_messageMap, m_messageMap.equal_range( key ),
431 [&]( MessageMap::const_reference j ) { return j.second == msg; } );
432}
433
435
436int MessageSvc::outputLevel( std::string_view source ) const {
437 auto lock = std::scoped_lock{ m_thresholdMapMutex };
438 auto it = m_thresholdMap.find( source );
439 return it != m_thresholdMap.end() ? it->second : m_outputLevel.value();
440}
441
442void MessageSvc::setOutputLevel( int new_level ) { m_outputLevel = new_level; }
443
444void MessageSvc::setOutputLevel( std::string_view source, int level ) {
445 auto lock = std::scoped_lock{ m_thresholdMapMutex };
446
447 // only write if we really have to...
448 auto i = m_thresholdMap.find( source );
449 if ( i == m_thresholdMap.end() ) {
450 m_thresholdMap.emplace( source, level );
451 } else if ( i->second != level ) {
452 i->second = level;
453 }
454}
455
456std::string MessageSvc::getLogColor( int logLevel ) const {
457 return ( logLevel < MSG::NUM_LEVELS ) ? m_logColorCodes[logLevel] : "";
458}
459
460int MessageSvc::messageCount( MSG::Level level ) const { return m_msgCount[level]; }
461
462void MessageSvc::incrInactiveCount( MSG::Level level, std::string_view source ) {
463 auto entry = m_inactiveMap.find( source );
464 if ( entry == m_inactiveMap.end() ) { entry = m_inactiveMap.emplace( source, MsgAry{} ).first; }
465 ++entry->second.msg[level];
466
467 if ( std::find( begin( m_tracedInactiveSources ), end( m_tracedInactiveSources ), source ) !=
468 end( m_tracedInactiveSources ) ) {
469 std::cout << "== inactive message detected from " << source << " ==\n";
470 std::string t;
471 System::backTrace( t, 25, 0 );
472 std::cout << t << std::endl;
473 }
474}
475
477 // reset state
478 m_loggedStreams.clear();
479
480 // make the unique set of output filenames
481 std::set<std::string_view> outFileNames;
482 std::transform( m_loggedStreamsName.begin(), m_loggedStreamsName.end(),
483 std::inserter( outFileNames, outFileNames.end() ),
484 []( const auto& p ) -> std::string_view { return p.second; } );
485 // map each unique filename to an ofstream
486 std::map<std::string_view, std::shared_ptr<std::ofstream>> outStreams;
487 std::transform( outFileNames.begin(), outFileNames.end(), std::inserter( outStreams, outStreams.end() ),
488 []( std::string_view fname ) {
489 return std::pair{ fname, std::make_shared<std::ofstream>(
490 std::string{ fname }, std::ios_base::out | std::ios_base::trunc ) };
491 } );
492 // associate the stream to ofstream...
493 for ( auto& iProp : m_loggedStreamsName ) {
494 auto& stream = outStreams.at( iProp.second );
495 if ( stream->good() ) m_loggedStreams.emplace( iProp.first, stream );
496 }
497}
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition Iterator.h:18
#define DECLARE_COMPONENT(type)
MsgStream & msg() const
shortcut for the method msgStream(MSG::INFO)
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
const std::string name() const
property name
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
const ValueType & value() const
Definition Property.h:251
bool setValue(const ValueType &v)
Definition Property.h:253
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
The Message class.
Definition Message.h:25
void setFormat(std::string msg) const
Set the format string.
Definition Message.cpp:97
Gaudi::Property< bool > m_color
Definition MessageSvc.h:162
void reportMessage(const Message &message) override
Gaudi::Property< std::string > m_defaultTimeFormat
Definition MessageSvc.h:149
std::recursive_mutex m_messageMapMutex
Mutex to synchronize multiple access to m_messageMap.
Definition MessageSvc.h:225
Message m_defaultMessage
Default Message.
Definition MessageSvc.h:196
MessageMap m_messageMap
Message map.
Definition MessageSvc.h:198
StatusCode reinitialize() override
void setupLogStreams()
StreamMap m_streamMap
Stream map.
Definition MessageSvc.h:197
std::map< std::string, MsgAry, std::less<> > m_sourceMap
Definition MessageSvc.h:211
ThresholdMap m_thresholdMap
Output level threshold map.
Definition MessageSvc.h:199
Gaudi::Property< bool > m_inactCount
Definition MessageSvc.h:184
std::map< std::string, std::shared_ptr< std::ostream >, std::less<> > m_loggedStreams
Definition MessageSvc.h:215
std::array< Gaudi::Property< int >, MSG::NUM_LEVELS > m_msgLimit
Definition MessageSvc.h:173
void setupInactCount(Gaudi::Details::PropertyBase &prop)
void setupThreshold(Gaudi::Details::PropertyBase &prop)
std::map< std::string, MsgAry, std::less<> > m_inactiveMap
Definition MessageSvc.h:211
std::array< int, MSG::NUM_LEVELS > m_msgCount
Definition MessageSvc.h:213
std::array< Gaudi::Property< std::vector< std::string > >, MSG::NUM_LEVELS > m_logColors
Definition MessageSvc.h:164
int outputLevel() const override
int messageCount(MSG::Level logLevel) const override
void setOutputLevel(int new_level) override
virtual void i_reportMessage(const Message &msg, int outputLevel)
Internal implementation of reportMessage(const Message&,int) without lock.
StatusCode initialize() override
void eraseStream() override
std::string m_defaultFormat
Definition MessageSvc.h:138
std::array< Gaudi::Property< std::vector< std::string > >, MSG::NUM_LEVELS > m_thresholdProp
Definition MessageSvc.h:153
void eraseMessage() override
void setupLimits(Gaudi::Details::PropertyBase &prop)
StatusCode finalize() override
Gaudi::Property< std::vector< std::string > > m_tracedInactiveSources
Definition MessageSvc.h:186
std::string getLogColor(int logLevel) const override
Gaudi::Property< unsigned int > m_statLevel
Definition MessageSvc.h:151
StatusCode setPropertyRepr(const std::string &n, const std::string &r) override
std::recursive_mutex m_thresholdMapMutex
Mutex to synchronize multiple access to m_thresholdMap (.
Definition MessageSvc.h:229
void setupColors(Gaudi::Details::PropertyBase &prop)
Gaudi::Property< bool > m_stats
Definition MessageSvc.h:150
std::recursive_mutex m_reportMutex
Mutex to synchronize multiple threads printing.
Definition MessageSvc.h:144
Gaudi::Property< std::map< std::string, std::string, std::less<> > > m_loggedStreamsName
Definition MessageSvc.h:192
std::pair< std::string, std::ostream * > NamedStream
Definition MessageSvc.h:38
void insertMessage(const StatusCode &code, Message message) override
bool m_suppress
Definition MessageSvc.h:137
void insertStream(int message_type, std::string name, std::ostream *stream) override
MessageSvc(const std::string &name, ISvcLocator *svcloc)
void incrInactiveCount(MSG::Level level, std::string_view src) override
std::string m_logColorCodes[MSG::NUM_LEVELS]
Definition MessageSvc.h:201
static GAUDI_API bool enableCountInactive(bool value=true)
Enable/disable the count of inactive messages.
Definition MsgStream.cpp:21
StatusCode setPropertyRepr(const std::string &n, const std::string &r) override
Gaudi::Property< int > m_outputLevel
flag indicating whether ToolHandle tools have been added to m_tools
Definition Service.h:184
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
Gaudi::StateMachine::State m_state
Service state.
Definition Service.h:155
StatusCode initialize() override
Definition Service.cpp:118
Small smart pointer class with automatic reference counting for IInterface.
Definition SmartIF.h:28
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
code_t getCode() const
Retrieve value.
Definition StatusCode.h:136
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition details.h:81
@ GREEN
Definition IMessageSvc.h:23
@ WHITE
Definition IMessageSvc.h:23
@ CYAN
Definition IMessageSvc.h:23
@ YELLOW
Definition IMessageSvc.h:23
@ PURPLE
Definition IMessageSvc.h:23
@ BLACK
Definition IMessageSvc.h:23
@ BLUE
Definition IMessageSvc.h:23
@ RED
Definition IMessageSvc.h:23
@ NIL
Definition IMessageSvc.h:22
@ NUM_LEVELS
Definition IMessageSvc.h:22
@ WARNING
Definition IMessageSvc.h:22
@ FATAL
Definition IMessageSvc.h:22
@ DEBUG
Definition IMessageSvc.h:22
@ ERROR
Definition IMessageSvc.h:22
@ ALWAYS
Definition IMessageSvc.h:22
@ INFO
Definition IMessageSvc.h:22
@ VERBOSE
Definition IMessageSvc.h:22
GAUDI_API int backTrace(void **addresses, const int depth)
Definition System.cpp:372
Private helper class to keep the count of messages of a type (MSG::LEVEL).
Definition MessageSvc.h:204