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
62 // implementation of a singleton here
63 AliLog* AliLog::fgInstance = NULL;
65 Bool_t AliLog::fgDebugEnabled = kTRUE;
66 Bool_t AliLog::fgCoreEnabled = kFALSE;
69 * get root logger singleton instance
71 AliLog *AliLog::GetRootLogger()
73 if (fgInstance == NULL)
76 fgInstance = new AliLog;
83 * delete the root logger singleton instance
85 void AliLog::DeleteRootLogger()
87 if (fgInstance != NULL)
95 * default private constructor
99 fGlobalLogLevel(kInfo),
100 fModuleDebugLevels(),
102 fPrintRepetitions(kTRUE),
112 // default constructor: set default values
114 for (Int_t iType = kFatal; iType < kMaxType; iType++)
116 fOutputTypes[iType] = 0;
117 fFileNames[iType] = "";
118 fOutputFiles[iType] = NULL;
119 fOutputStreams[iType] = NULL;
120 fCallBacks[iType]=NULL;
122 fPrintType[iType] = kTRUE;
123 fPrintModule[iType] = kFALSE;
124 fPrintScope[iType] = kTRUE;
125 fPrintLocation[iType] = (iType == kDebug);
129 // replace the previous instance by this one
130 if (fgInstance) delete fgInstance;
133 SetHandleRootMessages(kTRUE);
135 // read the .rootrc settings
144 // destructor: clean up and reset instance pointer
146 if (fRepetitions > 0) PrintRepetitions();
148 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
150 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
153 fClassDebugLevels.Delete();
155 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
157 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
160 fClassDebugLevels.Delete();
162 for (Int_t iType = kFatal; iType < kMaxType; iType++)
174 //_____________________________________________________________________________
175 AliLog::AliLog(const AliLog& log) :
177 fGlobalLogLevel(log.fGlobalLogLevel),
178 fModuleDebugLevels(log.fModuleDebugLevels),
179 fClassDebugLevels(log.fClassDebugLevels),
180 fPrintRepetitions(log.fPrintRepetitions),
181 fRepetitions(log.fRepetitions),
182 fLastType(log.fLastType),
183 fLastMessage(log.fLastMessage),
184 fLastModule(log.fLastModule),
185 fLastClassName(log.fLastClassName),
186 fLastFunction(log.fLastFunction),
187 fLastFile(log.fLastFile),
188 fLastLine(log.fLastLine)
192 Fatal("AliLog", "copy constructor not implemented");
196 //_____________________________________________________________________________
197 AliLog& AliLog::operator = (const AliLog& /*log*/)
199 // assignment operator
201 Fatal("operator =", "assignment operator not implemented");
207 * gSystem see TSystem.h
210 * LOG_NO_DEBUG: fgDebugEnabled <- false
211 * AliRoot.AliLog.EnableDebug
212 * AliRoot.AliLog.GlobalLogLevel
214 //_____________________________________________________________________________
215 void AliLog::ReadEnvSettings()
217 // load settings from the root configuration file (.rootrc)
218 // and from environment variables
220 static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
222 // debug en- or disabling
223 if (gSystem->Getenv("LOG_NO_DEBUG"))
225 fgDebugEnabled = kFALSE;
227 else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
229 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
230 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
234 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
236 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
238 for (Int_t iType = kFatal; iType < kMaxType; iType++)
240 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
243 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
246 // global debug level
247 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
249 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
250 if (level < -kDebugOffset) level = kDebugOffset;
251 fGlobalLogLevel = kDebugOffset + level;
252 AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
255 // module debug level
256 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
258 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
259 char* p = const_cast<char*>(levels.Data());
261 while (const char* module = strtok(p, " "))
264 char* pos = const_cast<char*>(index(module, ':'));
267 Int_t level = atoi(pos);
268 SetModuleDebugLevel(module, level);
269 AliDebug(3, Form("debug level for module %s set to %d", module, level));
274 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
276 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
277 char* p = const_cast<char*>(levels.Data());
279 while (const char* className = strtok(p, " "))
282 char* pos = const_cast<char*>(index(className, ':'));
285 Int_t level = atoi(pos);
286 SetClassDebugLevel(className, level);
287 AliDebug(3, Form("debug level for class %s set to %d", className, level));
291 // general output stream
292 if (gEnv->Defined("AliRoot.AliLog.Output"))
294 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
296 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
299 AliDebug(3, "output stream set to standard output for all types");
301 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
304 AliDebug(3, "output stream set to error output for all types");
306 else if (!stream.IsNull())
308 SetFileOutput(stream);
309 AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
313 // individual output streams
314 for (Int_t iType = kFatal; iType < kMaxType; iType++)
316 TString name("AliRoot.AliLog.Output.");
317 name += &typeNames[iType][1];
319 if (gEnv->Defined(name))
321 TString stream = gEnv->GetValue(name, "Standard");
323 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
325 SetStandardOutput(EType_t(iType));
326 AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
328 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
330 SetErrorOutput(EType_t(iType));
331 AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
333 else if (!stream.IsNull())
335 SetFileOutput(EType_t(iType), stream);
336 AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
341 // handling of root error messages
342 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
344 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
345 SetHandleRootMessages(on);
346 AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
350 static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
351 Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
353 for (Int_t iSetting = 0; iSetting < 4; iSetting++)
355 TString name("AliRoot.AliLog.Print");
356 name += settingNames[iSetting];
358 if (gEnv->Defined(name))
360 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
362 for (Int_t iType = kFatal; iType < kMaxType; iType++)
364 settings[iSetting][iType] = on;
366 AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
369 for (Int_t iType = kFatal; iType < kMaxType; iType++)
371 TString nameType = name + "." + &typeNames[iType][1];
373 if (gEnv->Defined(nameType))
375 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
376 settings[iSetting][iType] = on;
377 AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
382 // repetition of messages
383 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
385 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
386 fPrintRepetitions = on;
387 AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
389 if (gSystem->Getenv("ALIROOT_FORCE_COREDUMP")){
390 EnableCoreDump(kTRUE);
396 //_____________________________________________________________________________
397 void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
398 const char* location, const char* message)
400 // new error handler for messages from root
404 case ::kFatal : level = kFatal; break;
406 DefaultErrorHandler(level, abort, location, message);
409 DefaultErrorHandler(level, abort, location, message);
411 case ::kError : level = kError; break;
412 case ::kWarning : level = kWarning; break;
413 case ::kInfo : level = kInfo; break;
414 default : level = kDebug; break;
416 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
420 // DEPRECATED: USE A CONFIGURATION FILE INSTEAD
421 //_____________________________________________________________________________
422 void AliLog::EnableDebug(Bool_t enabled)
424 // enable or disable debug output
426 fgDebugEnabled = enabled;
429 void AliLog::EnableCoreDump(Bool_t enabled)
431 // enable or disable debug output
432 gSystem->Exec("ulimit -c unlimited");
433 fgCoreEnabled = enabled;
434 gSystem->ResetSignal(kSigFloatingException,enabled);
435 gSystem->ResetSignal(kSigSegmentationViolation,enabled);
437 printf("Core dump enabled\n");
440 printf("Core dump disabled\n");
446 //_____________________________________________________________________________
447 void AliLog::SetGlobalLogLevel(EType_t type)
449 // set the global debug level
452 if (!fgInstance) new AliLog;
453 fgInstance->fGlobalLogLevel = type;
456 //_____________________________________________________________________________
457 Int_t AliLog::GetGlobalLogLevel()
459 // get the global debug level
461 if (!fgInstance) new AliLog;
462 return fgInstance->fGlobalLogLevel;
465 //_____________________________________________________________________________
466 void AliLog::SetGlobalDebugLevel(Int_t level)
468 // set the global debug level
470 if (!fgInstance) new AliLog;
471 if (level < -kDebugOffset) level = -kDebugOffset;
472 fgInstance->fGlobalLogLevel = kDebugOffset + level;
475 //_____________________________________________________________________________
476 Int_t AliLog::GetGlobalDebugLevel()
478 // get the global debug level
480 if (!fgInstance) new AliLog;
481 return fgInstance->fGlobalLogLevel - kDebugOffset;
484 //_____________________________________________________________________________
485 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
487 // set the debug level for the given module
490 if (!fgInstance) new AliLog;
491 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
493 obj = new TNamed(module, module);
494 fgInstance->fModuleDebugLevels.Add(obj);
496 level += kDebugOffset;
497 if (level < kFatal) level = kFatal;
498 obj->SetUniqueID(level);
501 //_____________________________________________________________________________
502 void AliLog::ClearModuleDebugLevel(const char* module)
504 // remove the setting of the debug level for the given module
507 if (!fgInstance) new AliLog;
508 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
509 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
512 //_____________________________________________________________________________
513 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
515 // set the debug level for the given class
517 if (!className) return;
518 if (!fgInstance) new AliLog;
519 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
521 obj = new TNamed(className, className);
522 fgInstance->fClassDebugLevels.Add(obj);
524 level += kDebugOffset;
525 if (level < kFatal) level = kFatal;
526 obj->SetUniqueID(level);
529 //_____________________________________________________________________________
530 void AliLog::ClearClassDebugLevel(const char* className)
532 // remove the setting of the debug level for the given class
534 if (!className) return;
535 if (!fgInstance) new AliLog;
536 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
537 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
541 //_____________________________________________________________________________
542 void AliLog::SetStandardOutput()
544 // write all log messages to the standard output (stdout)
546 if (!fgInstance) new AliLog;
547 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
548 fgInstance->CloseFile(iType);
549 fgInstance->fOutputTypes[iType] = 0;
553 //_____________________________________________________________________________
554 void AliLog::SetStandardOutput(EType_t type)
556 // write log messages of the given type to the standard output (stdout)
558 if ((type < kFatal) || (type >= kMaxType)) return;
559 if (!fgInstance) new AliLog;
560 fgInstance->CloseFile(type);
561 fgInstance->fOutputTypes[type] = 0;
564 //_____________________________________________________________________________
565 void AliLog::SetErrorOutput()
567 // write all log messages to the error output (stderr)
569 if (!fgInstance) new AliLog;
570 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
571 fgInstance->CloseFile(iType);
572 fgInstance->fOutputTypes[iType] = 1;
576 //_____________________________________________________________________________
577 void AliLog::SetErrorOutput(EType_t type)
579 // write log messages of the given type to the error output (stderr)
581 if ((type < kFatal) || (type >= kMaxType)) return;
582 if (!fgInstance) new AliLog;
583 fgInstance->CloseFile(type);
584 fgInstance->fOutputTypes[type] = 1;
587 //_____________________________________________________________________________
588 void AliLog::SetFileOutput(const char* fileName)
590 // write all log messages to the given file
592 if (!fgInstance) new AliLog;
593 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
594 if ((fgInstance->fOutputTypes[iType] == 2) &&
595 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
596 fgInstance->CloseFile(iType);
598 fgInstance->fOutputTypes[iType] = 2;
599 fgInstance->fFileNames[iType] = fileName;
600 fgInstance->fOutputFiles[iType] = NULL;
601 fgInstance->fOutputStreams[iType] = NULL;
605 //_____________________________________________________________________________
606 void AliLog::SetFileOutput(EType_t type, const char* fileName)
608 // write log messages of the given type to the given file
610 if ((type < kFatal) || (type >= kMaxType)) return;
611 if (!fgInstance) new AliLog;
612 if ((fgInstance->fOutputTypes[type] == 2) &&
613 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
614 fgInstance->CloseFile(type);
616 fgInstance->fOutputTypes[type] = 2;
617 fgInstance->fFileNames[type] = fileName;
618 fgInstance->fOutputFiles[type] = NULL;
619 fgInstance->fOutputStreams[type] = NULL;
622 //_____________________________________________________________________________
623 void AliLog::CloseFile(Int_t type)
625 // close the file for the given type if needed
627 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
628 Bool_t closeFile = kTRUE;
629 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
630 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
635 fclose(fOutputFiles[type]);
636 ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
638 delete fOutputStreams[type];
641 fOutputFiles[type] = NULL;
642 fOutputStreams[type] = NULL;
643 fFileNames[type] = "";
644 fOutputTypes[type] = 0;
647 //_____________________________________________________________________________
648 FILE* AliLog::GetOutputStream(Int_t type)
650 // get the output stream for the given type of messages
652 if (type > kDebug) type = kDebug;
653 if (fOutputTypes[type] == 0) return stdout;
654 else if (fOutputTypes[type] == 1) return stderr;
655 else if (fOutputTypes[type] == 2) {
656 if (!fOutputFiles[type]) {
658 ostream* stream = NULL;
659 if (!fFileNames[type].IsNull()) {
660 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
661 if ((iType != type) &&
662 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
663 fOutputFiles[iType]) {
664 file = fOutputFiles[iType];
665 stream = fOutputStreams[iType];
670 file = fopen(fFileNames[type], "a");
671 stream = new ofstream(fFileNames[type], ios::app);
674 fOutputFiles[type] = file;
675 fOutputStreams[type] = stream;
676 if (!file) CloseFile(type);
678 if (fOutputFiles[type]) return fOutputFiles[type];
684 //_____________________________________________________________________________
687 // flush the output streams
689 if (!fgInstance) new AliLog;
690 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
691 if (fgInstance->fOutputFiles[iType]) {
692 fflush(fgInstance->fOutputFiles[iType]);
693 fgInstance->fOutputStreams[iType]->flush();
701 //_____________________________________________________________________________
702 void AliLog::SetHandleRootMessages(Bool_t on)
704 // enable or disable the handling of messages form root
706 if (!fgInstance) new AliLog;
708 SetErrorHandler(RootErrorHandler);
710 SetErrorHandler(DefaultErrorHandler);
715 //_____________________________________________________________________________
716 void AliLog::SetPrintType(Bool_t on)
718 // switch on or off the printing of the message type for all message types
720 if (!fgInstance) new AliLog;
721 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
722 fgInstance->fPrintType[iType] = on;
726 //_____________________________________________________________________________
727 void AliLog::SetPrintType(EType_t type, Bool_t on)
729 // switch on or off the printing of the message type for the given message type
731 if ((type < kFatal) || (type >= kMaxType)) return;
732 if (!fgInstance) new AliLog;
733 fgInstance->fPrintType[type] = on;
736 //_____________________________________________________________________________
737 void AliLog::SetPrintModule(Bool_t on)
739 // switch on or off the printing of the module for all message types
741 if (!fgInstance) new AliLog;
742 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
743 fgInstance->fPrintModule[iType] = on;
747 //_____________________________________________________________________________
748 void AliLog::SetPrintModule(EType_t type, Bool_t on)
750 // switch on or off the printing of the module for the given message type
752 if ((type < kFatal) || (type >= kMaxType)) return;
753 if (!fgInstance) new AliLog;
754 fgInstance->fPrintModule[type] = on;
757 //_____________________________________________________________________________
758 void AliLog::SetPrintScope(Bool_t on)
760 // switch on or off the printing of the scope/class name for all message types
762 if (!fgInstance) new AliLog;
763 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
764 fgInstance->fPrintScope[iType] = on;
768 //_____________________________________________________________________________
769 void AliLog::SetPrintScope(EType_t type, Bool_t on)
771 // switch on or off the printing of the scope/class name
772 // for the given message type
774 if ((type < kFatal) || (type >= kMaxType)) return;
775 if (!fgInstance) new AliLog;
776 fgInstance->fPrintScope[type] = on;
779 //_____________________________________________________________________________
780 void AliLog::SetPrintLocation(Bool_t on)
782 // switch on or off the printing of the file name and line number
783 // for all message types
785 if (!fgInstance) new AliLog;
786 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
787 fgInstance->fPrintLocation[iType] = on;
791 //_____________________________________________________________________________
792 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
794 // switch on or off the printing of the file name and line number
795 // for the given message type
797 if ((type < kFatal) || (type >= kMaxType)) return;
798 if (!fgInstance) new AliLog;
799 fgInstance->fPrintLocation[type] = on;
803 //_____________________________________________________________________________
804 void AliLog::SetPrintRepetitions(Bool_t on)
806 // switch on or off the printing of the number of repetitions of a message
807 // instead of repeating the same message
809 if (!fgInstance) new AliLog;
810 if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
811 fgInstance->fPrintRepetitions = on;
815 //_____________________________________________________________________________
816 void AliLog::WriteToFile(const char* name, Int_t option)
818 // write the log object with the given name and option to the current file
820 if (!fgInstance) new AliLog;
821 fgInstance->TObject::Write(name, option);
825 //_____________________________________________________________________________
826 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
828 // get the logging level for the given module and class
830 if (!fgInstance) new AliLog;
832 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
833 if (obj) return obj->GetUniqueID();
836 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
837 if (obj) return obj->GetUniqueID();
839 return fgInstance->fGlobalLogLevel;
842 //_____________________________________________________________________________
843 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
845 // get the debug level for the given module and class
847 if (!fgInstance) new AliLog;
848 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
851 //_____________________________________________________________________________
852 void AliLog::PrintMessage(UInt_t type, const char* message,
853 const char* module, const char* className,
854 const char* function, const char* file, Int_t line)
856 // print the given message
858 // don't print the message if it is repeated
859 if (fPrintRepetitions &&
860 (fLastType == type) &&
861 (message && (fLastMessage.CompareTo(message) == 0)) &&
862 ((module && (fLastModule.CompareTo(module) == 0)) ||
863 (!module && fLastModule.IsNull())) &&
864 ((className && (fLastClassName.CompareTo(className) == 0)) ||
865 (!className && fLastClassName.IsNull())) &&
866 ((function && (fLastFunction.CompareTo(function) == 0)) ||
867 (!function && fLastFunction.IsNull()))&&
868 ((file && (fLastFile.CompareTo(file) == 0)) ||
869 (!file && fLastFile.IsNull())) &&
870 (fLastLine == line)) {
875 // print number of repetitions
876 if (fRepetitions > 0) PrintRepetitions();
878 // remember this message
881 fLastMessage = message;
882 fLastModule = module;
883 fLastClassName = className;
884 fLastFunction = function;
889 FILE* stream = GetOutputStream(type);
890 static const char* typeNames[kMaxType] =
891 {"Fatal", "Error", "Warning", "Info", "Debug"};
893 if (fPrintType[type]) {
894 PrintString(type, stream, "%c-", typeNames[type][0]);
896 if (fPrintModule[type] && module) {
897 PrintString(type, stream, "%s/", module);
899 if (fPrintScope[type] && className) {
900 PrintString(type, stream, "%s::", className);
903 PrintString(type, stream, "%s: %s", function, message);
905 PrintString(type, stream, "%s", function);
907 if (fPrintLocation[type] && file) {
908 PrintString(type, stream, " (%s:%.0d)", file, line);
911 PrintString(type, stream, "\n");
913 PrintString(type, stream, ": ");
915 if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
918 //_____________________________________________________________________________
919 void AliLog::PrintRepetitions()
921 // print number of repetitions
923 PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
924 fRepetitions, (fRepetitions > 1) ? "s" : "");
925 if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
928 //_____________________________________________________________________________
929 void AliLog::Message(UInt_t level, const char* message,
930 const char* module, const char* className,
931 const char* function, const char* file, Int_t line)
933 // print a log message
935 if (!fgInstance) new AliLog;
937 // get the message type
939 if (type >= kMaxType) type = kMaxType - 1;
941 // print the message if the debug level allows
942 if (level <= fgInstance->GetLogLevel(module, className)) {
943 fgInstance->PrintMessage(type, message,
944 module, className, function, file, line);
947 // abort in case of a fatal message
948 if (type == kFatal) {
951 gSystem->StackTrace();
952 if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
955 if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
963 //_____________________________________________________________________________
964 void AliLog::Debug(UInt_t level, const char* message,
965 const char* module, const char* className,
966 const char* function, const char* file, Int_t line)
968 // print a debug message
970 if (level == 0) level = 1;
971 level += kDebugOffset;
972 Message(level, message, module, className, function, file, line);
976 //_____________________________________________________________________________
977 Int_t AliLog::RedirectStdoutTo(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 output to the stream of the given type
983 if (!fgInstance) new AliLog;
984 return fgInstance->RedirectTo(stdout, type, level, module, className,
985 function, file, line, print);
988 //_____________________________________________________________________________
989 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
990 const char* className, const char* function,
991 const char* file, Int_t line, Bool_t print)
993 // redirect the standard error output to the stream of the given type
995 if (!fgInstance) new AliLog;
996 return fgInstance->RedirectTo(stderr, type, level, module, className,
997 function, file, line, print);
1000 //_____________________________________________________________________________
1001 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
1002 const char* module, const char* className,
1003 const char* function, const char* file, Int_t line,
1006 // redirect the standard (error) output stream to the stream of the given type
1008 // get the original file descriptor to be able to restore it later
1009 Int_t original = dup(fileno(stream));
1012 // flush the stream of the selected type
1013 FILE* newStream = GetOutputStream(type);
1017 if ((type == kDebug) && (level > 0)) level--;
1018 if (type + level > GetLogLevel(module, className)) { // /dev/null
1019 if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
1020 } else if (fOutputTypes[type] == 0) { // stdout
1021 if (stream != stdout) dup2(fileno(stdout), fileno(stream));
1022 } else if (fOutputTypes[type] == 1) { // stderr
1023 if (stream != stderr) dup2(fileno(stderr), fileno(stream));
1024 } else if (fOutputTypes[type] == 2) { // file
1025 if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
1026 } else if (fOutputTypes[type] == 3) { // external C++ stream
1027 // redirection is not possible for external C++ streams
1030 // print information
1032 PrintMessage(type, NULL, module, className, function, file, line);
1039 //_____________________________________________________________________________
1040 void AliLog::RestoreStdout(Int_t original)
1042 // restore the standard output
1045 dup2(original, fileno(stdout));
1049 //_____________________________________________________________________________
1050 void AliLog::RestoreStderr(Int_t original)
1052 // restore the standard error output
1055 dup2(original, fileno(stderr));
1060 //_____________________________________________________________________________
1061 ostream& AliLog::Stream(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 (!fgInstance) new AliLog;
1068 return fgInstance->GetStream(type, level, module, className,
1069 function, file, line);
1072 //_____________________________________________________________________________
1073 ostream& AliLog::GetStream(EType_t type, UInt_t level,
1074 const char* module, const char* className,
1075 const char* function, const char* file, Int_t line)
1077 // get the stream object for the given output type
1079 if ((type == kDebug) && (level > 0)) level--;
1080 Bool_t noOutput = (type + level > GetLogLevel(module, className));
1083 PrintMessage(type, NULL, module, className, function, file, line);
1085 fflush(GetOutputStream(type));
1087 static ofstream nullStream("/dev/null");
1090 } else if (fOutputTypes[type] == 0) {
1092 } else if (fOutputTypes[type] == 1) {
1094 } else if (fOutputTypes[type] == 2) {
1095 return *fOutputStreams[type];
1096 } else if (fOutputTypes[type] == 3) {
1097 return *fOutputStreams[type];
1103 void AliLog::SetStreamOutput(ostream* stream)
1105 // set an external stream as target for log messages of all types
1106 // the external stream is completely handled by the caller, the
1107 // AliLog class just writes to it
1109 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1110 SetStreamOutput((AliLog::EType_t)iType, stream);
1114 void AliLog::SetStreamOutput(EType_t type, ostream* stream)
1116 // set an external stream as target for log messages of the given type
1117 // the external stream is completely handled by the caller, the
1118 // AliLog class just writes to it
1120 if ((type < kFatal) || (type >= kMaxType)) return;
1121 if (!fgInstance) new AliLog;
1122 if (fgInstance->fOutputTypes[type] == 2) {
1123 fgInstance->CloseFile(type);
1125 fgInstance->fOutputTypes[type] = 3;
1126 fgInstance->fFileNames[type] = "";
1127 fgInstance->fOutputFiles[type] = NULL;
1128 fgInstance->fOutputStreams[type] = stream;
1131 void AliLog::SetLogNotification(AliLogNotification pCallBack)
1133 // set a notification callback function for log messages of all types
1135 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1136 SetLogNotification((AliLog::EType_t)iType, pCallBack);
1140 void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
1142 // set a notifications call back function for log messages of all types
1143 // the callback fuction is invoced whenever an output was written
1144 // Note: does not work for c++ streamer classes, the external stream
1145 // has to handle this diectly (e.g. custom implementation of endl)
1147 if ((type < kFatal) || (type >= kMaxType)) return;
1148 if (!fgInstance) new AliLog;
1149 fgInstance->fCallBacks[type]=pCallBack;
1152 void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1154 // this is the general method to print a log message using variadac args
1155 // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1157 // Only in case of an external c++ ostream type output, the message is
1158 // written to that stream and the notifictaion callback is called.
1159 // The message is printed by a normal vfprintf function otherwise
1161 if (format==NULL) return;
1164 va_start(ap, format);
1165 if (fOutputTypes[type] != 3) {
1167 vfprintf(stream, format, ap);
1170 // build the string and write everthing to the corresponding ostream
1171 TString fmt(format);
1172 TArrayC tgt(fmt.Length()*10); // just take a number
1175 R__VA_COPY(bap, ap);
1177 #warning definition of R__VA_COPY has disappeared
1182 iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1184 iResult=tgt.GetSize()*2;
1185 } else if (iResult<tgt.GetSize()) {
1189 if (iResult<10000) {
1192 R__VA_COPY(ap, bap);
1196 tgt[tgt.GetSize()-1]=0;
1204 if (fOutputStreams[type]) {
1205 *(fOutputStreams[type]) << tgt.GetArray();
1212 void AliLog::MakeCoreDump(const char *fout){
1214 // Functionality to make a program snapshot
1215 // gcore - Generate a core file for a running process
1216 // gcore dmake a current snapshot, program can continue further
1217 // We assum that gcore is installed
1218 // for details see: man gcore
1220 // Example use - make default core file for current process: AliLog::MakeCoreDump(0)
1223 // Automatic core dump creation in case of the AliFatal can be specified using
1224 // static void EnableCoreDump(Bool_t enabled);
1225 // Core dump is created in addition to the stack trace ()
1226 // marian.ivanov@cern.ch
1228 if (!gSystem) return;
1229 printf("AliLog::MakeCoreDump\n");
1231 gSystem->Exec(Form("gcore -o %s %d",fout, gSystem->GetPid()));
1233 gSystem->Exec(Form("gcore %d", gSystem->GetPid()));
1238 void AliLog::TestException(Int_t level){
1240 // Dummy function to throw exception
1242 printf("AliLog::TestException(%d)\n",level);
1245 TestException(level);
1247 throw std::runtime_error("Test exception");