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