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