Logo ROOT  
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
32ostringstream 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
59const std::string TMVA::MsgLogger::fgPrefix = "";
60const std::string TMVA::MsgLogger::fgSuffix = ": ";
61#if __cplusplus > 199711L
62std::atomic<Bool_t> TMVA::MsgLogger::fgInhibitOutput{kFALSE};
63std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgTypeMap{0};
64std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgColorMap{0};
65#else
67const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgTypeMap = 0;
68const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgColorMap = 0;
69#endif
70static std::unique_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnTypeMap;
71static std::unique_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnColorMap;
72
73
75void TMVA::MsgLogger::EnableOutput() { fgInhibitOutput = kFALSE; }
76////////////////////////////////////////////////////////////////////////////////
77/// constructor
78
79TMVA::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
91TMVA::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
103TMVA::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
219void 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}
static std::unique_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnTypeMap
Definition: MsgLogger.cxx:70
static std::unique_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnColorMap
Definition: MsgLogger.cxx:71
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
int type
Definition: TGX11.cxx:120
ostringstream derivative to redirect and format output
Definition: MsgLogger.h:59
static const UInt_t fgMaxSourceSize
Definition: MsgLogger.h:115
static const std::string fgPrefix
Definition: MsgLogger.h:112
~MsgLogger()
destructor
Definition: MsgLogger.cxx:128
MsgLogger(const TObject *source, EMsgType minType=kINFO)
constructor
Definition: MsgLogger.cxx:79
MsgLogger & operator=(const MsgLogger &parent)
assignment operator
Definition: MsgLogger.cxx:135
std::string GetPrintedSource() const
the full logger prefix
Definition: MsgLogger.cxx:172
std::string fStrSource
Definition: MsgLogger.h:111
static void InhibitOutput()
Definition: MsgLogger.cxx:74
const TObject * fObjSource
Definition: MsgLogger.h:110
static const std::string fgSuffix
Definition: MsgLogger.h:113
static void EnableOutput()
Definition: MsgLogger.cxx:75
static const std::map< EMsgType, std::string > * fgTypeMap
Definition: MsgLogger.h:126
EMsgType fMinType
Definition: MsgLogger.h:129
std::string GetFormattedSource() const
make sure the source name is no longer than fgMaxSourceSize:
Definition: MsgLogger.cxx:150
static Bool_t fgInhibitOutput
Definition: MsgLogger.h:124
void InitMaps()
Create the message type and color maps.
Definition: MsgLogger.cxx:269
EMsgType fActiveType
Definition: MsgLogger.h:114
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
static MsgLogger & Endmsg(MsgLogger &logger)
end line
Definition: MsgLogger.cxx:260
static const std::map< EMsgType, std::string > * fgColorMap
Definition: MsgLogger.h:127
void Send()
activates the logger writer
Definition: MsgLogger.cxx:184
Mother of all ROOT objects.
Definition: TObject.h:37
TLine * line
Config & gConfig()