// //
///////////////////////////////////////////////////////////////////////////////
+#include <Riostream.h>
#include <TError.h>
#include <TNamed.h>
#include <TSystem.h>
+#include <TEnv.h>
#include "AliLog.h"
fOutputTypes[iType] = 0;
fFileNames[iType] = "";
fOutputFiles[iType] = NULL;
+ fOutputStreams[iType] = NULL;
fPrintType[iType] = kTRUE;
fPrintModule[iType] = kFALSE;
// replace the previous instance by this one
if (fgInstance) delete fgInstance;
fgInstance = this;
+
+ // read the .rootrc settings
+ ReadEnvSettings();
}
//_____________________________________________________________________________
}
+//_____________________________________________________________________________
+void AliLog::ReadEnvSettings()
+{
+// load settings from the root configuration file (.rootrc)
+// and from environment variables
+
+ static const char* typeNames[kMaxType] =
+ {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
+
+ // debug en- or disabling
+ if (gSystem->Getenv("LOG_NO_DEBUG")) {
+ fgDebugEnabled = kFALSE;
+ } else if (gEnv->Defined("AliRoot.AliLog.EnableDebug")) {
+ fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug",
+ fgDebugEnabled);
+ AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
+ }
+
+ // global log level
+ if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel")) {
+ const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
+ }
+ AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
+ }
+
+ // global debug level
+ if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel")) {
+ Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel",
+ Int_t(fGlobalLogLevel - kDebugOffset));
+ if (level < -kDebugOffset) level = kDebugOffset;
+ fGlobalLogLevel = kDebugOffset + level;
+ AliDebug(3, Form("global debug level set to %d",
+ fGlobalLogLevel - kDebugOffset));
+ }
+
+ // module debug level
+ if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel")) {
+ TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
+ char* p = const_cast<char*>(levels.Data());
+ while (const char* module = strtok(p, " ")) {
+ p = NULL;
+ char* pos = index(module, ':');
+ if (!pos) continue;
+ *(pos++) = '\0';
+ Int_t level = atoi(pos);
+ SetModuleDebugLevel(module, level);
+ AliDebug(3, Form("debug level for module %s set to %d", module, level));
+ }
+ }
+
+ // class debug level
+ if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel")) {
+ TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
+ char* p = const_cast<char*>(levels.Data());
+ while (const char* className = strtok(p, " ")) {
+ p = NULL;
+ char* pos = index(className, ':');
+ if (!pos) continue;
+ *(pos++) = '\0';
+ Int_t level = atoi(pos);
+ SetClassDebugLevel(className, level);
+ AliDebug(3, Form("debug level for class %s set to %d",
+ className, level));
+ }
+ }
+
+ // general output stream
+ if (gEnv->Defined("AliRoot.AliLog.Output")) {
+ TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
+ if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
+ SetStandardOutput();
+ AliDebug(3, "output stream set to standard output for all types");
+ } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
+ SetErrorOutput();
+ AliDebug(3, "output stream set to error output for all types");
+ } else if (!stream.IsNull()) {
+ SetFileOutput(stream);
+ AliDebug(3, Form("output stream set to file %s for all types",
+ stream.Data()));
+ }
+ }
+
+ // individual output streams
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ TString name("AliRoot.AliLog.Output.");
+ name += &typeNames[iType][1];
+ if (gEnv->Defined(name)) {
+ TString stream = gEnv->GetValue(name, "Standard");
+ if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
+ SetStandardOutput(EType(iType));
+ AliDebug(3, Form("output stream set to standard output for type %s",
+ typeNames[iType]));
+ } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
+ SetErrorOutput(EType(iType));
+ AliDebug(3, Form("output stream set to error output for type %s",
+ typeNames[iType]));
+ } else if (!stream.IsNull()) {
+ SetFileOutput(EType(iType), stream);
+ AliDebug(3, Form("output stream set to file %s for type %s",
+ stream.Data(), typeNames[iType]));
+ }
+ }
+ }
+
+ // handling of root error messages
+ if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages")) {
+ Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
+ SetHandleRootMessages(on);
+ AliDebug(3, Form("handling of root messages %sabled",
+ ((on) ? "en" : "dis")));
+ }
+
+ // printout settings
+ static const char* settingNames[4] =
+ {"Type", "Module", "Scope", "Location"};
+ Bool_t* settings[] =
+ {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
+ for (Int_t iSetting = 0; iSetting < 4; iSetting++) {
+ TString name("AliRoot.AliLog.Print");
+ name += settingNames[iSetting];
+ if (gEnv->Defined(name)) {
+ Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ settings[iSetting][iType] = on;
+ }
+ AliDebug(3, Form("printing of %s %sabled for all types",
+ settingNames[iSetting], ((on) ? "en" : "dis")));
+ }
+
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ TString nameType = name + "." + &typeNames[iType][1];
+ if (gEnv->Defined(nameType)) {
+ Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
+ settings[iSetting][iType] = on;
+ AliDebug(3, Form("printing of %s %sabled for type %s",
+ settingNames[iSetting], ((on) ? "en" : "dis"),
+ typeNames[iType]));
+ }
+ }
+ }
+}
+
+
//_____________________________________________________________________________
void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
const char* location, const char* message)
fgInstance->fOutputTypes[iType] = 2;
fgInstance->fFileNames[iType] = fileName;
fgInstance->fOutputFiles[iType] = NULL;
+ fgInstance->fOutputStreams[iType] = NULL;
}
}
fgInstance->fOutputTypes[type] = 2;
fgInstance->fFileNames[type] = fileName;
fgInstance->fOutputFiles[type] = NULL;
+ fgInstance->fOutputStreams[type] = NULL;
}
//_____________________________________________________________________________
closeFile = kFALSE;
}
}
- if (closeFile) fclose(fOutputFiles[type]);
+ if (closeFile) {
+ fclose(fOutputFiles[type]);
+ fOutputStreams[type]->close();
+ delete fOutputStreams[type];
+ }
}
fOutputFiles[type] = NULL;
+ fOutputStreams[type] = NULL;
fFileNames[type] = "";
fOutputTypes[type] = 0;
}
{
// get the output stream for the given type of messages
+ if (type > kDebug) type = kDebug;
if (fOutputTypes[type] == 0) return stdout;
else if (fOutputTypes[type] == 1) return stderr;
else if (fOutputTypes[type] == 2) {
if (!fOutputFiles[type]) {
FILE* file = NULL;
+ ofstream* stream = NULL;
if (!fFileNames[type].IsNull()) {
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if ((iType != type) &&
(fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
fOutputFiles[iType]) {
file = fOutputFiles[iType];
+ stream = fOutputStreams[iType];
break;
}
}
- if (!file) file = fopen(fFileNames[type], "a");
+ if (!file) {
+ file = fopen(fFileNames[type], "a");
+ stream = new ofstream(fFileNames[type], ios::app);
+ }
}
fOutputFiles[type] = file;
+ fOutputStreams[type] = stream;
if (!file) CloseFile(type);
}
if (fOutputFiles[type]) return fOutputFiles[type];
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if (fgInstance->fOutputFiles[iType]) {
fflush(fgInstance->fOutputFiles[iType]);
+ fgInstance->fOutputStreams[iType]->flush();
}
}
fflush(stderr);
return fgInstance->GetLogLevel(module, className) - kDebugOffset;
}
+//_____________________________________________________________________________
+void AliLog::PrintMessage(UInt_t type, const char* message,
+ const char* module, const char* className,
+ const char* function, const char* file, Int_t line)
+{
+// print the given message
+
+ FILE* stream = GetOutputStream(type);
+ static const char* typeNames[kMaxType] =
+ {"Fatal", "Error", "Warning", "Info", "Debug"};
+
+ if (fPrintType[type]) {
+ fprintf(stream, "%s in ", typeNames[type]);
+ }
+ fprintf(stream, "<");
+ if (fPrintModule[type] && module) {
+ fprintf(stream, "%s/", module);
+ }
+ if (fPrintScope[type] && className) {
+ fprintf(stream, "%s::", className);
+ }
+ if (message) {
+ fprintf(stream, "%s>: %s", function, message);
+ } else {
+ fprintf(stream, "%s>", function);
+ }
+ if (fPrintLocation[type] && file) {
+ fprintf(stream, " (%s:%.0d)", file, line);
+ }
+ if (message) {
+ fprintf(stream, "\n");
+ } else {
+ fprintf(stream, ": ");
+ }
+}
+
//_____________________________________________________________________________
void AliLog::Message(UInt_t level, const char* message,
const char* module, const char* className,
if (!fgInstance) new AliLog;
// get the message type
- static const char* typeNames[kMaxType] =
- {"Fatal", "Error", "Warning", "Info", "Debug"};
UInt_t type = level;
if (type >= kMaxType) type = kMaxType - 1;
// print the message if the debug level allows
if (level <= fgInstance->GetLogLevel(module, className)) {
- if (fgInstance->fPrintType[type]) {
- fprintf(fgInstance->GetOutputStream(type), "%s in ", typeNames[type]);
- }
- fprintf(fgInstance->GetOutputStream(type), "<");
- if (fgInstance->fPrintModule[type] && module) {
- fprintf(fgInstance->GetOutputStream(type), "%s/", module);
- }
- if (fgInstance->fPrintScope[type] && className) {
- fprintf(fgInstance->GetOutputStream(type), "%s::", className);
- }
- fprintf(fgInstance->GetOutputStream(type), "%s>: %s", function, message);
- if (fgInstance->fPrintLocation[type] && file) {
- fprintf(fgInstance->GetOutputStream(type), " (%s:%.0d)", file, line);
- }
- fprintf(fgInstance->GetOutputStream(type), "\n");
+ fgInstance->PrintMessage(type, message,
+ module, className, function, file, line);
}
// abort in case of a fatal message
level += kDebugOffset;
Message(level, message, module, className, function, file, line);
}
+
+
+//_____________________________________________________________________________
+Int_t AliLog::RedirectStdoutTo(EType type, UInt_t level, const char* module,
+ const char* className, const char* function,
+ const char* file, Int_t line, Bool_t print)
+{
+// redirect the standard output to the stream of the given type
+
+ if (!fgInstance) new AliLog;
+ return fgInstance->RedirectTo(stdout, type, level, module, className,
+ function, file, line, print);
+}
+
+//_____________________________________________________________________________
+Int_t AliLog::RedirectStderrTo(EType type, UInt_t level, const char* module,
+ const char* className, const char* function,
+ const char* file, Int_t line, Bool_t print)
+{
+// redirect the standard error output to the stream of the given type
+
+ if (!fgInstance) new AliLog;
+ return fgInstance->RedirectTo(stderr, type, level, module, className,
+ function, file, line, print);
+}
+
+//_____________________________________________________________________________
+Int_t AliLog::RedirectTo(FILE* stream, EType type, UInt_t level,
+ const char* module, const char* className,
+ const char* function, const char* file, Int_t line,
+ Bool_t print)
+{
+// redirect the standard (error) output stream to the stream of the given type
+
+ // get the original file descriptor to be able to restore it later
+ Int_t original = dup(fileno(stream));
+ fflush(stream);
+
+ // flush the stream of the selected type
+ FILE* newStream = GetOutputStream(type);
+ fflush(newStream);
+
+ // redirect stream
+ if ((type == kDebug) && (level > 0)) level--;
+ if (type + level > GetLogLevel(module, className)) { // /dev/null
+ freopen("/dev/null", "a", stream);
+ } else if (fOutputTypes[type] == 0) { // stdout
+ if (stream != stdout) dup2(fileno(stdout), fileno(stream));
+ } else if (fOutputTypes[type] == 1) { // stderr
+ if (stream != stderr) dup2(fileno(stderr), fileno(stream));
+ } else if (fOutputTypes[type] == 2) { // file
+ freopen(fFileNames[type], "a", stream);
+ }
+
+ // print information
+ if (print) {
+ PrintMessage(type, NULL, module, className, function, file, line);
+ fflush(newStream);
+ }
+
+ return original;
+}
+
+//_____________________________________________________________________________
+void AliLog::RestoreStdout(Int_t original)
+{
+// restore the standard output
+
+ fflush(stdout);
+ dup2(original, fileno(stdout));
+}
+
+//_____________________________________________________________________________
+void AliLog::RestoreStderr(Int_t original)
+{
+// restore the standard error output
+
+ fflush(stderr);
+ dup2(original, fileno(stderr));
+}
+
+
+//_____________________________________________________________________________
+ostream& AliLog::Stream(EType type, UInt_t level,
+ const char* module, const char* className,
+ const char* function, const char* file, Int_t line)
+{
+// get the stream object for the given output type
+
+ if (!fgInstance) new AliLog;
+ return fgInstance->GetStream(type, level, module, className,
+ function, file, line);
+}
+
+//_____________________________________________________________________________
+ostream& AliLog::GetStream(EType type, UInt_t level,
+ const char* module, const char* className,
+ const char* function, const char* file, Int_t line)
+{
+// get the stream object for the given output type
+
+ if ((type == kDebug) && (level > 0)) level--;
+ Bool_t noOutput = (type + level > GetLogLevel(module, className));
+
+ if (!noOutput) {
+ PrintMessage(type, NULL, module, className, function, file, line);
+ }
+ fflush(GetOutputStream(type));
+
+ static ofstream nullStream("/dev/null");
+ if (noOutput) {
+ return nullStream;
+ } else if (fOutputTypes[type] == 0) {
+ return cout;
+ } else if (fOutputTypes[type] == 1) {
+ return cerr;
+ } else if (fOutputTypes[type] == 2) {
+ return *fOutputStreams[type];
+ }
+
+ return nullStream;
+}
+