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