Logo ROOT   6.12/07
Reference Guide
MsgLogger.cxx
Go to the documentation of this file.
1 // @(#)root/tmva $Id$
2 // Author: Attila Krasznahorkay, Andreas Hoecker, Joerg Stelzer, Eckhard von Toerne
3 
4 /**********************************************************************************
5  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6  * Package: TMVA *
7  * Class : MsgLogger *
8  * Web : http://tmva.sourceforge.net *
9  * *
10  * Description: *
11  * Implementation (see header for description) *
12  * *
13  * Author: *
14  * Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> - CERN, Switzerland *
15  * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
16  * Joerg Stelzer <stelzer@cern.ch> - DESY, Germany *
17  * Eckhard v. Toerne <evt@uni-bonn.de> - U of Bonn, Germany *
18  * *
19  * Copyright (c) 2005-2011: *
20  * CERN, Switzerland *
21  * U. of Victoria, Canada *
22  * MPI-K Heidelberg, Germany *
23  * U. of Bonn, Germany *
24  * *
25  * Redistribution and use in source and binary forms, with or without *
26  * modification, are permitted according to the terms listed in LICENSE *
27  * (http://tmva.sourceforge.net/LICENSE) *
28  **********************************************************************************/
29 
30 /*! \class TMVA::MsgLogger
31 \ingroup TMVA
32 ostringstream derivative to redirect and format output
33 */
34 
35 // Local include(s):
36 #include "TMVA/MsgLogger.h"
37 
38 #include "TMVA/Config.h"
39 #include "TMVA/Types.h"
40 
41 // ROOT include(s):
42 #include "Riostream.h"
43 #include "Rtypes.h"
44 #include "TObject.h"
45 
46 // STL include(s):
47 #include <assert.h>
48 #include <cstdlib>
49 #include <iomanip>
50 #include <memory>
51 
52 
54 
55 // declaration of global variables
56 // this is the hard-coded maximum length of the source names
58 
59 const std::string TMVA::MsgLogger::fgPrefix = "";
60 const std::string TMVA::MsgLogger::fgSuffix = ": ";
61 #if __cplusplus > 199711L
62 std::atomic<Bool_t> TMVA::MsgLogger::fgInhibitOutput{kFALSE};
63 std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgTypeMap{0};
64 std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgColorMap{0};
65 #else
67 const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgTypeMap = 0;
68 const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgColorMap = 0;
69 #endif
70 static std::unique_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnTypeMap;
71 static std::unique_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnColorMap;
72 
73 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// constructor
78 
79 TMVA::MsgLogger::MsgLogger( const TObject* source, EMsgType minType )
80  : fObjSource ( source ),
81  fStrSource ( "" ),
82  fActiveType( kINFO ),
83  fMinType ( minType )
84 {
85  InitMaps();
86 }
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// constructor
90 
91 TMVA::MsgLogger::MsgLogger( const std::string& source, EMsgType minType )
92  : fObjSource ( 0 ),
93  fStrSource ( source ),
94  fActiveType( kINFO ),
95  fMinType ( minType )
96 {
97  InitMaps();
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// constructor
102 
103 TMVA::MsgLogger::MsgLogger( EMsgType minType )
104  : fObjSource ( 0 ),
105  fStrSource ( "Unknown" ),
106  fActiveType( kINFO ),
107  fMinType ( minType )
108 {
109  InitMaps();
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// copy constructor
114 
116  : std::basic_ios<MsgLogger::char_type, MsgLogger::traits_type>(),
117  std::ostringstream(),
118  TObject(),
119  fObjSource(0)
120 {
121  InitMaps();
122  *this = parent;
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// destructor
127 
129 {
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// assignment operator
134 
136 {
137  if (&parent != this) {
138  fObjSource = parent.fObjSource;
139  fStrSource = parent.fStrSource;
140  fActiveType = parent.fActiveType;
141  fMinType = parent.fMinType;
142  }
143 
144  return *this;
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 /// make sure the source name is no longer than fgMaxSourceSize:
149 
151 {
152  std::string source_name;
153  if (fActiveType == kHEADER)
154  {
155  source_name = fStrSource;
156  }
157  if (fActiveType == kWARNING)
158  {
159  source_name ="<WARNING>";
160  }
161  if (source_name.size() > fgMaxSourceSize) {
162  source_name = source_name.substr( 0, fgMaxSourceSize - 3 );
163  source_name += "...";
164  }
165 
166  return source_name;
167 }
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// the full logger prefix
171 
173 {
174  std::string source_name = GetFormattedSource();
175  if (source_name.size() < fgMaxSourceSize)
176  for (std::string::size_type i=source_name.size(); i<fgMaxSourceSize; i++) source_name.push_back( ' ' );
177 
178  return fgPrefix + source_name + fgSuffix;
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// activates the logger writer
183 
185 {
186  // make sure the source name is no longer than fgMaxSourceSize:
187  std::string source_name = GetFormattedSource();
188 
189  std::string message = this->str();
190  std::string::size_type previous_pos = 0, current_pos = 0;
191 
192  // slice the message into lines:
193  while (kTRUE) {
194  current_pos = message.find( '\n', previous_pos );
195  std::string line = message.substr( previous_pos, current_pos - previous_pos );
196 
197  std::ostringstream message_to_send;
198  // must call the modifiers like this, otherwise g++ get's confused with the operators...
199  message_to_send.setf( std::ios::adjustfield, std::ios::left );
200  message_to_send.width( fgMaxSourceSize );
201  message_to_send << source_name << fgSuffix << line;
202  std::string msg = message_to_send.str();
203  this->WriteMsg( fActiveType, msg );
204 
205  if (current_pos == message.npos) break;
206  previous_pos = current_pos + 1;
207  }
208 
209  // reset the stream buffer:
210  this->str( "" );
211  fActiveType = kINFO; // To always print messages that have no level specified...
212  return;
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// putting the output string, the message type, and the color
217 /// switcher together into a single string
218 
219 void TMVA::MsgLogger::WriteMsg( EMsgType type, const std::string& line ) const
220 {
221  if ( (type < fMinType || fgInhibitOutput) && type!=kFATAL ) return; // no output
222 
223  std::map<EMsgType, std::string>::const_iterator stype;
224 
225  if ((stype = fgTypeMap.load()->find( type )) != fgTypeMap.load()->end()) {
226  if (!gConfig().IsSilent() || type==kFATAL) {
227  if (gConfig().UseColor()) {
228  // no text for INFO or VERBOSE
229  if (type == kHEADER || type ==kWARNING)
230  std::cout << fgPrefix << line << std::endl;
231  else if (type == kINFO || type == kVERBOSE)
232  //std::cout << fgPrefix << line << std::endl; // no color for info
233  std::cout << line << std::endl;
234  else{
235  //std::cout<<"prefix='"<<fgPrefix<<"'"<<std::endl;
236  std::cout << fgColorMap.load()->find( type )->second << "<" << stype->second << ">" << line << "\033[0m" << std::endl;
237 }
238  }
239 
240  else {
241  if (type == kINFO) std::cout << fgPrefix << line << std::endl;
242  else std::cout << fgPrefix << "<" << stype->second << "> " << line << std::endl;
243  }
244  }
245  }
246 
247  // take decision to stop if fatal error
248  if (type == kFATAL) {
249  std::cout << "***> abort program execution" << std::endl;
250  throw std::runtime_error("FATAL error");
251 
252  //std::exit(1);
253  //assert(false);
254  }
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// end line
259 
261 {
262  logger.Send();
263  return logger;
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 /// Create the message type and color maps
268 
270 {
271  if(!fgTypeMap) {
272  std::map<TMVA::EMsgType, std::string>*tmp = new std::map<TMVA::EMsgType, std::string>();
273 
274  (*tmp)[kVERBOSE] = std::string("VERBOSE");
275  (*tmp)[kDEBUG] = std::string("DEBUG");
276  (*tmp)[kINFO] = std::string("INFO");
277  (*tmp)[kWARNING] = std::string("WARNING");
278  (*tmp)[kERROR] = std::string("ERROR");
279  (*tmp)[kFATAL] = std::string("FATAL");
280  (*tmp)[kSILENT] = std::string("SILENT");
281  (*tmp)[kHEADER] = std::string("HEADER");
282  const std::map<TMVA::EMsgType, std::string>* expected=0;
283  if(fgTypeMap.compare_exchange_strong(expected,tmp)) {
284  //Have the global own this
285  gOwnTypeMap.reset(tmp);
286  } else {
287  //Another thread beat us in creating the instance
288  delete tmp;
289  }
290  }
291 
292  if(!fgColorMap) {
293  std::map<TMVA::EMsgType, std::string>*tmp = new std::map<TMVA::EMsgType, std::string>();
294 
295  (*tmp)[kVERBOSE] = std::string("");
296  (*tmp)[kDEBUG] = std::string("\033[34m");
297  (*tmp)[kINFO] = std::string("");
298  (*tmp)[kWARNING] = std::string("\033[1;31m");
299  (*tmp)[kERROR] = std::string("\033[31m");
300  (*tmp)[kFATAL] = std::string("\033[37;41;1m");
301  (*tmp)[kSILENT] = std::string("\033[30m");
302 
303  const std::map<TMVA::EMsgType, std::string>* expected=0;
304  if(fgColorMap.compare_exchange_strong(expected,tmp)) {
305  //Have the global own this
306  gOwnColorMap.reset(tmp);
307  } else {
308  //Another thread beat us in creating the instance
309  delete tmp;
310  }
311  }
312 }
TLine * line
~MsgLogger()
destructor
Definition: MsgLogger.cxx:128
EMsgType fMinType
Definition: MsgLogger.h:129
static const std::string fgPrefix
Definition: MsgLogger.h:112
Config & gConfig()
bool Bool_t
Definition: RtypesCore.h:59
void Send()
activates the logger writer
Definition: MsgLogger.cxx:184
STL namespace.
const TObject * fObjSource
Definition: MsgLogger.h:110
static Bool_t fgInhibitOutput
Definition: MsgLogger.h:124
static void InhibitOutput()
Definition: MsgLogger.cxx:74
static std::unique_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnColorMap
Definition: MsgLogger.cxx:71
static const std::map< EMsgType, std::string > * fgTypeMap
Definition: MsgLogger.h:126
static const UInt_t fgMaxSourceSize
Definition: MsgLogger.h:115
MsgLogger(const TObject *source, EMsgType minType=kINFO)
constructor
Definition: MsgLogger.cxx:79
EMsgType fActiveType
Definition: MsgLogger.h:114
std::string GetPrintedSource() const
the full logger prefix
Definition: MsgLogger.cxx:172
MsgLogger & operator=(const MsgLogger &parent)
assignment operator
Definition: MsgLogger.cxx:135
void WriteMsg(EMsgType type, const std::string &line) const
putting the output string, the message type, and the color switcher together into a single string ...
Definition: MsgLogger.cxx:219
void InitMaps()
Create the message type and color maps.
Definition: MsgLogger.cxx:269
unsigned int UInt_t
Definition: RtypesCore.h:42
static const std::string fgSuffix
Definition: MsgLogger.h:113
std::string fStrSource
Definition: MsgLogger.h:111
const Bool_t kFALSE
Definition: RtypesCore.h:88
#define ClassImp(name)
Definition: Rtypes.h:359
int type
Definition: TGX11.cxx:120
static MsgLogger & Endmsg(MsgLogger &logger)
end line
Definition: MsgLogger.cxx:260
std::string GetFormattedSource() const
make sure the source name is no longer than fgMaxSourceSize:
Definition: MsgLogger.cxx:150
ostringstream derivative to redirect and format output
Definition: MsgLogger.h:59
static const std::map< EMsgType, std::string > * fgColorMap
Definition: MsgLogger.h:127
Mother of all ROOT objects.
Definition: TObject.h:37
static std::unique_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnTypeMap
Definition: MsgLogger.cxx:70
Bool_t IsSilent() const
Definition: Config.h:67
Bool_t UseColor() const
Definition: Config.h:64
static void EnableOutput()
Definition: MsgLogger.cxx:75
const Bool_t kTRUE
Definition: RtypesCore.h:87