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