/* $Id$ */
-///
-/// class for logging debug, info and error messages
-///
-
-#include <TObject.h>
+#include <TClass.h>
#include <TObjArray.h>
+#include <TObject.h>
#include <TString.h>
+// deprecation macro
+#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define ALIROOT_DEPRECATED(func) func __attribute__ ((deprecated))
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+#define ALIROOT_DEPRECATED(func) __declspec(deprecated) func
+# else
+#define ALIROOT_DEPRECATED(func) func
+#endif
-class AliLog: public TObject {
+/**
+ * class for logging debug, info and error messages
+ */
+class AliLog: public TObject
+{
public:
- AliLog();
- virtual ~AliLog();
- static AliLog* Instance() {return fgInstance;}
+ // Log4j log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
enum EType_t {kFatal = 0, kError, kWarning, kInfo, kDebug, kMaxType};
+ typedef void (*AliLogNotification)(EType_t type, const char* message );
+
+ // NB: singleton constructor & destructor should not be public!
+ // ALIROOT_DEPRECATED(AliLog());
+ // ALIROOT_DEPRECATED(virtual ~AliLog());
+ // NB: singleton deprecated static instance method
+ // ALIROOT_DEPRECATED(static AliLog* Instance() {return fgInstance;};)
+
+ // get root logger singleton instance
+ static AliLog *GetRootLogger();
+
+ // delete root logger singleton instance
+ static void DeleteRootLogger();
+
+ // NB: the following functions should not be static
+ // NB: deprecated: logging configuration should be made through to a configuration file
static void EnableDebug(Bool_t enabled);
static void SetGlobalLogLevel(EType_t type);
static Int_t GetGlobalLogLevel();
static void SetErrorOutput(EType_t type);
static void SetFileOutput(const char* fileName);
static void SetFileOutput(EType_t type, const char* fileName);
+ static void SetStreamOutput(ostream* stream);
+ static void SetStreamOutput(EType_t type, ostream* stream);
+ static void SetLogNotification(AliLogNotification pCallBack);
+ static void SetLogNotification(EType_t type, AliLogNotification pCallBack);
static void Flush();
static void SetHandleRootMessages(Bool_t on);
const char* function, const char* file, Int_t line);
private:
+
+ // constructor is made private for implementing a singleton
+ AliLog();
+ virtual ~AliLog();
+
+ // NOT IMPLEMENTED?
AliLog(const AliLog& log);
AliLog& operator = (const AliLog& log);
const char* module, const char* className,
const char* function,
const char* file, Int_t line);
+
+ void PrintString(Int_t type, FILE* stream, const char* format, ...);
void PrintRepetitions();
Int_t RedirectTo(FILE* stream, EType_t type, UInt_t level,
enum {kDebugOffset = kDebug-1};
static AliLog* fgInstance; //! pointer to current instance
-
static Bool_t fgDebugEnabled; // flag for debug en-/disabling
UInt_t fGlobalLogLevel; // global logging level
Int_t fOutputTypes[kMaxType]; // types of output streams
TString fFileNames[kMaxType]; // file names
FILE* fOutputFiles[kMaxType]; //! log output files
- ofstream* fOutputStreams[kMaxType]; //! log output streams
+ ostream* fOutputStreams[kMaxType]; //! log output streams
Bool_t fPrintType[kMaxType]; // print type on/off
Bool_t fPrintModule[kMaxType]; // print module on/off
TString fLastFunction; //! function name of last message
TString fLastFile; //! file name of last message
Int_t fLastLine; //! line number of last message
+ AliLogNotification fCallBacks[kMaxType]; //! external notification callback
ClassDef(AliLog, 1) // class for logging debug, info and error messages
};
-// module name
+// module name macro
#ifdef _MODULE_
#define MODULENAME() _MODULE_
#else
#define MODULENAME() "NoModule"
#endif
-// function name
+// function name macro
#if defined(__GNUC__) || defined(__ICC) || defined(__ECC) || defined(__APPLE__)
#define FUNCTIONNAME() __FUNCTION__
// #elif defined(__HP_aCC) || defined(__alpha) || defined(__DECCXX)
#define AliDebugClass(level, message)
#define AliDebugGeneral(scope, level, message)
#else
-#define AliDebug(level, message) {if (AliLog::IsDebugEnabled()) AliLog::Debug(level, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__);}
-#define AliDebugClass(level, message) {if (AliLog::IsDebugEnabled()) AliLog::Debug(level, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__);}
-#define AliDebugGeneral(scope, level, message) {if (AliLog::IsDebugEnabled()) AliLog::Debug(level, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__);}
+
+// inspired by log4cxx code (see log4cxx/Logger.h)
+// implements GCC branch prediction for increasing logging performance
+#if !defined(ALIROOT_UNLIKELY)
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+/**
+Provides optimization hint to the compiler
+to optimize for the expression being false.
+@param expr boolean expression.
+@returns value of expression.
+*/
+#define ALIROOT_UNLIKELY(expr) __builtin_expect(expr, 0)
+#else
+/**
+Provides optimization hint to the compiler
+to optimize for the expression being false.
+@param expr boolean expression.
+@returns value of expression.
+**/
+#define ALIROOT_UNLIKELY(expr) expr
+#endif
+#endif
+
+/**
+Logs a message to a specified logger with the DEBUG level.
+
+@param logLevel the debug level.
+@param message message to print in the following format: Form(message).
+ Note, that message should contain balanced parenthesis, like
+ <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code>
+*/
+#define AliDebug(logLevel, message) \
+ do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), ClassName()) >= logLevel)) {\
+ AliLog::Debug(logLevel, message, MODULENAME(), ClassName(), FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
+
+/**
+Logs a message to a specified logger with the DEBUG level.
+
+@param logLevel the debug level.
+@param message message to print in the following format: Form(message).
+ Note, that message should contain balanced parenthesis, like
+ <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code>
+*/
+#define AliDebugClass(logLevel, message) \
+ do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), Class()->GetName()) >= logLevel)) {\
+ AliLog::Debug(logLevel, message, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
+
+/**
+Logs a message to a specified logger with the DEBUG level.
+
+@param scope the logging scope.
+@param logLevel the debug level.
+@param message message to print in the following format: Form(message).
+ Note, that message should contain balanced parenthesis, like
+ <code>AliDebug(1, Form("Failed to decode line %d of %s", line, filename));</code>
+*/
+#define AliDebugGeneral(scope, logLevel, message) \
+ do { if (ALIROOT_UNLIKELY(AliLog::IsDebugEnabled() && AliLog::GetDebugLevel(MODULENAME(), scope) >= logLevel)) {\
+ AliLog::Debug(logLevel, message, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__); }} while (0)
+
#endif
// redirection to debug
#define AliInfoClassStream() AliLog::Stream(AliLog::kInfo, 0, MODULENAME(), Class()->GetName(), FUNCTIONNAME(), __FILE__, __LINE__)
#define AliInfoGeneralStream(scope) AliLog::Stream(AliLog::kInfo, 0, MODULENAME(), scope, FUNCTIONNAME(), __FILE__, __LINE__)
-
// warning messages
#ifdef LOG_NO_WARNING
#define AliWarning(message)