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
48 // implementation of a singleton here
49 AliLog* AliLog::fgInstance = NULL;
51 Bool_t AliLog::fgDebugEnabled = kTRUE;
54 * get root logger singleton instance
56 AliLog *AliLog::GetRootLogger()
58 if (fgInstance == NULL)
61 fgInstance = new AliLog;
68 * delete the root logger singleton instance
70 void AliLog::DeleteRootLogger()
72 if (fgInstance != NULL)
80 * default private constructor
84 fGlobalLogLevel(kInfo),
87 fPrintRepetitions(kTRUE),
97 // default constructor: set default values
99 for (Int_t iType = kFatal; iType < kMaxType; iType++)
101 fOutputTypes[iType] = 0;
102 fFileNames[iType] = "";
103 fOutputFiles[iType] = NULL;
104 fOutputStreams[iType] = NULL;
105 fCallBacks[iType]=NULL;
107 fPrintType[iType] = kTRUE;
108 fPrintModule[iType] = kFALSE;
109 fPrintScope[iType] = kTRUE;
110 fPrintLocation[iType] = (iType == kDebug);
114 // replace the previous instance by this one
115 if (fgInstance) delete fgInstance;
118 SetHandleRootMessages(kTRUE);
120 // read the .rootrc settings
129 // destructor: clean up and reset instance pointer
131 if (fRepetitions > 0) PrintRepetitions();
133 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
135 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
138 fClassDebugLevels.Delete();
140 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
142 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
145 fClassDebugLevels.Delete();
147 for (Int_t iType = kFatal; iType < kMaxType; iType++)
159 //_____________________________________________________________________________
160 AliLog::AliLog(const AliLog& log) :
162 fGlobalLogLevel(log.fGlobalLogLevel),
163 fModuleDebugLevels(log.fModuleDebugLevels),
164 fClassDebugLevels(log.fClassDebugLevels),
165 fPrintRepetitions(log.fPrintRepetitions),
166 fRepetitions(log.fRepetitions),
167 fLastType(log.fLastType),
168 fLastMessage(log.fLastMessage),
169 fLastModule(log.fLastModule),
170 fLastClassName(log.fLastClassName),
171 fLastFunction(log.fLastFunction),
172 fLastFile(log.fLastFile),
173 fLastLine(log.fLastLine)
177 Fatal("AliLog", "copy constructor not implemented");
181 //_____________________________________________________________________________
182 AliLog& AliLog::operator = (const AliLog& /*log*/)
184 // assignment operator
186 Fatal("operator =", "assignment operator not implemented");
192 * gSystem see TSystem.h
195 * LOG_NO_DEBUG: fgDebugEnabled <- false
196 * AliRoot.AliLog.EnableDebug
197 * AliRoot.AliLog.GlobalLogLevel
199 //_____________________________________________________________________________
200 void AliLog::ReadEnvSettings()
202 // load settings from the root configuration file (.rootrc)
203 // and from environment variables
205 static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
207 // debug en- or disabling
208 if (gSystem->Getenv("LOG_NO_DEBUG"))
210 fgDebugEnabled = kFALSE;
212 else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
214 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
215 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
219 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
221 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
223 for (Int_t iType = kFatal; iType < kMaxType; iType++)
225 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
228 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
231 // global debug level
232 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
234 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
235 if (level < -kDebugOffset) level = kDebugOffset;
236 fGlobalLogLevel = kDebugOffset + level;
237 AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
240 // module debug level
241 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
243 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
244 char* p = const_cast<char*>(levels.Data());
246 while (const char* module = strtok(p, " "))
249 char* pos = const_cast<char*>(index(module, ':'));
252 Int_t level = atoi(pos);
253 SetModuleDebugLevel(module, level);
254 AliDebug(3, Form("debug level for module %s set to %d", module, level));
259 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
261 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
262 char* p = const_cast<char*>(levels.Data());
264 while (const char* className = strtok(p, " "))
267 char* pos = const_cast<char*>(index(className, ':'));
270 Int_t level = atoi(pos);
271 SetClassDebugLevel(className, level);
272 AliDebug(3, Form("debug level for class %s set to %d", className, level));
276 // general output stream
277 if (gEnv->Defined("AliRoot.AliLog.Output"))
279 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
281 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
284 AliDebug(3, "output stream set to standard output for all types");
286 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
289 AliDebug(3, "output stream set to error output for all types");
291 else if (!stream.IsNull())
293 SetFileOutput(stream);
294 AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
298 // individual output streams
299 for (Int_t iType = kFatal; iType < kMaxType; iType++)
301 TString name("AliRoot.AliLog.Output.");
302 name += &typeNames[iType][1];
304 if (gEnv->Defined(name))
306 TString stream = gEnv->GetValue(name, "Standard");
308 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
310 SetStandardOutput(EType_t(iType));
311 AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
313 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
315 SetErrorOutput(EType_t(iType));
316 AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
318 else if (!stream.IsNull())
320 SetFileOutput(EType_t(iType), stream);
321 AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
326 // handling of root error messages
327 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
329 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
330 SetHandleRootMessages(on);
331 AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
335 static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
336 Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
338 for (Int_t iSetting = 0; iSetting < 4; iSetting++)
340 TString name("AliRoot.AliLog.Print");
341 name += settingNames[iSetting];
343 if (gEnv->Defined(name))
345 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
347 for (Int_t iType = kFatal; iType < kMaxType; iType++)
349 settings[iSetting][iType] = on;
351 AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
354 for (Int_t iType = kFatal; iType < kMaxType; iType++)
356 TString nameType = name + "." + &typeNames[iType][1];
358 if (gEnv->Defined(nameType))
360 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
361 settings[iSetting][iType] = on;
362 AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
367 // repetition of messages
368 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
370 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
371 fPrintRepetitions = on;
372 AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
377 //_____________________________________________________________________________
378 void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
379 const char* location, const char* message)
381 // new error handler for messages from root
385 case ::kFatal : level = kFatal; break;
387 DefaultErrorHandler(level, abort, location, message);
390 DefaultErrorHandler(level, abort, location, message);
392 case ::kError : level = kError; break;
393 case ::kWarning : level = kWarning; break;
394 case ::kInfo : level = kInfo; break;
395 default : level = kDebug; break;
397 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
401 // DEPRECATED: USE A CONFIGURATION FILE INSTEAD
402 //_____________________________________________________________________________
403 void AliLog::EnableDebug(Bool_t enabled)
405 // enable or disable debug output
407 fgDebugEnabled = enabled;
410 //_____________________________________________________________________________
411 void AliLog::SetGlobalLogLevel(EType_t type)
413 // set the global debug level
416 if (!fgInstance) new AliLog;
417 fgInstance->fGlobalLogLevel = type;
420 //_____________________________________________________________________________
421 Int_t AliLog::GetGlobalLogLevel()
423 // get the global debug level
425 if (!fgInstance) new AliLog;
426 return fgInstance->fGlobalLogLevel;
429 //_____________________________________________________________________________
430 void AliLog::SetGlobalDebugLevel(Int_t level)
432 // set the global debug level
434 if (!fgInstance) new AliLog;
435 if (level < -kDebugOffset) level = -kDebugOffset;
436 fgInstance->fGlobalLogLevel = kDebugOffset + level;
439 //_____________________________________________________________________________
440 Int_t AliLog::GetGlobalDebugLevel()
442 // get the global debug level
444 if (!fgInstance) new AliLog;
445 return fgInstance->fGlobalLogLevel - kDebugOffset;
448 //_____________________________________________________________________________
449 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
451 // set the debug level for the given module
454 if (!fgInstance) new AliLog;
455 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
457 obj = new TNamed(module, module);
458 fgInstance->fModuleDebugLevels.Add(obj);
460 level += kDebugOffset;
461 if (level < kFatal) level = kFatal;
462 obj->SetUniqueID(level);
465 //_____________________________________________________________________________
466 void AliLog::ClearModuleDebugLevel(const char* module)
468 // remove the setting of the debug level for the given module
471 if (!fgInstance) new AliLog;
472 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
473 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
476 //_____________________________________________________________________________
477 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
479 // set the debug level for the given class
481 if (!className) return;
482 if (!fgInstance) new AliLog;
483 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
485 obj = new TNamed(className, className);
486 fgInstance->fClassDebugLevels.Add(obj);
488 level += kDebugOffset;
489 if (level < kFatal) level = kFatal;
490 obj->SetUniqueID(level);
493 //_____________________________________________________________________________
494 void AliLog::ClearClassDebugLevel(const char* className)
496 // remove the setting of the debug level for the given class
498 if (!className) return;
499 if (!fgInstance) new AliLog;
500 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
501 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
505 //_____________________________________________________________________________
506 void AliLog::SetStandardOutput()
508 // write all log messages to the standard output (stdout)
510 if (!fgInstance) new AliLog;
511 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
512 fgInstance->CloseFile(iType);
513 fgInstance->fOutputTypes[iType] = 0;
517 //_____________________________________________________________________________
518 void AliLog::SetStandardOutput(EType_t type)
520 // write log messages of the given type to the standard output (stdout)
522 if ((type < kFatal) || (type >= kMaxType)) return;
523 if (!fgInstance) new AliLog;
524 fgInstance->CloseFile(type);
525 fgInstance->fOutputTypes[type] = 0;
528 //_____________________________________________________________________________
529 void AliLog::SetErrorOutput()
531 // write all log messages to the error output (stderr)
533 if (!fgInstance) new AliLog;
534 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
535 fgInstance->CloseFile(iType);
536 fgInstance->fOutputTypes[iType] = 1;
540 //_____________________________________________________________________________
541 void AliLog::SetErrorOutput(EType_t type)
543 // write log messages of the given type to the error output (stderr)
545 if ((type < kFatal) || (type >= kMaxType)) return;
546 if (!fgInstance) new AliLog;
547 fgInstance->CloseFile(type);
548 fgInstance->fOutputTypes[type] = 1;
551 //_____________________________________________________________________________
552 void AliLog::SetFileOutput(const char* fileName)
554 // write all log messages to the given file
556 if (!fgInstance) new AliLog;
557 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
558 if ((fgInstance->fOutputTypes[iType] == 2) &&
559 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
560 fgInstance->CloseFile(iType);
562 fgInstance->fOutputTypes[iType] = 2;
563 fgInstance->fFileNames[iType] = fileName;
564 fgInstance->fOutputFiles[iType] = NULL;
565 fgInstance->fOutputStreams[iType] = NULL;
569 //_____________________________________________________________________________
570 void AliLog::SetFileOutput(EType_t type, const char* fileName)
572 // write log messages of the given type to the given file
574 if ((type < kFatal) || (type >= kMaxType)) return;
575 if (!fgInstance) new AliLog;
576 if ((fgInstance->fOutputTypes[type] == 2) &&
577 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
578 fgInstance->CloseFile(type);
580 fgInstance->fOutputTypes[type] = 2;
581 fgInstance->fFileNames[type] = fileName;
582 fgInstance->fOutputFiles[type] = NULL;
583 fgInstance->fOutputStreams[type] = NULL;
586 //_____________________________________________________________________________
587 void AliLog::CloseFile(Int_t type)
589 // close the file for the given type if needed
591 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
592 Bool_t closeFile = kTRUE;
593 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
594 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
599 fclose(fOutputFiles[type]);
600 ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
602 delete fOutputStreams[type];
605 fOutputFiles[type] = NULL;
606 fOutputStreams[type] = NULL;
607 fFileNames[type] = "";
608 fOutputTypes[type] = 0;
611 //_____________________________________________________________________________
612 FILE* AliLog::GetOutputStream(Int_t type)
614 // get the output stream for the given type of messages
616 if (type > kDebug) type = kDebug;
617 if (fOutputTypes[type] == 0) return stdout;
618 else if (fOutputTypes[type] == 1) return stderr;
619 else if (fOutputTypes[type] == 2) {
620 if (!fOutputFiles[type]) {
622 ostream* stream = NULL;
623 if (!fFileNames[type].IsNull()) {
624 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
625 if ((iType != type) &&
626 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
627 fOutputFiles[iType]) {
628 file = fOutputFiles[iType];
629 stream = fOutputStreams[iType];
634 file = fopen(fFileNames[type], "a");
635 stream = new ofstream(fFileNames[type], ios::app);
638 fOutputFiles[type] = file;
639 fOutputStreams[type] = stream;
640 if (!file) CloseFile(type);
642 if (fOutputFiles[type]) return fOutputFiles[type];
648 //_____________________________________________________________________________
651 // flush the output streams
653 if (!fgInstance) new AliLog;
654 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
655 if (fgInstance->fOutputFiles[iType]) {
656 fflush(fgInstance->fOutputFiles[iType]);
657 fgInstance->fOutputStreams[iType]->flush();
665 //_____________________________________________________________________________
666 void AliLog::SetHandleRootMessages(Bool_t on)
668 // enable or disable the handling of messages form root
670 if (!fgInstance) new AliLog;
672 SetErrorHandler(RootErrorHandler);
674 SetErrorHandler(DefaultErrorHandler);
679 //_____________________________________________________________________________
680 void AliLog::SetPrintType(Bool_t on)
682 // switch on or off the printing of the message type for all message types
684 if (!fgInstance) new AliLog;
685 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
686 fgInstance->fPrintType[iType] = on;
690 //_____________________________________________________________________________
691 void AliLog::SetPrintType(EType_t type, Bool_t on)
693 // switch on or off the printing of the message type for the given message type
695 if ((type < kFatal) || (type >= kMaxType)) return;
696 if (!fgInstance) new AliLog;
697 fgInstance->fPrintType[type] = on;
700 //_____________________________________________________________________________
701 void AliLog::SetPrintModule(Bool_t on)
703 // switch on or off the printing of the module for all message types
705 if (!fgInstance) new AliLog;
706 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
707 fgInstance->fPrintModule[iType] = on;
711 //_____________________________________________________________________________
712 void AliLog::SetPrintModule(EType_t type, Bool_t on)
714 // switch on or off the printing of the module for the given message type
716 if ((type < kFatal) || (type >= kMaxType)) return;
717 if (!fgInstance) new AliLog;
718 fgInstance->fPrintModule[type] = on;
721 //_____________________________________________________________________________
722 void AliLog::SetPrintScope(Bool_t on)
724 // switch on or off the printing of the scope/class name for all message types
726 if (!fgInstance) new AliLog;
727 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
728 fgInstance->fPrintScope[iType] = on;
732 //_____________________________________________________________________________
733 void AliLog::SetPrintScope(EType_t type, Bool_t on)
735 // switch on or off the printing of the scope/class name
736 // for the given message type
738 if ((type < kFatal) || (type >= kMaxType)) return;
739 if (!fgInstance) new AliLog;
740 fgInstance->fPrintScope[type] = on;
743 //_____________________________________________________________________________
744 void AliLog::SetPrintLocation(Bool_t on)
746 // switch on or off the printing of the file name and line number
747 // for all message types
749 if (!fgInstance) new AliLog;
750 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
751 fgInstance->fPrintLocation[iType] = on;
755 //_____________________________________________________________________________
756 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
758 // switch on or off the printing of the file name and line number
759 // for the given message type
761 if ((type < kFatal) || (type >= kMaxType)) return;
762 if (!fgInstance) new AliLog;
763 fgInstance->fPrintLocation[type] = on;
767 //_____________________________________________________________________________
768 void AliLog::SetPrintRepetitions(Bool_t on)
770 // switch on or off the printing of the number of repetitions of a message
771 // instead of repeating the same message
773 if (!fgInstance) new AliLog;
774 if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
775 fgInstance->fPrintRepetitions = on;
779 //_____________________________________________________________________________
780 void AliLog::WriteToFile(const char* name, Int_t option)
782 // write the log object with the given name and option to the current file
784 if (!fgInstance) new AliLog;
785 fgInstance->TObject::Write(name, option);
789 //_____________________________________________________________________________
790 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
792 // get the logging level for the given module and class
794 if (!fgInstance) new AliLog;
796 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
797 if (obj) return obj->GetUniqueID();
800 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
801 if (obj) return obj->GetUniqueID();
803 return fgInstance->fGlobalLogLevel;
806 //_____________________________________________________________________________
807 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
809 // get the debug level for the given module and class
811 if (!fgInstance) new AliLog;
812 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
815 //_____________________________________________________________________________
816 void AliLog::PrintMessage(UInt_t type, const char* message,
817 const char* module, const char* className,
818 const char* function, const char* file, Int_t line)
820 // print the given message
822 // don't print the message if it is repeated
823 if (fPrintRepetitions &&
824 (fLastType == type) &&
825 (message && (fLastMessage.CompareTo(message) == 0)) &&
826 ((module && (fLastModule.CompareTo(module) == 0)) ||
827 (!module && fLastModule.IsNull())) &&
828 ((className && (fLastClassName.CompareTo(className) == 0)) ||
829 (!className && fLastClassName.IsNull())) &&
830 ((function && (fLastFunction.CompareTo(function) == 0)) ||
831 (!function && fLastFunction.IsNull()))&&
832 ((file && (fLastFile.CompareTo(file) == 0)) ||
833 (!file && fLastFile.IsNull())) &&
834 (fLastLine == line)) {
839 // print number of repetitions
840 if (fRepetitions > 0) PrintRepetitions();
842 // remember this message
845 fLastMessage = message;
846 fLastModule = module;
847 fLastClassName = className;
848 fLastFunction = function;
853 FILE* stream = GetOutputStream(type);
854 static const char* typeNames[kMaxType] =
855 {"Fatal", "Error", "Warning", "Info", "Debug"};
857 if (fPrintType[type]) {
858 PrintString(type, stream, "%c-", typeNames[type][0]);
860 if (fPrintModule[type] && module) {
861 PrintString(type, stream, "%s/", module);
863 if (fPrintScope[type] && className) {
864 PrintString(type, stream, "%s::", className);
867 PrintString(type, stream, "%s: %s", function, message);
869 PrintString(type, stream, "%s", function);
871 if (fPrintLocation[type] && file) {
872 PrintString(type, stream, " (%s:%.0d)", file, line);
875 PrintString(type, stream, "\n");
877 PrintString(type, stream, ": ");
879 if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
882 //_____________________________________________________________________________
883 void AliLog::PrintRepetitions()
885 // print number of repetitions
887 PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
888 fRepetitions, (fRepetitions > 1) ? "s" : "");
889 if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
892 //_____________________________________________________________________________
893 void AliLog::Message(UInt_t level, const char* message,
894 const char* module, const char* className,
895 const char* function, const char* file, Int_t line)
897 // print a log message
899 if (!fgInstance) new AliLog;
901 // get the message type
903 if (type >= kMaxType) type = kMaxType - 1;
905 // print the message if the debug level allows
906 if (level <= fgInstance->GetLogLevel(module, className)) {
907 fgInstance->PrintMessage(type, message,
908 module, className, function, file, line);
911 // abort in case of a fatal message
912 if (type == kFatal) {
915 gSystem->StackTrace();
923 //_____________________________________________________________________________
924 void AliLog::Debug(UInt_t level, const char* message,
925 const char* module, const char* className,
926 const char* function, const char* file, Int_t line)
928 // print a debug message
930 if (level == 0) level = 1;
931 level += kDebugOffset;
932 Message(level, message, module, className, function, file, line);
936 //_____________________________________________________________________________
937 Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
938 const char* className, const char* function,
939 const char* file, Int_t line, Bool_t print)
941 // redirect the standard output to the stream of the given type
943 if (!fgInstance) new AliLog;
944 return fgInstance->RedirectTo(stdout, type, level, module, className,
945 function, file, line, print);
948 //_____________________________________________________________________________
949 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
950 const char* className, const char* function,
951 const char* file, Int_t line, Bool_t print)
953 // redirect the standard error output to the stream of the given type
955 if (!fgInstance) new AliLog;
956 return fgInstance->RedirectTo(stderr, type, level, module, className,
957 function, file, line, print);
960 //_____________________________________________________________________________
961 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
962 const char* module, const char* className,
963 const char* function, const char* file, Int_t line,
966 // redirect the standard (error) output stream to the stream of the given type
968 // get the original file descriptor to be able to restore it later
969 Int_t original = dup(fileno(stream));
972 // flush the stream of the selected type
973 FILE* newStream = GetOutputStream(type);
977 if ((type == kDebug) && (level > 0)) level--;
978 if (type + level > GetLogLevel(module, className)) { // /dev/null
979 freopen("/dev/null", "a", stream);
980 } else if (fOutputTypes[type] == 0) { // stdout
981 if (stream != stdout) dup2(fileno(stdout), fileno(stream));
982 } else if (fOutputTypes[type] == 1) { // stderr
983 if (stream != stderr) dup2(fileno(stderr), fileno(stream));
984 } else if (fOutputTypes[type] == 2) { // file
985 freopen(fFileNames[type], "a", stream);
986 } else if (fOutputTypes[type] == 3) { // external C++ stream
987 // redirection is not possible for external C++ streams
992 PrintMessage(type, NULL, module, className, function, file, line);
999 //_____________________________________________________________________________
1000 void AliLog::RestoreStdout(Int_t original)
1002 // restore the standard output
1005 dup2(original, fileno(stdout));
1009 //_____________________________________________________________________________
1010 void AliLog::RestoreStderr(Int_t original)
1012 // restore the standard error output
1015 dup2(original, fileno(stderr));
1020 //_____________________________________________________________________________
1021 ostream& AliLog::Stream(EType_t type, UInt_t level,
1022 const char* module, const char* className,
1023 const char* function, const char* file, Int_t line)
1025 // get the stream object for the given output type
1027 if (!fgInstance) new AliLog;
1028 return fgInstance->GetStream(type, level, module, className,
1029 function, file, line);
1032 //_____________________________________________________________________________
1033 ostream& AliLog::GetStream(EType_t type, UInt_t level,
1034 const char* module, const char* className,
1035 const char* function, const char* file, Int_t line)
1037 // get the stream object for the given output type
1039 if ((type == kDebug) && (level > 0)) level--;
1040 Bool_t noOutput = (type + level > GetLogLevel(module, className));
1043 PrintMessage(type, NULL, module, className, function, file, line);
1045 fflush(GetOutputStream(type));
1047 static ofstream nullStream("/dev/null");
1050 } else if (fOutputTypes[type] == 0) {
1052 } else if (fOutputTypes[type] == 1) {
1054 } else if (fOutputTypes[type] == 2) {
1055 return *fOutputStreams[type];
1056 } else if (fOutputTypes[type] == 3) {
1057 return *fOutputStreams[type];
1063 void AliLog::SetStreamOutput(ostream* stream)
1065 // set an external stream as target for log messages of all types
1066 // the external stream is completely handled by the caller, the
1067 // AliLog class just writes to it
1069 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1070 SetStreamOutput((AliLog::EType_t)iType, stream);
1074 void AliLog::SetStreamOutput(EType_t type, ostream* stream)
1076 // set an external stream as target for log messages of the given type
1077 // the external stream is completely handled by the caller, the
1078 // AliLog class just writes to it
1080 if ((type < kFatal) || (type >= kMaxType)) return;
1081 if (!fgInstance) new AliLog;
1082 if (fgInstance->fOutputTypes[type] == 2) {
1083 fgInstance->CloseFile(type);
1085 fgInstance->fOutputTypes[type] = 3;
1086 fgInstance->fFileNames[type] = "";
1087 fgInstance->fOutputFiles[type] = NULL;
1088 fgInstance->fOutputStreams[type] = stream;
1091 void AliLog::SetLogNotification(AliLogNotification pCallBack)
1093 // set a notification callback function for log messages of all types
1095 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1096 SetLogNotification((AliLog::EType_t)iType, pCallBack);
1100 void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
1102 // set a notifications call back function for log messages of all types
1103 // the callback fuction is invoced whenever an output was written
1104 // Note: does not work for c++ streamer classes, the external stream
1105 // has to handle this diectly (e.g. custom implementation of endl)
1107 if ((type < kFatal) || (type >= kMaxType)) return;
1108 if (!fgInstance) new AliLog;
1109 fgInstance->fCallBacks[type]=pCallBack;
1112 void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1114 // this is the general method to print a log message using variadac args
1115 // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1117 // Only in case of an external c++ ostream type output, the message is
1118 // written to that stream and the notifictaion callback is called.
1119 // The message is printed by a normal vfprintf function otherwise
1121 if (format==NULL) return;
1124 va_start(ap, format);
1125 if (fOutputTypes[type] != 3) {
1127 vfprintf(stream, format, ap);
1130 // build the string and write everthing to the corresponding ostream
1131 TString fmt(format);
1132 TArrayC tgt(fmt.Length()*10); // just take a number
1135 R__VA_COPY(bap, ap);
1137 #warning definition of R__VA_COPY has disappeared
1142 iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1144 iResult=tgt.GetSize()*2;
1145 } else if (iResult<tgt.GetSize()) {
1149 if (iResult<10000) {
1152 R__VA_COPY(ap, bap);
1156 tgt[tgt.GetSize()-1]=0;
1164 if (fOutputStreams[type]) {
1165 *(fOutputStreams[type]) << tgt.GetArray();