Logo ROOT  
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 RooFit::MsgLevel (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 "RooWorkspace.h"
54
55#include "TSystem.h"
56#include "Riostream.h"
57#include <iomanip>
58using namespace std ;
59using namespace RooFit ;
60
62
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Constructor. Defines names of message levels
68/// and mapping of topic codes to topic names
69/// Install default message streams.
70
72{
73 _devnull = new ofstream("/dev/null") ;
74
75 _levelNames[DEBUG]="DEBUG" ;
76 _levelNames[INFO]="INFO" ;
77 _levelNames[PROGRESS]="PROGRESS" ;
78 _levelNames[WARNING]="WARNING" ;
79 _levelNames[ERROR]="ERROR" ;
80 _levelNames[FATAL]="FATAL" ;
81
82 _topicNames[Generation]="Generation" ;
83 _topicNames[Minimization]="Minization" ;
84 _topicNames[Plotting]="Plotting" ;
85 _topicNames[Fitting]="Fitting" ;
86 _topicNames[Integration]="Integration" ;
87 _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
88 _topicNames[Eval]="Eval" ;
89 _topicNames[Caching]="Caching" ;
90 _topicNames[Optimization]="Optimization" ;
91 _topicNames[ObjectHandling]="ObjectHandling" ;
92 _topicNames[InputArguments]="InputArguments" ;
93 _topicNames[Tracing]="Tracing" ;
94 _topicNames[Contents]="Contents" ;
95 _topicNames[DataHandling]="DataHandling" ;
96 _topicNames[NumIntegration]="NumericIntegration" ;
97
98 reset();
99}
100
101
104 _showPid = kFALSE ;
107
108 delete _debugWorkspace;
109 _debugWorkspace = nullptr;
110 _debugCode = 0 ;
111
112 for (auto item : _files) {
113 delete item.second;
114 }
115 _files.clear();
116
117 // Old-style streams
118 _streams.clear();
121}
122
123
124////////////////////////////////////////////////////////////////////////////////
125/// Destructor
126
128{
129 // Delete all ostreams we own ;
130 map<string,ostream*>::iterator iter = _files.begin() ;
131 for (; iter != _files.end() ; ++iter) {
132 delete iter->second ;
133 }
134
135 if (_debugWorkspace) {
136 delete _debugWorkspace ;
137 }
138
139 delete _devnull ;
140}
141
142
143
144////////////////////////////////////////////////////////////////////////////////
145/// Returns true if any debug level stream is active
146
148{
149 return instance()._debugCount>0 ;
150}
151
152
153
154////////////////////////////////////////////////////////////////////////////////
155
157{
158 if (!_debugWorkspace) {
159 _debugWorkspace = new RooWorkspace("wdebug") ;
160 }
161 return _debugWorkspace ;
162}
163
164
165
166////////////////////////////////////////////////////////////////////////////////
167/// Add a message logging stream for message with given RooFit::MsgLevel or higher (i.e. more severe)
168/// This method accepts the following arguments to configure the stream
169///
170/// Output Style options
171/// --------------------
172/// Prefix(Bool_t flag=kTRUE) -- Prefix all messages in this stream with Topic/Originator information
173///
174/// Filtering options
175/// -----------------
176/// Topic(const char*) -- Restrict stream to messages on given topic
177/// ObjectName(const char*) -- Restrict stream to messages from object with given name
178/// ClassName(const char*) -- Restrict stream to messages from objects with given class name
179/// BaseClassName(const char*)-- Restrict stream to messages from objects with given base class name
180/// LabelName(const chat*) -- Restrict stream to messages from objects setAtrribute(const char*) tag with given name
181///
182/// Output redirection options
183/// --------------------------
184/// OutputFile(const char*) -- Send output to file with given name. Multiple streams can write to same file.
185/// OutputStream(ostream&) -- Send output to given C++ stream. Multiple message streams can write to same c++ stream
186///
187/// The return value is the unique ID code of the defined stream
188
189Int_t RooMsgService::addStream(RooFit::MsgLevel level, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3,
190 const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6)
191{
192
193 // Aggregate all arguments in a list
195 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
196 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
197 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
198
199 // Define configuration for this method
200 RooCmdConfig pc(Form("RooMsgService::addReportingStream(%s)",GetName())) ;
201 pc.defineInt("prefix","Prefix",0,kTRUE) ;
202 pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
203 pc.defineInt("topic","Topic",0,0xFFFFF) ;
204 pc.defineString("objName","ObjectName",0,"") ;
205 pc.defineString("className","ClassName",0,"") ;
206 pc.defineString("baseClassName","BaseClassName",0,"") ;
207 pc.defineString("tagName","LabelName",0,"") ;
208 pc.defineString("outFile","OutputFile",0,"") ;
209 pc.defineObject("outStream","OutputStream",0,0) ;
210 pc.defineMutex("OutputFile","OutputStream") ;
211
212 // Process & check varargs
213 pc.process(l) ;
214 if (!pc.ok(kTRUE)) {
215 return -1 ;
216 }
217
218 // Extract values from named arguments
219 RooFit::MsgTopic topic = (RooFit::MsgTopic) pc.getInt("topic") ;
220 const char* objName = pc.getString("objName") ;
221 const char* className = pc.getString("className") ;
222 const char* baseClassName = pc.getString("baseClassName") ;
223 const char* tagName = pc.getString("tagName") ;
224 const char* outFile = pc.getString("outFile") ;
225 Bool_t prefix = pc.getInt("prefix") ;
226 Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
227 ostream* os = reinterpret_cast<ostream*>(pc.getObject("outStream")) ;
228
229 // Create new stream object
230 StreamConfig newStream ;
231
232 // Store configuration info
233 newStream.active = kTRUE ;
234 newStream.minLevel = level ;
235 newStream.topic = topic ;
236 newStream.objectName = (objName ? objName : "" ) ;
237 newStream.className = (className ? className : "" ) ;
238 newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
239 newStream.tagName = (tagName ? tagName : "" ) ;
240 newStream.color = color ;
241 newStream.prefix = prefix ;
242 newStream.universal = (newStream.objectName=="" && newStream.className=="" && newStream.baseClassName=="" && newStream.tagName=="") ;
243
244 // Update debug stream count
245 if (level==DEBUG) {
246 _debugCount++ ;
247 }
248
249 // Configure output
250 if (os) {
251
252 // To given non-owned stream
253 newStream.os = os ;
254
255 } else if (string(outFile).size()>0) {
256
257 // See if we already opened the file
258 ostream* os2 = _files["outFile"] ;
259
260 if (!os2) {
261
262 // To given file name, create owned stream for it
263 os2 = new ofstream(outFile) ;
264
265 if (!*os2) {
266 cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << endl ;
267 delete os2 ;
268 newStream.os = &cout ;
269 } else {
270 newStream.os = os2 ;
271 }
272
273 } else {
274 _files["outFile"] = os2 ;
275 newStream.os = os2 ;
276 }
277
278
279 } else {
280
281 // To stdout
282 newStream.os = &cout ;
283
284 }
285
286
287 // Add it to list of active streams ;
288 _streams.push_back(newStream) ;
289
290 // Return stream identifier
291 return _streams.size()-1 ;
292}
293
294
295
296////////////////////////////////////////////////////////////////////////////////
297/// Delete stream with given unique ID code
298
300{
301 vector<StreamConfig>::iterator iter = _streams.begin() ;
302 iter += id ;
303
304 // Update debug stream count
305 if (iter->minLevel==DEBUG) {
306 _debugCount-- ;
307 }
308
309 _streams.erase(iter) ;
310}
311
312
313
314////////////////////////////////////////////////////////////////////////////////
315/// (De)Activate stream with given unique ID
316
318{
319 if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
320 cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << endl ;
321 return ;
322 }
323
324 // Update debug stream count
325 if (_streams[id].minLevel==DEBUG) {
326 _debugCount += flag ? 1 : -1 ;
327 }
328
329 _streams[id].active = flag ;
330}
331
332
333
334////////////////////////////////////////////////////////////////////////////////
335/// Get activation status of stream with given unique ID
336
338{
339 if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
340 cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << endl ;
341 return kFALSE ;
342 }
343 return _streams[id].active ;
344}
345
346
347
348////////////////////////////////////////////////////////////////////////////////
349/// Return reference to singleton instance
350
352{
353 static RooMsgService instance;
354 return instance;
355}
356
357
358
359////////////////////////////////////////////////////////////////////////////////
360/// Save current state of message service
361
363{
364 _streamsSaved.push(_streams) ;
365}
366
367
368
369////////////////////////////////////////////////////////////////////////////////
370/// Restore last saved state of message service
371
373{
374 _streams = _streamsSaved.top() ;
375 _streamsSaved.pop() ;
376}
377
378
379
380////////////////////////////////////////////////////////////////////////////////
381/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
382
384{
385 return (activeStream(self,topic,level)>=0) ;
386}
387
388
389////////////////////////////////////////////////////////////////////////////////
390/// Check if logging is active for given object/topic/RooFit::MsgLevel combination
391
393{
394 return (activeStream(self,topic,level)>=0) ;
395}
396
397
398////////////////////////////////////////////////////////////////////////////////
399/// Find appropriate logging stream for message from given object with given topic and message level
400
402{
403 if (level<_globMinLevel) return -1 ;
404 for (UInt_t i=0 ; i<_streams.size() ; i++) {
405 if (_streams[i].match(level,topic,self)) {
406 return i ;
407 }
408 }
409 return -1 ;
410}
411
412
413////////////////////////////////////////////////////////////////////////////////
414/// Find appropriate logging stream for message from given object with given topic and message level
415
417{
418 if (level<_globMinLevel) return -1 ;
419 for (UInt_t i=0 ; i<_streams.size() ; i++) {
420 if (_streams[i].match(level,topic,self)) {
421 return i ;
422 }
423 }
424 return -1 ;
425}
426
427
428////////////////////////////////////////////////////////////////////////////////
429/// Determine if message from given object at given level on given topic is logged
430
432{
433 if (!active) return kFALSE ;
434 if (level<minLevel) return kFALSE ;
435 if (!(topic&top)) return kFALSE ;
436
437 if (universal) return kTRUE ;
438
439 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
440 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
441 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
442 if (tagName.size()>0 && !obj->getAttribute(tagName.c_str())) return kFALSE ;
443
444 return kTRUE ;
445}
446
447
448////////////////////////////////////////////////////////////////////////////////
449/// Determine if message from given object at given level on given topic is logged
450
452{
453 if (!active) return kFALSE ;
454 if (level<minLevel) return kFALSE ;
455 if (!(topic&top)) return kFALSE ;
456
457 if (universal) return kTRUE ;
458
459 if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
460 if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
461 if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
462
463 return kTRUE ;
464}
465
466
467
468////////////////////////////////////////////////////////////////////////////////
469/// Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
470/// is true the standard RooMsgService prefix is not added.
471
472ostream& RooMsgService::log(const RooAbsArg* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
473{
474 if (level>=ERROR) {
475 _errorCount++ ;
476 }
477
478 // Return C++ ostream associated with given message configuration
479 Int_t as = activeStream(self,topic,level) ;
480
481 if (as==-1) {
482 return *_devnull ;
483 }
484
485 // Flush any previous messages
486 (*_streams[as].os).flush() ;
487
488 // Insert an endl if we switch from progress to another level
489 if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
490 (*_streams[as].os) << endl ;
491 }
492 _lastMsgLevel=level ;
493
494 if (_streams[as].prefix && !skipPrefix) {
495 if (_showPid) {
496 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
497 }
498 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
499 }
500 return (*_streams[as].os) ;
501}
502
503
504
505////////////////////////////////////////////////////////////////////////////////
506/// Log error message associated with TObject object self at given level and topic. If skipPrefix
507/// is true the standard RooMsgService prefix is not added.
508
509ostream& RooMsgService::log(const TObject* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix)
510{
511 if (level>=ERROR) {
512 _errorCount++ ;
513 }
514
515 // Return C++ ostream associated with given message configuration
516 Int_t as = activeStream(self,topic,level) ;
517 if (as==-1) {
518 return *_devnull ;
519 }
520
521 // Flush any previous messages
522 (*_streams[as].os).flush() ;
523
524 if (_streams[as].prefix && !skipPrefix) {
525 if (_showPid) {
526 (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
527 }
528 (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic] << " -- " ;
529 }
530 return (*_streams[as].os) ;
531}
532
533
534
535////////////////////////////////////////////////////////////////////////////////
536/// Print configuration of message service. If "v" option is given also
537/// inactive streams are listed
538
539void RooMsgService::Print(Option_t *options) const
540{
541 Bool_t activeOnly = kTRUE ;
542 if (TString(options).Contains("V") || TString(options).Contains("v")) {
543 activeOnly = kFALSE ;
544 }
545
546 cout << (activeOnly?"Active Message streams":"All Message streams") << endl ;
547 for (UInt_t i=0 ; i<_streams.size() ; i++) {
548
549 // Skip passive streams in active only mode
550 if (activeOnly && !_streams[i].active) {
551 continue ;
552 }
553
554
555 map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
556 cout << "[" << i << "] MinLevel = " << is->second ;
557
558 cout << " Topic = " ;
559 if (_streams[i].topic != 0xFFFFF) {
560 map<int,string>::const_iterator iter = _topicNames.begin() ;
561 while(iter!=_topicNames.end()) {
562 if (iter->first & _streams[i].topic) {
563 cout << iter->second << " " ;
564 }
565 ++iter ;
566 }
567 } else {
568 cout << " Any " ;
569 }
570
571
572 if (_streams[i].objectName.size()>0) {
573 cout << " ObjectName = " << _streams[i].objectName ;
574 }
575 if (_streams[i].className.size()>0) {
576 cout << " ClassName = " << _streams[i].className ;
577 }
578 if (_streams[i].baseClassName.size()>0) {
579 cout << " BaseClassName = " << _streams[i].baseClassName ;
580 }
581 if (_streams[i].tagName.size()>0) {
582 cout << " TagLabel = " << _streams[i].tagName ;
583 }
584
585 // Postfix status when printing all
586 if (!activeOnly && !_streams[i].active) {
587 cout << " (NOT ACTIVE)" ;
588 }
589
590 cout << endl ;
591 }
592
593}
#define DEBUG
Definition: Polynomial.cxx:41
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:365
@ kBlack
Definition: Rtypes.h:63
XFontStruct * id
Definition: TGX11.cxx:108
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:71
Bool_t getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Definition: RooAbsArg.cxx:284
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:28
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:36
The RooMsgService class is a singleton class that organizes informational, debugging,...
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.
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
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
Basic string class.
Definition: TString.h:131
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:717
TString as(SEXP s)
Definition: RExports.h:71
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
RooCmdArg Topic(Int_t topic)
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
Definition: RooGlobalFunc.h:65
MsgTopic
Topics for a RooMsgService::StreamConfig in RooMsgService.
Definition: RooGlobalFunc.h:67
@ Minimization
Definition: RooGlobalFunc.h:67
@ Generation
Definition: RooGlobalFunc.h:67
@ NumIntegration
Definition: RooGlobalFunc.h:69
@ Optimization
Definition: RooGlobalFunc.h:68
@ DataHandling
Definition: RooGlobalFunc.h:69
@ InputArguments
Definition: RooGlobalFunc.h:68
@ ObjectHandling
Definition: RooGlobalFunc.h:68
@ Integration
Definition: RooGlobalFunc.h:67
@ LinkStateMgmt
Definition: RooGlobalFunc.h:67
static constexpr double pc
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