1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 // class for logging debug, info and error messages //
22 // The AliLog class is a singleton class. It allows to steer the output //
23 // level and output streams for different types of messages via static //
26 // It also handles the messages produces by the preprocessor macros defined //
27 // in the header file: AliDebug, AliInfo, AliWarning, AliError, AliFatal. //
29 // More details about the message logging can be found on the ALICE Offline //
32 ///////////////////////////////////////////////////////////////////////////////
36 #include <Riostream.h>
42 #include <Varargs.h> // platform independent definition of va_copy
54 // implementation of a singleton here
55 AliLog* AliLog::fgInstance = NULL;
57 Bool_t AliLog::fgDebugEnabled = kTRUE;
58 Bool_t AliLog::fgCoreEnabled = kFALSE;
61 * get root logger singleton instance
63 AliLog *AliLog::GetRootLogger()
65 if (fgInstance == NULL)
68 fgInstance = new AliLog;
75 * delete the root logger singleton instance
77 void AliLog::DeleteRootLogger()
79 if (fgInstance != NULL)
87 * default private constructor
91 fGlobalLogLevel(kInfo),
94 fPrintRepetitions(kTRUE),
104 // default constructor: set default values
106 for (Int_t iType = kFatal; iType < kMaxType; iType++)
108 fOutputTypes[iType] = 0;
109 fFileNames[iType] = "";
110 fOutputFiles[iType] = NULL;
111 fOutputStreams[iType] = NULL;
112 fCallBacks[iType]=NULL;
114 fPrintType[iType] = kTRUE;
115 fPrintModule[iType] = kFALSE;
116 fPrintScope[iType] = kTRUE;
117 fPrintLocation[iType] = (iType == kDebug);
121 // replace the previous instance by this one
122 if (fgInstance) delete fgInstance;
125 SetHandleRootMessages(kTRUE);
127 // read the .rootrc settings
136 // destructor: clean up and reset instance pointer
138 if (fRepetitions > 0) PrintRepetitions();
140 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
142 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
145 fClassDebugLevels.Delete();
147 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
149 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
152 fClassDebugLevels.Delete();
154 for (Int_t iType = kFatal; iType < kMaxType; iType++)
166 //_____________________________________________________________________________
167 AliLog::AliLog(const AliLog& log) :
169 fGlobalLogLevel(log.fGlobalLogLevel),
170 fModuleDebugLevels(log.fModuleDebugLevels),
171 fClassDebugLevels(log.fClassDebugLevels),
172 fPrintRepetitions(log.fPrintRepetitions),
173 fRepetitions(log.fRepetitions),
174 fLastType(log.fLastType),
175 fLastMessage(log.fLastMessage),
176 fLastModule(log.fLastModule),
177 fLastClassName(log.fLastClassName),
178 fLastFunction(log.fLastFunction),
179 fLastFile(log.fLastFile),
180 fLastLine(log.fLastLine)
184 Fatal("AliLog", "copy constructor not implemented");
188 //_____________________________________________________________________________
189 AliLog& AliLog::operator = (const AliLog& /*log*/)
191 // assignment operator
193 Fatal("operator =", "assignment operator not implemented");
199 * gSystem see TSystem.h
202 * LOG_NO_DEBUG: fgDebugEnabled <- false
203 * AliRoot.AliLog.EnableDebug
204 * AliRoot.AliLog.GlobalLogLevel
206 //_____________________________________________________________________________
207 void AliLog::ReadEnvSettings()
209 // load settings from the root configuration file (.rootrc)
210 // and from environment variables
212 static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
214 // debug en- or disabling
215 if (gSystem->Getenv("LOG_NO_DEBUG"))
217 fgDebugEnabled = kFALSE;
219 else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
221 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
222 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
226 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
228 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
230 for (Int_t iType = kFatal; iType < kMaxType; iType++)
232 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
235 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
238 // global debug level
239 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
241 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
242 if (level < -kDebugOffset) level = kDebugOffset;
243 fGlobalLogLevel = kDebugOffset + level;
244 AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
247 // module debug level
248 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
250 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
251 char* p = const_cast<char*>(levels.Data());
253 while (const char* module = strtok(p, " "))
256 char* pos = const_cast<char*>(index(module, ':'));
259 Int_t level = atoi(pos);
260 SetModuleDebugLevel(module, level);
261 AliDebug(3, Form("debug level for module %s set to %d", module, level));
266 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
268 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
269 char* p = const_cast<char*>(levels.Data());
271 while (const char* className = strtok(p, " "))
274 char* pos = const_cast<char*>(index(className, ':'));
277 Int_t level = atoi(pos);
278 SetClassDebugLevel(className, level);
279 AliDebug(3, Form("debug level for class %s set to %d", className, level));
283 // general output stream
284 if (gEnv->Defined("AliRoot.AliLog.Output"))
286 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
288 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
291 AliDebug(3, "output stream set to standard output for all types");
293 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
296 AliDebug(3, "output stream set to error output for all types");
298 else if (!stream.IsNull())
300 SetFileOutput(stream);
301 AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
305 // individual output streams
306 for (Int_t iType = kFatal; iType < kMaxType; iType++)
308 TString name("AliRoot.AliLog.Output.");
309 name += &typeNames[iType][1];
311 if (gEnv->Defined(name))
313 TString stream = gEnv->GetValue(name, "Standard");
315 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
317 SetStandardOutput(EType_t(iType));
318 AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
320 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
322 SetErrorOutput(EType_t(iType));
323 AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
325 else if (!stream.IsNull())
327 SetFileOutput(EType_t(iType), stream);
328 AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
333 // handling of root error messages
334 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
336 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
337 SetHandleRootMessages(on);
338 AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
342 static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
343 Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
345 for (Int_t iSetting = 0; iSetting < 4; iSetting++)
347 TString name("AliRoot.AliLog.Print");
348 name += settingNames[iSetting];
350 if (gEnv->Defined(name))
352 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
354 for (Int_t iType = kFatal; iType < kMaxType; iType++)
356 settings[iSetting][iType] = on;
358 AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
361 for (Int_t iType = kFatal; iType < kMaxType; iType++)
363 TString nameType = name + "." + &typeNames[iType][1];
365 if (gEnv->Defined(nameType))
367 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
368 settings[iSetting][iType] = on;
369 AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
374 // repetition of messages
375 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
377 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
378 fPrintRepetitions = on;
379 AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
381 if (gSystem->Getenv("ALIROOT_FORCE_COREDUMP")){
382 EnableCoreDump(kTRUE);
388 //_____________________________________________________________________________
389 void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
390 const char* location, const char* message)
392 // new error handler for messages from root
396 case ::kFatal : level = kFatal; break;
398 DefaultErrorHandler(level, abort, location, message);
401 DefaultErrorHandler(level, abort, location, message);
403 case ::kError : level = kError; break;
404 case ::kWarning : level = kWarning; break;
405 case ::kInfo : level = kInfo; break;
406 default : level = kDebug; break;
408 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
412 // DEPRECATED: USE A CONFIGURATION FILE INSTEAD
413 //_____________________________________________________________________________
414 void AliLog::EnableDebug(Bool_t enabled)
416 // enable or disable debug output
418 fgDebugEnabled = enabled;
421 void AliLog::EnableCoreDump(Bool_t enabled)
423 // enable or disable debug output
425 fgCoreEnabled = enabled;
426 gSystem->ResetSignal(kSigFloatingException,enabled);
427 gSystem->ResetSignal(kSigSegmentationViolation,enabled);
434 //_____________________________________________________________________________
435 void AliLog::SetGlobalLogLevel(EType_t type)
437 // set the global debug level
440 if (!fgInstance) new AliLog;
441 fgInstance->fGlobalLogLevel = type;
444 //_____________________________________________________________________________
445 Int_t AliLog::GetGlobalLogLevel()
447 // get the global debug level
449 if (!fgInstance) new AliLog;
450 return fgInstance->fGlobalLogLevel;
453 //_____________________________________________________________________________
454 void AliLog::SetGlobalDebugLevel(Int_t level)
456 // set the global debug level
458 if (!fgInstance) new AliLog;
459 if (level < -kDebugOffset) level = -kDebugOffset;
460 fgInstance->fGlobalLogLevel = kDebugOffset + level;
463 //_____________________________________________________________________________
464 Int_t AliLog::GetGlobalDebugLevel()
466 // get the global debug level
468 if (!fgInstance) new AliLog;
469 return fgInstance->fGlobalLogLevel - kDebugOffset;
472 //_____________________________________________________________________________
473 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
475 // set the debug level for the given module
478 if (!fgInstance) new AliLog;
479 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
481 obj = new TNamed(module, module);
482 fgInstance->fModuleDebugLevels.Add(obj);
484 level += kDebugOffset;
485 if (level < kFatal) level = kFatal;
486 obj->SetUniqueID(level);
489 //_____________________________________________________________________________
490 void AliLog::ClearModuleDebugLevel(const char* module)
492 // remove the setting of the debug level for the given module
495 if (!fgInstance) new AliLog;
496 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
497 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
500 //_____________________________________________________________________________
501 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
503 // set the debug level for the given class
505 if (!className) return;
506 if (!fgInstance) new AliLog;
507 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
509 obj = new TNamed(className, className);
510 fgInstance->fClassDebugLevels.Add(obj);
512 level += kDebugOffset;
513 if (level < kFatal) level = kFatal;
514 obj->SetUniqueID(level);
517 //_____________________________________________________________________________
518 void AliLog::ClearClassDebugLevel(const char* className)
520 // remove the setting of the debug level for the given class
522 if (!className) return;
523 if (!fgInstance) new AliLog;
524 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
525 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
529 //_____________________________________________________________________________
530 void AliLog::SetStandardOutput()
532 // write all log messages to the standard output (stdout)
534 if (!fgInstance) new AliLog;
535 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
536 fgInstance->CloseFile(iType);
537 fgInstance->fOutputTypes[iType] = 0;
541 //_____________________________________________________________________________
542 void AliLog::SetStandardOutput(EType_t type)
544 // write log messages of the given type to the standard output (stdout)
546 if ((type < kFatal) || (type >= kMaxType)) return;
547 if (!fgInstance) new AliLog;
548 fgInstance->CloseFile(type);
549 fgInstance->fOutputTypes[type] = 0;
552 //_____________________________________________________________________________
553 void AliLog::SetErrorOutput()
555 // write all log messages to the error output (stderr)
557 if (!fgInstance) new AliLog;
558 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
559 fgInstance->CloseFile(iType);
560 fgInstance->fOutputTypes[iType] = 1;
564 //_____________________________________________________________________________
565 void AliLog::SetErrorOutput(EType_t type)
567 // write log messages of the given type to the error output (stderr)
569 if ((type < kFatal) || (type >= kMaxType)) return;
570 if (!fgInstance) new AliLog;
571 fgInstance->CloseFile(type);
572 fgInstance->fOutputTypes[type] = 1;
575 //_____________________________________________________________________________
576 void AliLog::SetFileOutput(const char* fileName)
578 // write all log messages to the given file
580 if (!fgInstance) new AliLog;
581 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
582 if ((fgInstance->fOutputTypes[iType] == 2) &&
583 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
584 fgInstance->CloseFile(iType);
586 fgInstance->fOutputTypes[iType] = 2;
587 fgInstance->fFileNames[iType] = fileName;
588 fgInstance->fOutputFiles[iType] = NULL;
589 fgInstance->fOutputStreams[iType] = NULL;
593 //_____________________________________________________________________________
594 void AliLog::SetFileOutput(EType_t type, const char* fileName)
596 // write log messages of the given type to the given file
598 if ((type < kFatal) || (type >= kMaxType)) return;
599 if (!fgInstance) new AliLog;
600 if ((fgInstance->fOutputTypes[type] == 2) &&
601 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
602 fgInstance->CloseFile(type);
604 fgInstance->fOutputTypes[type] = 2;
605 fgInstance->fFileNames[type] = fileName;
606 fgInstance->fOutputFiles[type] = NULL;
607 fgInstance->fOutputStreams[type] = NULL;
610 //_____________________________________________________________________________
611 void AliLog::CloseFile(Int_t type)
613 // close the file for the given type if needed
615 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
616 Bool_t closeFile = kTRUE;
617 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
618 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
623 fclose(fOutputFiles[type]);
624 ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
626 delete fOutputStreams[type];
629 fOutputFiles[type] = NULL;
630 fOutputStreams[type] = NULL;
631 fFileNames[type] = "";
632 fOutputTypes[type] = 0;
635 //_____________________________________________________________________________
636 FILE* AliLog::GetOutputStream(Int_t type)
638 // get the output stream for the given type of messages
640 if (type > kDebug) type = kDebug;
641 if (fOutputTypes[type] == 0) return stdout;
642 else if (fOutputTypes[type] == 1) return stderr;
643 else if (fOutputTypes[type] == 2) {
644 if (!fOutputFiles[type]) {
646 ostream* stream = NULL;
647 if (!fFileNames[type].IsNull()) {
648 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
649 if ((iType != type) &&
650 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
651 fOutputFiles[iType]) {
652 file = fOutputFiles[iType];
653 stream = fOutputStreams[iType];
658 file = fopen(fFileNames[type], "a");
659 stream = new ofstream(fFileNames[type], ios::app);
662 fOutputFiles[type] = file;
663 fOutputStreams[type] = stream;
664 if (!file) CloseFile(type);
666 if (fOutputFiles[type]) return fOutputFiles[type];
672 //_____________________________________________________________________________
675 // flush the output streams
677 if (!fgInstance) new AliLog;
678 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
679 if (fgInstance->fOutputFiles[iType]) {
680 fflush(fgInstance->fOutputFiles[iType]);
681 fgInstance->fOutputStreams[iType]->flush();
689 //_____________________________________________________________________________
690 void AliLog::SetHandleRootMessages(Bool_t on)
692 // enable or disable the handling of messages form root
694 if (!fgInstance) new AliLog;
696 SetErrorHandler(RootErrorHandler);
698 SetErrorHandler(DefaultErrorHandler);
703 //_____________________________________________________________________________
704 void AliLog::SetPrintType(Bool_t on)
706 // switch on or off the printing of the message type for all message types
708 if (!fgInstance) new AliLog;
709 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
710 fgInstance->fPrintType[iType] = on;
714 //_____________________________________________________________________________
715 void AliLog::SetPrintType(EType_t type, Bool_t on)
717 // switch on or off the printing of the message type for the given message type
719 if ((type < kFatal) || (type >= kMaxType)) return;
720 if (!fgInstance) new AliLog;
721 fgInstance->fPrintType[type] = on;
724 //_____________________________________________________________________________
725 void AliLog::SetPrintModule(Bool_t on)
727 // switch on or off the printing of the module for all message types
729 if (!fgInstance) new AliLog;
730 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
731 fgInstance->fPrintModule[iType] = on;
735 //_____________________________________________________________________________
736 void AliLog::SetPrintModule(EType_t type, Bool_t on)
738 // switch on or off the printing of the module for the given message type
740 if ((type < kFatal) || (type >= kMaxType)) return;
741 if (!fgInstance) new AliLog;
742 fgInstance->fPrintModule[type] = on;
745 //_____________________________________________________________________________
746 void AliLog::SetPrintScope(Bool_t on)
748 // switch on or off the printing of the scope/class name for all message types
750 if (!fgInstance) new AliLog;
751 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
752 fgInstance->fPrintScope[iType] = on;
756 //_____________________________________________________________________________
757 void AliLog::SetPrintScope(EType_t type, Bool_t on)
759 // switch on or off the printing of the scope/class name
760 // for the given message type
762 if ((type < kFatal) || (type >= kMaxType)) return;
763 if (!fgInstance) new AliLog;
764 fgInstance->fPrintScope[type] = on;
767 //_____________________________________________________________________________
768 void AliLog::SetPrintLocation(Bool_t on)
770 // switch on or off the printing of the file name and line number
771 // for all message types
773 if (!fgInstance) new AliLog;
774 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
775 fgInstance->fPrintLocation[iType] = on;
779 //_____________________________________________________________________________
780 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
782 // switch on or off the printing of the file name and line number
783 // for the given message type
785 if ((type < kFatal) || (type >= kMaxType)) return;
786 if (!fgInstance) new AliLog;
787 fgInstance->fPrintLocation[type] = on;
791 //_____________________________________________________________________________
792 void AliLog::SetPrintRepetitions(Bool_t on)
794 // switch on or off the printing of the number of repetitions of a message
795 // instead of repeating the same message
797 if (!fgInstance) new AliLog;
798 if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
799 fgInstance->fPrintRepetitions = on;
803 //_____________________________________________________________________________
804 void AliLog::WriteToFile(const char* name, Int_t option)
806 // write the log object with the given name and option to the current file
808 if (!fgInstance) new AliLog;
809 fgInstance->TObject::Write(name, option);
813 //_____________________________________________________________________________
814 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
816 // get the logging level for the given module and class
818 if (!fgInstance) new AliLog;
820 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
821 if (obj) return obj->GetUniqueID();
824 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
825 if (obj) return obj->GetUniqueID();
827 return fgInstance->fGlobalLogLevel;
830 //_____________________________________________________________________________
831 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
833 // get the debug level for the given module and class
835 if (!fgInstance) new AliLog;
836 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
839 //_____________________________________________________________________________
840 void AliLog::PrintMessage(UInt_t type, const char* message,
841 const char* module, const char* className,
842 const char* function, const char* file, Int_t line)
844 // print the given message
846 // don't print the message if it is repeated
847 if (fPrintRepetitions &&
848 (fLastType == type) &&
849 (message && (fLastMessage.CompareTo(message) == 0)) &&
850 ((module && (fLastModule.CompareTo(module) == 0)) ||
851 (!module && fLastModule.IsNull())) &&
852 ((className && (fLastClassName.CompareTo(className) == 0)) ||
853 (!className && fLastClassName.IsNull())) &&
854 ((function && (fLastFunction.CompareTo(function) == 0)) ||
855 (!function && fLastFunction.IsNull()))&&
856 ((file && (fLastFile.CompareTo(file) == 0)) ||
857 (!file && fLastFile.IsNull())) &&
858 (fLastLine == line)) {
863 // print number of repetitions
864 if (fRepetitions > 0) PrintRepetitions();
866 // remember this message
869 fLastMessage = message;
870 fLastModule = module;
871 fLastClassName = className;
872 fLastFunction = function;
877 FILE* stream = GetOutputStream(type);
878 static const char* typeNames[kMaxType] =
879 {"Fatal", "Error", "Warning", "Info", "Debug"};
881 if (fPrintType[type]) {
882 PrintString(type, stream, "%c-", typeNames[type][0]);
884 if (fPrintModule[type] && module) {
885 PrintString(type, stream, "%s/", module);
887 if (fPrintScope[type] && className) {
888 PrintString(type, stream, "%s::", className);
891 PrintString(type, stream, "%s: %s", function, message);
893 PrintString(type, stream, "%s", function);
895 if (fPrintLocation[type] && file) {
896 PrintString(type, stream, " (%s:%.0d)", file, line);
899 PrintString(type, stream, "\n");
901 PrintString(type, stream, ": ");
903 if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
906 //_____________________________________________________________________________
907 void AliLog::PrintRepetitions()
909 // print number of repetitions
911 PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
912 fRepetitions, (fRepetitions > 1) ? "s" : "");
913 if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
916 //_____________________________________________________________________________
917 void AliLog::Message(UInt_t level, const char* message,
918 const char* module, const char* className,
919 const char* function, const char* file, Int_t line)
921 // print a log message
923 if (!fgInstance) new AliLog;
925 // get the message type
927 if (type >= kMaxType) type = kMaxType - 1;
929 // print the message if the debug level allows
930 if (level <= fgInstance->GetLogLevel(module, className)) {
931 fgInstance->PrintMessage(type, message,
932 module, className, function, file, line);
935 // abort in case of a fatal message
936 if (type == kFatal) {
939 gSystem->StackTrace();
940 if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
943 if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
951 //_____________________________________________________________________________
952 void AliLog::Debug(UInt_t level, const char* message,
953 const char* module, const char* className,
954 const char* function, const char* file, Int_t line)
956 // print a debug message
958 if (level == 0) level = 1;
959 level += kDebugOffset;
960 Message(level, message, module, className, function, file, line);
964 //_____________________________________________________________________________
965 Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
966 const char* className, const char* function,
967 const char* file, Int_t line, Bool_t print)
969 // redirect the standard output to the stream of the given type
971 if (!fgInstance) new AliLog;
972 return fgInstance->RedirectTo(stdout, type, level, module, className,
973 function, file, line, print);
976 //_____________________________________________________________________________
977 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
978 const char* className, const char* function,
979 const char* file, Int_t line, Bool_t print)
981 // redirect the standard error output to the stream of the given type
983 if (!fgInstance) new AliLog;
984 return fgInstance->RedirectTo(stderr, type, level, module, className,
985 function, file, line, print);
988 //_____________________________________________________________________________
989 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
990 const char* module, const char* className,
991 const char* function, const char* file, Int_t line,
994 // redirect the standard (error) output stream to the stream of the given type
996 // get the original file descriptor to be able to restore it later
997 Int_t original = dup(fileno(stream));
1000 // flush the stream of the selected type
1001 FILE* newStream = GetOutputStream(type);
1005 if ((type == kDebug) && (level > 0)) level--;
1006 if (type + level > GetLogLevel(module, className)) { // /dev/null
1007 if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
1008 } else if (fOutputTypes[type] == 0) { // stdout
1009 if (stream != stdout) dup2(fileno(stdout), fileno(stream));
1010 } else if (fOutputTypes[type] == 1) { // stderr
1011 if (stream != stderr) dup2(fileno(stderr), fileno(stream));
1012 } else if (fOutputTypes[type] == 2) { // file
1013 if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
1014 } else if (fOutputTypes[type] == 3) { // external C++ stream
1015 // redirection is not possible for external C++ streams
1018 // print information
1020 PrintMessage(type, NULL, module, className, function, file, line);
1027 //_____________________________________________________________________________
1028 void AliLog::RestoreStdout(Int_t original)
1030 // restore the standard output
1033 dup2(original, fileno(stdout));
1037 //_____________________________________________________________________________
1038 void AliLog::RestoreStderr(Int_t original)
1040 // restore the standard error output
1043 dup2(original, fileno(stderr));
1048 //_____________________________________________________________________________
1049 ostream& AliLog::Stream(EType_t type, UInt_t level,
1050 const char* module, const char* className,
1051 const char* function, const char* file, Int_t line)
1053 // get the stream object for the given output type
1055 if (!fgInstance) new AliLog;
1056 return fgInstance->GetStream(type, level, module, className,
1057 function, file, line);
1060 //_____________________________________________________________________________
1061 ostream& AliLog::GetStream(EType_t type, UInt_t level,
1062 const char* module, const char* className,
1063 const char* function, const char* file, Int_t line)
1065 // get the stream object for the given output type
1067 if ((type == kDebug) && (level > 0)) level--;
1068 Bool_t noOutput = (type + level > GetLogLevel(module, className));
1071 PrintMessage(type, NULL, module, className, function, file, line);
1073 fflush(GetOutputStream(type));
1075 static ofstream nullStream("/dev/null");
1078 } else if (fOutputTypes[type] == 0) {
1080 } else if (fOutputTypes[type] == 1) {
1082 } else if (fOutputTypes[type] == 2) {
1083 return *fOutputStreams[type];
1084 } else if (fOutputTypes[type] == 3) {
1085 return *fOutputStreams[type];
1091 void AliLog::SetStreamOutput(ostream* stream)
1093 // set an external stream as target for log messages of all types
1094 // the external stream is completely handled by the caller, the
1095 // AliLog class just writes to it
1097 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1098 SetStreamOutput((AliLog::EType_t)iType, stream);
1102 void AliLog::SetStreamOutput(EType_t type, ostream* stream)
1104 // set an external stream as target for log messages of the given type
1105 // the external stream is completely handled by the caller, the
1106 // AliLog class just writes to it
1108 if ((type < kFatal) || (type >= kMaxType)) return;
1109 if (!fgInstance) new AliLog;
1110 if (fgInstance->fOutputTypes[type] == 2) {
1111 fgInstance->CloseFile(type);
1113 fgInstance->fOutputTypes[type] = 3;
1114 fgInstance->fFileNames[type] = "";
1115 fgInstance->fOutputFiles[type] = NULL;
1116 fgInstance->fOutputStreams[type] = stream;
1119 void AliLog::SetLogNotification(AliLogNotification pCallBack)
1121 // set a notification callback function for log messages of all types
1123 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1124 SetLogNotification((AliLog::EType_t)iType, pCallBack);
1128 void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
1130 // set a notifications call back function for log messages of all types
1131 // the callback fuction is invoced whenever an output was written
1132 // Note: does not work for c++ streamer classes, the external stream
1133 // has to handle this diectly (e.g. custom implementation of endl)
1135 if ((type < kFatal) || (type >= kMaxType)) return;
1136 if (!fgInstance) new AliLog;
1137 fgInstance->fCallBacks[type]=pCallBack;
1140 void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1142 // this is the general method to print a log message using variadac args
1143 // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1145 // Only in case of an external c++ ostream type output, the message is
1146 // written to that stream and the notifictaion callback is called.
1147 // The message is printed by a normal vfprintf function otherwise
1149 if (format==NULL) return;
1152 va_start(ap, format);
1153 if (fOutputTypes[type] != 3) {
1155 vfprintf(stream, format, ap);
1158 // build the string and write everthing to the corresponding ostream
1159 TString fmt(format);
1160 TArrayC tgt(fmt.Length()*10); // just take a number
1163 R__VA_COPY(bap, ap);
1165 #warning definition of R__VA_COPY has disappeared
1170 iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1172 iResult=tgt.GetSize()*2;
1173 } else if (iResult<tgt.GetSize()) {
1177 if (iResult<10000) {
1180 R__VA_COPY(ap, bap);
1184 tgt[tgt.GetSize()-1]=0;
1192 if (fOutputStreams[type]) {
1193 *(fOutputStreams[type]) << tgt.GetArray();
1200 void AliLog::MakeCoreDump(const char *fout){
1202 // Functionality to make a program snapshot
1203 // gcore - Generate a core file for a running process
1204 // gcore dmake a current snapshot, program can continue further
1205 // We assum that gcore is installed
1206 // for details see: man gcore
1208 // Example use - make default core file for current process: AliLog::MakeCoreDump(0)
1211 // Automatic core dump creation in case of the AliFatal can be specified using
1212 // static void EnableCoreDump(Bool_t enabled);
1213 // Core dump is created in addition to the stack trace ()
1214 // marian.ivanov@cern.ch
1216 if (!gSystem) return;
1217 printf("AliLog::MakeCoreDump\n");
1219 gSystem->Exec(Form("gcore -o %s %d",fout, gSystem->GetPid()));
1221 gSystem->Exec(Form("gcore %d", gSystem->GetPid()));