Logo ROOT   6.16/01
Reference Guide
RooMsgService.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooMsgService.cxx
19\class RooMsgService
20\ingroup Roofitcore
21
22
23The RooMsgService class is a singleton class that organizes informational, debugging,
24warning and errors messages generated by the RooFit core code.
25Each message generated by the core
26has a message level (DEBUG,INFO,PROGRESS,WARNING,ERROR or FATAL), an originating object,
27and a 'topic'. Currently implemented topics are "Generation","Plotting",
28"Integration", "Minimization" and "Workspace" and "ChangeTracking".
29The RooMsgService class allows to filter and redirect messages into 'streams'
30according to message level, topic, (base) class of originating object, name of originating
31object and based on attribute labels attached to individual objects.
32The current default configuration creates streams for all messages at WARNING level
33or higher (e.g. ERROR and FATAL) and for all INFO message on topics Generation,Plotting,
34Integration and Minimization and redirects them to stdout. Users can create additional streams
35for logging of e.g. DEBUG messages on particular topics or objects and or redirect streams to
36C++ streams or files.
37The singleton instance is accessible through RooMsgService::instance() ;
38
39**/
40
41
42#include <sys/types.h>
43
44#include "RooFit.h"
45#include "RooAbsArg.h"
46#include "TClass.h"
47#include "TROOT.h"
48
49#include "RooMsgService.h"
50#include "RooCmdArg.h"
51#include "RooCmdConfig.h"
52#include "RooGlobalFunc.h"
53#include "RooSentinel.h"
54#include "RooWorkspace.h"
55
56#include "TSystem.h"
57#include "Riostream.h"
58#include <iomanip>
59using namespace std ;
60using namespace RooFit ;
61
63;
64
68
69
70////////////////////////////////////////////////////////////////////////////////
71/// Cleanup function called by atexit() handler installed by RooSentinel
72/// to delete all global object upon program termination
73
75{
76 if (_instance) {
77 delete _instance ;
78 _instance = 0 ;
79 }
80}
81
82
83
84////////////////////////////////////////////////////////////////////////////////
85/// Constructor. Defines names of message levels
86/// and mapping of topic codes to topic names
87/// Install default message streams.
88
90{
95
96 _devnull = new ofstream("/dev/null") ;
97
98 _levelNames[DEBUG]="DEBUG" ;
99 _levelNames[INFO]="INFO" ;
100 _levelNames[PROGRESS]="PROGRESS" ;
101 _levelNames[WARNING]="WARNING" ;
102 _levelNames[ERROR]="ERROR" ;
103 _levelNames[FATAL]="FATAL" ;
104
105 _topicNames[Generation]="Generation" ;
106 _topicNames[Minimization]="Minization" ;
107 _topicNames[Plotting]="Plotting" ;
108 _topicNames[Fitting]="Fitting" ;
109 _topicNames[Integration]="Integration" ;
110 _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
111 _topicNames[Eval]="Eval" ;
112 _topicNames[Caching]="Caching" ;
113 _topicNames[Optimization]="Optimization" ;
114 _topicNames[ObjectHandling]="ObjectHandling" ;
115 _topicNames[InputArguments]="InputArguments" ;
116 _topicNames[Tracing]="Tracing" ;
117 _topicNames[Contents]="Contents" ;
118 _topicNames[DataHandling]="DataHandling" ;
119 _topicNames[NumIntegration]="NumericIntegration" ;
120
121 _instance = this ;
122 gMsgService = this ;
123
124 _debugWorkspace = 0 ;
125 _debugCode = 0 ;
126
127 // Old-style streams
130}
131
132
133////////////////////////////////////////////////////////////////////////////////
134/// Destructor
135
137{
138 // Delete all ostreams we own ;
139 map<string,ostream*>::iterator iter = _files.begin() ;
140 for (; iter != _files.end() ; ++iter) {
141 delete iter->second ;
142 }
143
144 if (_debugWorkspace) {
145 delete _debugWorkspace ;
146 }
147
148 delete _devnull ;
149}
150
151
152
153////////////////////////////////////////////////////////////////////////////////
154/// Returns true if any debug level stream is active
155
157{
158 return instance()._debugCount>0 ;
159}
160
161
162
163////////////////////////////////////////////////////////////////////////////////
164
166{
167 if (!_debugWorkspace) {
168 _debugWorkspace = new RooWorkspace("wdebug") ;
169 }
170 return _debugWorkspace ;
171}
172
173
174
175////////////////////////////////////////////////////////////////////////////////
176/// Add a message logging stream for message with given RooFit::MsgLevel or higher (i.e. more severe)
177/// This method accepts the following arguments to configure the stream
178///
179/// Output Style options
180/// --------------------
181/// Prefix(Bool_t flag=kTRUE) -- Prefix all messages in this stream with Topic/Originator information
182///
183/// Filtering options
184/// -----------------
185/// Topic(const char*) -- Restrict stream to messages on given topic
186/// ObjectName(const char*) -- Restrict stream to messages from object with given name
187/// ClassName(const char*) -- Restrict stream to messages from objects with given class name
188/// BaseClassName(const char*)-- Restrict stream to messages from objects with given base class name
189/// LabelName(const chat*) -- Restrict stream to messages from objects setAtrribute(const char*) tag with given name
190///
191/// Output redirection options
192/// --------------------------
193/// OutputFile(const char*) -- Send output to file with given name. Multiple streams can write to same file.
194/// OutputStream(ostream&) -- Send output to given C++ stream. Multiple message streams can write to same c++ stream
195///
196/// The return value is the unique ID code of the defined stream
197
198Int_t RooMsgService::addStream(RooFit::MsgLevel level, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
199 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6)
200{
201
202 // Aggregate all arguments in a list
204 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
205 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
206 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
207
208 // Define configuration for this method
209 RooCmdConfig pc(Form("RooMsgService::addReportingStream(%s)",GetName())) ;
210 pc.defineInt("prefix","Prefix",0,kTRUE) ;
211 pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
212 pc.defineInt("topic","Topic",0,0xFFFFF) ;
213 pc.defineString("objName","ObjectName",0,"") ;
214 pc.defineString("className","ClassName",0,"") ;
215 pc.defineString("baseClassName","BaseClassName",0,"") ;
216 pc.defineString("tagName","LabelName",0,"") ;
217 pc.defineString("outFile","OutputFile",0,"") ;
218 pc.defineObject("outStream","OutputStream",0,0) ;
219 pc.defineMutex("OutputFile","OutputStream") ;
220
221 // Process & check varargs
222 pc.process(l) ;
223 if (!pc.ok(kTRUE)) {
224 return -1 ;
225 }
226
227 // Extract values from named arguments
228 RooFit::MsgTopic topic = (RooFit::MsgTopic) pc.getInt("topic") ;
229 const char* objName = pc.getString("objName") ;
230 const char* className = pc.getString("className") ;
231 const char* baseClassName = pc.getString("baseClassName") ;
232 const char* tagName = pc.getString("tagName") ;
233 const char* outFile = pc.getString("outFile") ;
234 Bool_t prefix = pc.getInt("prefix") ;
235 Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
236 ostream* os = reinterpret_cast<ostream*>(pc.getObject("outStream")) ;
237
238 // Create new stream object
239 StreamConfig newStream ;
240
241 // Store configuration info
242 newStream.active = kTRUE ;
243 newStream.minLevel = level ;
244 newStream.topic = topic ;
245 newStream.objectName = (objName ? objName : "" ) ;
246 newStream.className = (className ? className : "" ) ;
247 newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
248 newStream.tagName = (tagName ? tagName : "" ) ;
249 newStream.color = color ;
250 newStream.prefix = prefix ;
251 newStream.universal = (newStream.objectName=="" && newStream.className=="" && newStream.baseClassName=="" && newStream.tagName=="") ;
252
253 // Update debug stream count
254 if (level==DEBUG) {
255 _debugCount++ ;
256 }
257
258 // Configure output
259 if (os) {
260
261 // To given non-owned stream
262 newStream.os = os ;
263
264 } else if (string(outFile).size()>0) {
265
266 // See if we already opened the file
267 ostream* os2 = _files["outFile"] ;
268
269 if (!os2) {
270
271 // To given file name, create owned stream for it
272 os2 = new ofstream(outFile) ;
273
274 if (!*os2) {
275 cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << endl ;
276 delete os2 ;
277 newStream.os = &cout ;
278 } else {
279 newStream.os = os2 ;
280 }
281
282 } else {
283 _files["outFile"] = os2 ;
284 newStream.os = os2 ;
285 }
286
287
288 } else {
289
290 // To stdout
291 newStream.os = &cout ;
292
293 }
294
295
296 // Add it to list of active streams ;
297 _streams.push_back(newStream) ;
298
299 // Return stream identifier
300 return _streams.size()-1 ;
301}
302
303
304
305////////////////////////////////////////////////////////////////////////////////
306/// Delete stream with given unique ID code
307
309{
310 vector<StreamConfig>::iterator iter = _streams.begin() ;
311 iter += id ;
312
313 // Update debug stream count
314 if (iter->minLevel==DEBUG) {
315 _debugCount-- ;
316 }
317
318 _streams.erase(iter) ;
319}
320
321
322
323////////////////////////////////////////////////////////////////////////////////
324/// (De)Activate stream with given unique ID
325
327{
328 if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
329 cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << endl ;
330 return ;
331 }
332
333 // Update debug stream count
334 if (_streams[id].minLevel==DEBUG) {
335 _debugCount += flag ? 1 : -1 ;
336 }
337
338 _streams[id].active = flag ;
339}
340
341
342
343////////////////////////////////////////////////////////////////////////////////
344/// Get activation status of stream with given unique ID
345
347{
348 if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
349 cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << endl ;
350 return kFALSE ;
351 }
352 return _streams[id].active ;
353}
354
355
356
357////////////////////////////////////////////////////////////////////////////////
358/// Return reference to singleton instance
359
361{
362 if (!_instance) {
363 new RooMsgService() ;
365 }
366 return *_instance ;
367}
368
369
370
371////////////////////////////////////////////////////////////////////////////////
372/// Save current state of message service
373
375{
376 _streamsSaved.push(_streams) ;
377}
378
379
380
381////////////////////////////////////////////////////////////////////////////////
382/// Restore last saved state of message service
383
385{
386 _streams = _streamsSaved.top() ;
387 _streamsSaved.pop() ;
388}
389
390
391
392////////////////////////////////////////////////////////////////////////////////
393/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
394
396{
397 return (activeStream(self,topic,level)>=0) ;
398}
399
400
401////////////////////////////////////////////////////////////////////////////////
402/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
403
405{
406 return (activeStream(self,topic,level)>=0) ;
407}
408
409
410////////////////////////////////////////////////////////////////////////////////
411/// Find appropriate logging stream for message from given object with given topic and message level
412
414{
415 if (level<_globMinLevel) return -1 ;
416 for (UInt_t i=0 ; i<_streams.size() ; i++) {
417 if (_streams[i].match(level,topic,self)) {
418 return i ;
419 }
420 }
421 return -1 ;
422}
423
424
425////////////////////////////////////////////////////////////////////////////////
426/// Find appropriate logging stream for message from given object with given topic and message level
427
429{
430 if (level<_globMinLevel) return -1 ;
431 for (UInt_t i=0 ; i<_streams.size() ; i++) {
432 if (_streams[i].match(level,topic,self)) {
433 return i ;
434 }
435 }
436 return -1 ;
437}
438
439
440////////////////////////////////////////////////////////////////////////////////
441/// Determine if message from given object at given level on given topic is logged
442
444{
445 if (!active) return kFALSE ;
446 if (level<minLevel) return kFALSE ;
447 if (!(topic&top)) return kFALSE ;
448
449 if (universal) return kTRUE ;
450
451 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
452 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
453 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
454 if (tagName.size()>0 && !obj->getAttribute(tagName.c_str())) return kFALSE ;
455
456 return kTRUE ;
457}
458
459
460////////////////////////////////////////////////////////////////////////////////
461/// Determine if message from given object at given level on given topic is logged
462
464{
465 if (!active) return kFALSE ;
466 if (level<minLevel) return kFALSE ;
467 if (!(topic&top)) return kFALSE ;
468
469 if (universal) return kTRUE ;
470
471 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
472 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
473 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
474
475 return kTRUE ;
476}
477
478
479
480////////////////////////////////////////////////////////////////////////////////
481/// Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
482/// is true the standard RooMsgService prefix is not added.
483
484ostream& RooMsgService::log(const RooAbsArg* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
485{
486 if (level>=ERROR) {
487 _errorCount++ ;
488 }
489
490 // Return C++ ostream associated with given message configuration
491 Int_t as = activeStream(self,topic,level) ;
492
493 if (as==-1) {
494 return *_devnull ;
495 }
496
497 // Flush any previous messages
498 (*_streams[as].os).flush() ;
499
500 // Insert an endl if we switch from progress to another level
501 if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
502 (*_streams[as].os) << endl ;
503 }
504 _lastMsgLevel=level ;
505
506 if (_streams[as].prefix && !skipPrefix) {
507 if (_showPid) {
508 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
509 }
510 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
511 }
512 return (*_streams[as].os) ;
513}
514
515
516
517////////////////////////////////////////////////////////////////////////////////
518/// Log error message associated with TObject object self at given level and topic. If skipPrefix
519/// is true the standard RooMsgService prefix is not added.
520
521ostream& RooMsgService::log(const TObject* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
522{
523 if (level>=ERROR) {
524 _errorCount++ ;
525 }
526
527 // Return C++ ostream associated with given message configuration
528 Int_t as = activeStream(self,topic,level) ;
529 if (as==-1) {
530 return *_devnull ;
531 }
532
533 // Flush any previous messages
534 (*_streams[as].os).flush() ;
535
536 if (_streams[as].prefix && !skipPrefix) {
537 if (_showPid) {
538 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
539 }
540 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
541 }
542 return (*_streams[as].os) ;
543}
544
545
546
547////////////////////////////////////////////////////////////////////////////////
548/// Print configuration of message service. If "v" option is given also
549/// inactive streams are listed
550
551void RooMsgService::Print(Option_t *options) const
552{
553 Bool_t activeOnly = kTRUE ;
554 if (TString(options).Contains("V") || TString(options).Contains("v")) {
555 activeOnly = kFALSE ;
556 }
557
558 cout << (activeOnly?"Active Message streams":"All Message streams") << endl ;
559 for (UInt_t i=0 ; i<_streams.size() ; i++) {
560
561 // Skip passive streams in active only mode
562 if (activeOnly && !_streams[i].active) {
563 continue ;
564 }
565
566
567 map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
568 cout << "[" << i << "] MinLevel = " << is->second ;
569
570 cout << " Topic = " ;
571 if (_streams[i].topic != 0xFFFFF) {
572 map<int,string>::const_iterator iter = _topicNames.begin() ;
573 while(iter!=_topicNames.end()) {
574 if (iter->first & _streams[i].topic) {
575 cout << iter->second << " " ;
576 }
577 ++iter ;
578 }
579 } else {
580 cout << " Any " ;
581 }
582
583
584 if (_streams[i].objectName.size()>0) {
585 cout << " ObjectName = " << _streams[i].objectName ;
586 }
587 if (_streams[i].className.size()>0) {
588 cout << " ClassName = " << _streams[i].className ;
589 }
590 if (_streams[i].baseClassName.size()>0) {
591 cout << " BaseClassName = " << _streams[i].baseClassName ;
592 }
593 if (_streams[i].tagName.size()>0) {
594 cout << " TagLabel = " << _streams[i].tagName ;
595 }
596
597 // Postfix status when printing all
598 if (!activeOnly && !_streams[i].active) {
599 cout << " (NOT ACTIVE)" ;
600 }
601
602 cout << endl ;
603 }
604
605}
#define DEBUG
Definition: Polynomial.cxx:41
RooMsgService * gMsgService
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
short Color_t
Definition: RtypesCore.h:79
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
@ kBlack
Definition: Rtypes.h:62
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:264
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:27
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
Definition: RooCmdConfig.h:27
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
The RooMsgService class is a singleton class that organizes informational, debugging,...
static void cleanup()
Cleanup function called by atexit() handler installed by RooSentinel to delete all global object upon...
std::vector< StreamConfig > _streams
void restoreState()
Restore last saved state of message service.
std::ostream * _devnull
void setStreamStatus(Int_t id, Bool_t active)
(De)Activate stream with given unique ID
Bool_t getStreamStatus(Int_t id) const
Get activation status of stream with given unique ID.
static RooMsgService & instance()
Return reference to singleton instance.
static Int_t _debugCount
RooFit::MsgLevel _globMinLevel
Bool_t isActive(const RooAbsArg *self, RooFit::MsgTopic facility, RooFit::MsgLevel level)
Check if logging is active for given object/topic/RooFit::MsgLevel combination.
static RooMsgService * _instance
std::stack< std::vector< StreamConfig > > _streamsSaved
RooMsgService()
Constructor.
Bool_t _silentMode
RooWorkspace * debugWorkspace()
void saveState()
Save current state of message service.
std::map< int, std::string > _topicNames
std::ostream & log(const RooAbsArg *self, RooFit::MsgLevel level, RooFit::MsgTopic facility, Bool_t forceSkipPrefix=kFALSE)
Log error message associated with RooAbsArg object self at given level and topic.
Int_t addStream(RooFit::MsgLevel level, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg())
Add a message logging stream for message with given RooFit::MsgLevel or higher (i....
RooWorkspace * _debugWorkspace
static Bool_t anyDebug()
Returns true if any debug level stream is active.
Int_t activeStream(const RooAbsArg *self, RooFit::MsgTopic facility, RooFit::MsgLevel level)
Find appropriate logging stream for message from given object with given topic and message level.
virtual ~RooMsgService()
Destructor.
void deleteStream(Int_t id)
Delete stream with given unique ID code.
std::map< std::string, std::ostream * > _files
std::map< int, std::string > _levelNames
void Print(Option_t *options=0) const
Print configuration of message service.
RooFit::MsgLevel _lastMsgLevel
static void activate()
Install atexit handler that calls CleanupRooFitAtExit() on program termination.
Definition: RooSentinel.cxx:73
The RooWorkspace is a persistable container for RooFit projects.
Definition: RooWorkspace.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:716
TString as(SEXP s)
Definition: RExports.h:71
RooCmdArg Topic(Int_t topic)
@ Minimization
Definition: RooGlobalFunc.h:57
@ Generation
Definition: RooGlobalFunc.h:57
@ NumIntegration
Definition: RooGlobalFunc.h:59
@ Optimization
Definition: RooGlobalFunc.h:58
@ DataHandling
Definition: RooGlobalFunc.h:59
@ InputArguments
Definition: RooGlobalFunc.h:58
@ ObjectHandling
Definition: RooGlobalFunc.h:58
@ Integration
Definition: RooGlobalFunc.h:57
@ LinkStateMgmt
Definition: RooGlobalFunc.h:57
static constexpr double pc
STL namespace.
Bool_t match(RooFit::MsgLevel level, RooFit::MsgTopic facility, const RooAbsArg *obj)
Determine if message from given object at given level on given topic is logged.
auto * l
Definition: textangle.C:4