1155f5faae5b7d613c3f18c50eb679e0a6892a83
[u/mrichter/AliRoot.git] / STEER / AliLog.h
1 #ifndef ALILOG_H
2 #define ALILOG_H
3 /* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4  * See cxx source for full Copyright notice                               */
5
6 /* $Id$ */
7
8 #include <TClass.h>
9 #include <TObjArray.h>
10 #include <TObject.h>
11 #include <TString.h>
12
13 // deprecation macro
14 #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
15 #define ALIROOT_DEPRECATED(func) func  __attribute__ ((deprecated))
16 #elif defined(_MSC_VER) && _MSC_VER >= 1300
17 #define ALIROOT_DEPRECATED(func) __declspec(deprecated) func
18 # else
19 #define ALIROOT_DEPRECATED(func) func
20 #endif
21
22 /**
23  * class for logging debug, info and error messages
24  */
25 class AliLog: public TObject
26 {
27  public:
28
29                 // Log4j log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
30   enum EType_t {kFatal = 0, kError, kWarning, kInfo, kDebug, kMaxType};
31   typedef void (*AliLogNotification)(EType_t type, const char* message );
32
33                 // NB: singleton constructor & destructor should not be public!
34                 // ALIROOT_DEPRECATED(AliLog());
35                 // ALIROOT_DEPRECATED(virtual ~AliLog());
36
37                 // NB: singleton deprecated static instance method
38                 // ALIROOT_DEPRECATED(static AliLog* Instance() {return fgInstance;};)
39
40                 // get root logger singleton instance
41                 static AliLog *GetRootLogger();
42
43                 // delete root logger singleton instance
44                 static void DeleteRootLogger();
45
46                 // NB: the following functions should not be static
47                 // NB: deprecated: logging configuration should be made through to a configuration file
48   static void  EnableDebug(Bool_t enabled);
49   static void  SetGlobalLogLevel(EType_t type);
50   static Int_t GetGlobalLogLevel();
51   static void  SetGlobalDebugLevel(Int_t level);
52   static Int_t GetGlobalDebugLevel();
53   static void  SetModuleDebugLevel(const char* module, Int_t level);
54   static void  ClearModuleDebugLevel(const char* module);
55   static void  SetClassDebugLevel(const char* className, Int_t level);
56   static void  ClearClassDebugLevel(const char* className);
57
58   static void  SetStandardOutput();
59   static void  SetStandardOutput(EType_t type);
60   static void  SetErrorOutput();
61   static void  SetErrorOutput(EType_t type);
62   static void  SetFileOutput(const char* fileName);
63   static void  SetFileOutput(EType_t type, const char* fileName);
64   static void  SetStreamOutput(ostream* stream);
65   static void  SetStreamOutput(EType_t type, ostream* stream);
66   static void  SetLogNotification(AliLogNotification pCallBack);
67   static void  SetLogNotification(EType_t type, AliLogNotification pCallBack);
68   static void  Flush();
69
70   static void  SetHandleRootMessages(Bool_t on);
71
72   static void  SetPrintType(Bool_t on);
73   static void  SetPrintType(EType_t type, Bool_t on);
74   static void  SetPrintModule(Bool_t on);
75   static void  SetPrintModule(EType_t type, Bool_t on);
76   static void  SetPrintScope(Bool_t on);
77   static void  SetPrintScope(EType_t type, Bool_t on);
78   static void  SetPrintLocation(Bool_t on);
79   static void  SetPrintLocation(EType_t type, Bool_t on);
80
81   static void  SetPrintRepetitions(Bool_t on);
82
83   static void  WriteToFile(const char* name, Int_t option = 0);
84
85   // the following public methods are used by the preprocessor macros 
86   // and should not be called directly
87   static Bool_t IsDebugEnabled() {return fgDebugEnabled;}
88   static Int_t GetDebugLevel(const char* module, const char* className);
89   static void  Message(UInt_t level, const char* message, 
90                        const char* module, const char* className,
91                        const char* function, const char* file, Int_t line);
92   static void  Debug(UInt_t level, const char* message, 
93                      const char* module, const char* className,
94                      const char* function, const char* file, Int_t line);
95
96   static Int_t RedirectStdoutTo(EType_t type, UInt_t level, const char* module, 
97                                 const char* className, const char* function,
98                                 const char* file, Int_t line, Bool_t print);
99   static Int_t RedirectStderrTo(EType_t type, UInt_t level, const char* module, 
100                                 const char* className, const char* function,
101                                 const char* file, Int_t line, Bool_t print);
102   static void  RestoreStdout(Int_t original);
103   static void  RestoreStderr(Int_t original);
104
105   static ostream& Stream(EType_t type, UInt_t level,
106                          const char* module, const char* className,
107                          const char* function, const char* file, Int_t line);
108
109  private:
110
111                 // constructor is made private for implementing a singleton
112                 AliLog();
113                 virtual ~AliLog();
114
115                 // NOT IMPLEMENTED?
116   AliLog(const AliLog& log);
117   AliLog& operator = (const AliLog& log);
118
119   void           ReadEnvSettings();
120
121   static void    RootErrorHandler(Int_t level, Bool_t abort, 
122                                   const char* location, const char* message);
123
124   void           CloseFile(Int_t type);
125   FILE*          GetOutputStream(Int_t type);
126
127   UInt_t         GetLogLevel(const char* module, const char* className) const;
128   void           PrintMessage(UInt_t type, const char* message, 
129                               const char* module, const char* className,
130                               const char* function, 
131                               const char* file, Int_t line);
132
133   void           PrintString(Int_t type, FILE* stream, const char* format, ...);
134   void           PrintRepetitions();
135
136   Int_t          RedirectTo(FILE* stream, EType_t type, UInt_t level,
137                             const char* module, const char* className,
138                             const char* function,
139                             const char* file, Int_t line, Bool_t print);
140
141   ostream&       GetStream(EType_t type, UInt_t level,
142                            const char* module, const char* className,
143                            const char* function, const char* file, Int_t line);
144
145   enum {kDebugOffset = kDebug-1};
146
147   static AliLog* fgInstance;                 //! pointer to current instance
148   static Bool_t  fgDebugEnabled;             // flag for debug en-/disabling
149
150   UInt_t         fGlobalLogLevel;            // global logging level
151   TObjArray      fModuleDebugLevels;         // debug levels for modules
152   TObjArray      fClassDebugLevels;          // debug levels for classes
153
154   Int_t          fOutputTypes[kMaxType];     // types of output streams
155   TString        fFileNames[kMaxType];       // file names
156   FILE*          fOutputFiles[kMaxType];     //! log output files
157   ostream*       fOutputStreams[kMaxType];   //! log output streams
158
159   Bool_t         fPrintType[kMaxType];       // print type on/off
160   Bool_t         fPrintModule[kMaxType];     // print module on/off
161   Bool_t         fPrintScope[kMaxType];      // print scope/class name on/off
162   Bool_t         fPrintLocation[kMaxType];   // print file and line on/off
163
164   Bool_t         fPrintRepetitions;          // print number of repetitions instead of repeated message on/off
165
166   Int_t          fRepetitions;               //! counter of repetitions
167   UInt_t         fLastType;                  //! type of last message
168   TString        fLastMessage;               //! last message
169   TString        fLastModule;                //! module name of last message
170   TString        fLastClassName;             //! class name of last message
171   TString        fLastFunction;              //! function name of last message
172   TString        fLastFile;                  //! file name of last message
173   Int_t          fLastLine;                  //! line number of last message
174   AliLogNotification fCallBacks[kMaxType];   //! external notification callback
175
176   ClassDef(AliLog, 1)   // class for logging debug, info and error messages
177 };
178
179
180 // module name macro
181 #ifdef _MODULE_
182 #define MODULENAME() _MODULE_
183 #else
184 #define MODULENAME() "NoModule"
185 #endif
186
187 // function name macro
188 #if defined(__GNUC__) || defined(__ICC) || defined(__ECC) || defined(__APPLE__)
189 #define FUNCTIONNAME() __FUNCTION__
190 // #elif defined(__HP_aCC) || defined(__alpha) || defined(__DECCXX)
191 // #define FUNCTIONNAME() __FUNC__
192 #else
193 #define FUNCTIONNAME() "???"
194 #endif
195
196 // redirection
197 #define REDIRECTSTDOUT(type, level, scope, whatever) {Int_t originalStdout = AliLog::RedirectStdoutTo(type, level, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__, kFALSE); whatever; AliLog::RestoreStdout(originalStdout);}
198 #define REDIRECTSTDERR(type, level, scope, whatever) {Int_t originalStderr = AliLog::RedirectStderrTo(type, level, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__, kFALSE); whatever; AliLog::RestoreStderr(originalStderr);}
199 #define REDIRECTSTDOUTANDSTDERR(type, level, scope, whatever) {Int_t originalStdout = AliLog::RedirectStdoutTo(type, level, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__, kFALSE); Int_t originalStderr = AliLog::RedirectStderrTo(type, level, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__, kFALSE); whatever; AliLog::RestoreStderr(originalStderr); AliLog::RestoreStdout(originalStdout);}
200
201
202 // debug level
203 #ifdef LOG_NO_DEBUG
204 #define AliDebugLevel() -1
205 #define AliDebugLevelClass() -1
206 #define AliDebugLevelGeneral(scope) -1
207 #else
208 #define AliDebugLevel() ((AliLog::IsDebugEnabled()) ? AliLog::GetDebugLevel(MODULENAME(), ClassName()) : -1)
209 #define AliDebugLevelClass() ((AliLog::IsDebugEnabled()) ? AliLog::GetDebugLevel(MODULENAME(), Class()->GetName()) : -1)
210 #define AliDebugLevelGeneral(scope) ((AliLog::IsDebugEnabled()) ? AliLog::GetDebugLevel(MODULENAME(), scope) : -1)
211 #endif
212
213 // debug messages
214 #ifdef LOG_NO_DEBUG
215 #define AliDebug(level, message)
216 #define AliDebugClass(level, message)
217 #define AliDebugGeneral(scope, level, message)
218 #else
219
220 // inspired by log4cxx code (see log4cxx/Logger.h)
221 // implements GCC branch prediction for increasing logging performance
222 #if !defined(ALIROOT_UNLIKELY)
223 #if defined(__GNUC__) && (__GNUC__ >= 3)
224 /**
225 Provides optimization hint to the compiler
226 to optimize for the expression being false.
227 @param expr boolean expression.
228 @returns value of expression.
229 */
230 #define ALIROOT_UNLIKELY(expr) __builtin_expect(expr, 0)
231 #else
232 /**
233 Provides optimization hint to the compiler
234 to optimize for the expression being false.
235 @param expr boolean expression.
236 @returns value of expression.
237 **/
238 #define ALIROOT_UNLIKELY(expr) expr
239 #endif
240 #endif 
241
242 /**
243 Logs a message to a specified logger with the DEBUG level.
244
245 @param logLevel the debug level.
246 @param message message to print in the following format: Form(message).
247     Note, that message should contain balanced parenthesis, like 
248     <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code> 
249 */
250 #define AliDebug(logLevel, message) \
251         do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), ClassName()) >= logLevel)) {\
252           AliLog::Debug(logLevel, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
253
254 /**
255 Logs a message to a specified logger with the DEBUG level.
256
257 @param logLevel the debug level.
258 @param message message to print in the following format: Form(message).
259     Note, that message should contain balanced parenthesis, like 
260     <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code> 
261 */
262 #define AliDebugClass(logLevel, message) \
263         do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), Class()->GetName()) >= logLevel)) {\
264           AliLog::Debug(logLevel, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
265
266 /**
267 Logs a message to a specified logger with the DEBUG level.
268
269 @param scope the logging scope.
270 @param logLevel the debug level.
271 @param message message to print in the following format: Form(message).
272     Note, that message should contain balanced parenthesis, like 
273     <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code> 
274 */
275 #define AliDebugGeneral(scope, logLevel, message) \
276         do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), scope) >= logLevel)) {\
277           AliLog::Debug(logLevel, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
278
279 #endif
280
281 // redirection to debug
282 #define StdoutToAliDebug(level, whatever) REDIRECTSTDOUT(AliLog::kDebug, level, ClassName(), whatever)
283 #define StderrToAliDebug(level, whatever) REDIRECTSTDERR(AliLog::kDebug, level, ClassName(), whatever)
284 #define ToAliDebug(level, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kDebug, level, ClassName(), whatever)
285 #define StdoutToAliDebugClass(level, whatever) REDIRECTSTDOUT(AliLog::kDebug, level, Class()->GetName(), whatever)
286 #define StderrToAliDebugClass(level, whatever) REDIRECTSTDERR(AliLog::kDebug, level, Class()->GetName(), whatever)
287 #define ToAliDebugClass(level, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kDebug, level, Class()->GetName(), whatever)
288 #define StdoutToAliDebugGeneral(scope, level, whatever) REDIRECTSTDOUT(AliLog::kDebug, level, scope, whatever)
289 #define StderrToAliDebugGeneral(scope, level, whatever) REDIRECTSTDERR(AliLog::kDebug, level, scope, whatever)
290 #define ToAliDebugGeneral(scope, level, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kDebug, level, scope, whatever)
291
292 // debug stream objects
293 #define AliDebugStream(level) AliLog::Stream(AliLog::kDebug, level, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__)
294 #define AliDebugClassStream(level) AliLog::Stream(AliLog::kDebug, level, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__)
295 #define AliDebugGeneralStream(scope, level) AliLog::Stream(AliLog::kDebug, level, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__)
296
297
298 // info messages
299 #ifdef LOG_NO_INFO
300 #define AliInfo(message)
301 #define AliInfoClass(message)
302 #define AliInfoGeneral(scope, message)
303 #else
304 #define AliInfo(message) {AliLog::Message(AliLog::kInfo, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__);}
305 #define AliInfoClass(message) {AliLog::Message(AliLog::kInfo, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__);}
306 #define AliInfoGeneral(scope, message) {AliLog::Message(AliLog::kInfo, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__);}
307 #endif
308
309 // redirection to info
310 #define StdoutToAliInfo(whatever) REDIRECTSTDOUT(AliLog::kInfo, 0, ClassName(), whatever)
311 #define StderrToAliInfo(whatever) REDIRECTSTDERR(AliLog::kInfo, 0, ClassName(), whatever)
312 #define ToAliInfo(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kInfo, 0, ClassName(), whatever)
313 #define StdoutToAliInfoClass(whatever) REDIRECTSTDOUT(AliLog::kInfo, 0, Class()->GetName(), whatever)
314 #define StderrToAliInfoClass(whatever) REDIRECTSTDERR(AliLog::kInfo, 0, Class()->GetName(), whatever)
315 #define ToAliInfoClass(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kInfo, 0, Class()->GetName(), whatever)
316 #define StdoutToAliInfoGeneral(scope, whatever) REDIRECTSTDOUT(AliLog::kInfo, 0, scope, whatever)
317 #define StderrToAliInfoGeneral(scope, whatever) REDIRECTSTDERR(AliLog::kInfo, 0, scope, whatever)
318 #define ToAliInfoGeneral(scope, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kInfo, 0, scope, whatever)
319
320 // info stream objects
321 #define AliInfoStream() AliLog::Stream(AliLog::kInfo, 0, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__)
322 #define AliInfoClassStream() AliLog::Stream(AliLog::kInfo, 0, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__)
323 #define AliInfoGeneralStream(scope) AliLog::Stream(AliLog::kInfo, 0, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__)
324
325 // warning messages
326 #ifdef LOG_NO_WARNING
327 #define AliWarning(message)
328 #define AliWarningClass(message)
329 #define AliWarningGeneral(scope, message)
330 #else
331 #define AliWarning(message) {AliLog::Message(AliLog::kWarning, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__);}
332 #define AliWarningClass(message) {AliLog::Message(AliLog::kWarning, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__);}
333 #define AliWarningGeneral(scope, message) {AliLog::Message(AliLog::kWarning, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__);}
334 #endif
335
336 // redirection to warning
337 #define StdoutToAliWarning(whatever) REDIRECTSTDOUT(AliLog::kWarning, 0, ClassName(), whatever)
338 #define StderrToAliWarning(whatever) REDIRECTSTDERR(AliLog::kWarning, 0, ClassName(), whatever)
339 #define ToAliWarning(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kWarning, 0, ClassName(), whatever)
340 #define StdoutToAliWarningClass(whatever) REDIRECTSTDOUT(AliLog::kWarning, 0, Class()->GetName(), whatever)
341 #define StderrToAliWarningClass(whatever) REDIRECTSTDERR(AliLog::kWarning, 0, Class()->GetName(), whatever)
342 #define ToAliWarningClass(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kWarning, 0, Class()->GetName(), whatever)
343 #define StdoutToAliWarningGeneral(scope, whatever) REDIRECTSTDOUT(AliLog::kWarning, 0, scope, whatever)
344 #define StderrToAliWarningGeneral(scope, whatever) REDIRECTSTDERR(AliLog::kWarning, 0, scope, whatever)
345 #define ToAliWarningGeneral(scope, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kWarning, 0, scope, whatever)
346
347 // warning stream objects
348 #define AliWarningStream() AliLog::Stream(AliLog::kWarning, 0, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__)
349 #define AliWarningClassStream() AliLog::Stream(AliLog::kWarning, 0, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__)
350 #define AliWarningGeneralStream(scope) AliLog::Stream(AliLog::kWarning, 0, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__)
351
352
353 // error messages
354 #define AliError(message) {AliLog::Message(AliLog::kError, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__);}
355 #define AliErrorClass(message) {AliLog::Message(AliLog::kError, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__);}
356 #define AliErrorGeneral(scope, message) {AliLog::Message(AliLog::kError, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__);}
357
358 // redirection to error
359 #define StdoutToAliError(whatever) REDIRECTSTDOUT(AliLog::kError, 0, ClassName(), whatever)
360 #define StderrToAliError(whatever) REDIRECTSTDERR(AliLog::kError, 0, ClassName(), whatever)
361 #define ToAliError(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kError, 0, ClassName(), whatever)
362 #define StdoutToAliErrorClass(whatever) REDIRECTSTDOUT(AliLog::kError, 0, Class()->GetName(), whatever)
363 #define StderrToAliErrorClass(whatever) REDIRECTSTDERR(AliLog::kError, 0, Class()->GetName(), whatever)
364 #define ToAliErrorClass(whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kError, 0, Class()->GetName(), whatever)
365 #define StdoutToAliErrorGeneral(scope, whatever) REDIRECTSTDOUT(AliLog::kError, 0, scope, whatever)
366 #define StderrToAliErrorGeneral(scope, whatever) REDIRECTSTDERR(AliLog::kError, 0, scope, whatever)
367 #define ToAliErrorGeneral(scope, whatever) REDIRECTSTDOUTANDSTDERR(AliLog::kError, 0, scope, whatever)
368
369 // error stream objects
370 #define AliErrorStream() AliLog::Stream(AliLog::kError, 0, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__)
371 #define AliErrorClassStream() AliLog::Stream(AliLog::kError, 0, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__)
372 #define AliErrorGeneralStream(scope) AliLog::Stream(AliLog::kError, 0, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__)
373
374
375 // fatal messages
376 #define AliFatal(message) {AliLog::Message(AliLog::kFatal, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__);}
377 #define AliFatalClass(message) {AliLog::Message(AliLog::kFatal, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__);}
378 #define AliFatalGeneral(scope, message) {AliLog::Message(AliLog::kFatal, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__);}
379
380 #endif