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 ///////////////////////////////////////////////////////////////////////////////
35 #include <Riostream.h>
47 AliLog* AliLog::fgInstance = NULL;
49 Bool_t AliLog::fgDebugEnabled = kTRUE;
52 //_____________________________________________________________________________
55 fGlobalLogLevel(kInfo),
58 fPrintRepetitions(kTRUE),
68 // default constructor: set default values
70 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
71 fOutputTypes[iType] = 0;
72 fFileNames[iType] = "";
73 fOutputFiles[iType] = NULL;
74 fOutputStreams[iType] = NULL;
75 fCallBacks[iType]=NULL;
77 fPrintType[iType] = kTRUE;
78 fPrintModule[iType] = kFALSE;
79 fPrintScope[iType] = kTRUE;
80 fPrintLocation[iType] = (iType == kDebug);
83 // replace the previous instance by this one
84 if (fgInstance) delete fgInstance;
87 SetHandleRootMessages(kTRUE);
89 // read the .rootrc settings
93 //_____________________________________________________________________________
96 // destructor: clean up and reset instance pointer
98 if (fRepetitions > 0) PrintRepetitions();
100 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++) {
101 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
103 fClassDebugLevels.Delete();
104 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++) {
105 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
107 fClassDebugLevels.Delete();
109 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
118 //_____________________________________________________________________________
119 AliLog::AliLog(const AliLog& log) :
121 fGlobalLogLevel(log.fGlobalLogLevel),
122 fModuleDebugLevels(log.fModuleDebugLevels),
123 fClassDebugLevels(log.fClassDebugLevels),
124 fPrintRepetitions(log.fPrintRepetitions),
125 fRepetitions(log.fRepetitions),
126 fLastType(log.fLastType),
127 fLastMessage(log.fLastMessage),
128 fLastModule(log.fLastModule),
129 fLastClassName(log.fLastClassName),
130 fLastFunction(log.fLastFunction),
131 fLastFile(log.fLastFile),
132 fLastLine(log.fLastLine)
136 Fatal("AliLog", "copy constructor not implemented");
139 //_____________________________________________________________________________
140 AliLog& AliLog::operator = (const AliLog& /*log*/)
142 // assignment operator
144 Fatal("operator =", "assignment operator not implemented");
149 //_____________________________________________________________________________
150 void AliLog::ReadEnvSettings()
152 // load settings from the root configuration file (.rootrc)
153 // and from environment variables
155 static const char* typeNames[kMaxType] =
156 {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
158 // debug en- or disabling
159 if (gSystem->Getenv("LOG_NO_DEBUG")) {
160 fgDebugEnabled = kFALSE;
161 } else if (gEnv->Defined("AliRoot.AliLog.EnableDebug")) {
162 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug",
164 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
168 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel")) {
169 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
170 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
171 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
173 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
176 // global debug level
177 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel")) {
178 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel",
179 Int_t(fGlobalLogLevel - kDebugOffset));
180 if (level < -kDebugOffset) level = kDebugOffset;
181 fGlobalLogLevel = kDebugOffset + level;
182 AliDebug(3, Form("global debug level set to %d",
183 fGlobalLogLevel - kDebugOffset));
186 // module debug level
187 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel")) {
188 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
189 char* p = const_cast<char*>(levels.Data());
190 while (const char* module = strtok(p, " ")) {
192 char* pos = index(module, ':');
195 Int_t level = atoi(pos);
196 SetModuleDebugLevel(module, level);
197 AliDebug(3, Form("debug level for module %s set to %d", module, level));
202 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel")) {
203 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
204 char* p = const_cast<char*>(levels.Data());
205 while (const char* className = strtok(p, " ")) {
207 char* pos = index(className, ':');
210 Int_t level = atoi(pos);
211 SetClassDebugLevel(className, level);
212 AliDebug(3, Form("debug level for class %s set to %d",
217 // general output stream
218 if (gEnv->Defined("AliRoot.AliLog.Output")) {
219 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
220 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
222 AliDebug(3, "output stream set to standard output for all types");
223 } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
225 AliDebug(3, "output stream set to error output for all types");
226 } else if (!stream.IsNull()) {
227 SetFileOutput(stream);
228 AliDebug(3, Form("output stream set to file %s for all types",
233 // individual output streams
234 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
235 TString name("AliRoot.AliLog.Output.");
236 name += &typeNames[iType][1];
237 if (gEnv->Defined(name)) {
238 TString stream = gEnv->GetValue(name, "Standard");
239 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
240 SetStandardOutput(EType_t(iType));
241 AliDebug(3, Form("output stream set to standard output for type %s",
243 } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
244 SetErrorOutput(EType_t(iType));
245 AliDebug(3, Form("output stream set to error output for type %s",
247 } else if (!stream.IsNull()) {
248 SetFileOutput(EType_t(iType), stream);
249 AliDebug(3, Form("output stream set to file %s for type %s",
250 stream.Data(), typeNames[iType]));
255 // handling of root error messages
256 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages")) {
257 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
258 SetHandleRootMessages(on);
259 AliDebug(3, Form("handling of root messages %sabled",
260 ((on) ? "en" : "dis")));
264 static const char* settingNames[4] =
265 {"Type", "Module", "Scope", "Location"};
267 {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
268 for (Int_t iSetting = 0; iSetting < 4; iSetting++) {
269 TString name("AliRoot.AliLog.Print");
270 name += settingNames[iSetting];
271 if (gEnv->Defined(name)) {
272 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
273 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
274 settings[iSetting][iType] = on;
276 AliDebug(3, Form("printing of %s %sabled for all types",
277 settingNames[iSetting], ((on) ? "en" : "dis")));
280 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
281 TString nameType = name + "." + &typeNames[iType][1];
282 if (gEnv->Defined(nameType)) {
283 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
284 settings[iSetting][iType] = on;
285 AliDebug(3, Form("printing of %s %sabled for type %s",
286 settingNames[iSetting], ((on) ? "en" : "dis"),
292 // repetition of messages
293 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions")) {
294 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
295 fPrintRepetitions = on;
296 AliDebug(3, Form("printing of message repetitions %sabled",
297 ((on) ? "en" : "dis")));
302 //_____________________________________________________________________________
303 void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
304 const char* location, const char* message)
306 // new error handler for messages from root
309 case ::kFatal : level = kFatal; break;
311 DefaultErrorHandler(level, abort, location, message);
314 DefaultErrorHandler(level, abort, location, message);
316 case ::kError : level = kError; break;
317 case ::kWarning : level = kWarning; break;
318 case ::kInfo : level = kInfo; break;
319 default : level = kDebug; break;
321 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
325 //_____________________________________________________________________________
326 void AliLog::EnableDebug(Bool_t enabled)
328 // enable or disable debug output
330 fgDebugEnabled = enabled;
333 //_____________________________________________________________________________
334 void AliLog::SetGlobalLogLevel(EType_t type)
336 // set the global debug level
338 if (!fgInstance) new AliLog;
339 fgInstance->fGlobalLogLevel = type;
342 //_____________________________________________________________________________
343 Int_t AliLog::GetGlobalLogLevel()
345 // get the global debug level
347 if (!fgInstance) new AliLog;
348 return fgInstance->fGlobalLogLevel;
351 //_____________________________________________________________________________
352 void AliLog::SetGlobalDebugLevel(Int_t level)
354 // set the global debug level
356 if (!fgInstance) new AliLog;
357 if (level < -kDebugOffset) level = -kDebugOffset;
358 fgInstance->fGlobalLogLevel = kDebugOffset + level;
361 //_____________________________________________________________________________
362 Int_t AliLog::GetGlobalDebugLevel()
364 // get the global debug level
366 if (!fgInstance) new AliLog;
367 return fgInstance->fGlobalLogLevel - kDebugOffset;
370 //_____________________________________________________________________________
371 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
373 // set the debug level for the given module
376 if (!fgInstance) new AliLog;
377 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
379 obj = new TNamed(module, module);
380 fgInstance->fModuleDebugLevels.Add(obj);
382 level += kDebugOffset;
383 if (level < kFatal) level = kFatal;
384 obj->SetUniqueID(level);
387 //_____________________________________________________________________________
388 void AliLog::ClearModuleDebugLevel(const char* module)
390 // remove the setting of the debug level for the given module
393 if (!fgInstance) new AliLog;
394 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
395 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
398 //_____________________________________________________________________________
399 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
401 // set the debug level for the given class
403 if (!className) return;
404 if (!fgInstance) new AliLog;
405 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
407 obj = new TNamed(className, className);
408 fgInstance->fClassDebugLevels.Add(obj);
410 level += kDebugOffset;
411 if (level < kFatal) level = kFatal;
412 obj->SetUniqueID(level);
415 //_____________________________________________________________________________
416 void AliLog::ClearClassDebugLevel(const char* className)
418 // remove the setting of the debug level for the given class
420 if (!className) return;
421 if (!fgInstance) new AliLog;
422 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
423 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
427 //_____________________________________________________________________________
428 void AliLog::SetStandardOutput()
430 // write all log messages to the standard output (stdout)
432 if (!fgInstance) new AliLog;
433 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
434 fgInstance->CloseFile(iType);
435 fgInstance->fOutputTypes[iType] = 0;
439 //_____________________________________________________________________________
440 void AliLog::SetStandardOutput(EType_t type)
442 // write log messages of the given type to the standard output (stdout)
444 if ((type < kFatal) || (type >= kMaxType)) return;
445 if (!fgInstance) new AliLog;
446 fgInstance->CloseFile(type);
447 fgInstance->fOutputTypes[type] = 0;
450 //_____________________________________________________________________________
451 void AliLog::SetErrorOutput()
453 // write all log messages to the error output (stderr)
455 if (!fgInstance) new AliLog;
456 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
457 fgInstance->CloseFile(iType);
458 fgInstance->fOutputTypes[iType] = 1;
462 //_____________________________________________________________________________
463 void AliLog::SetErrorOutput(EType_t type)
465 // write log messages of the given type to the error output (stderr)
467 if ((type < kFatal) || (type >= kMaxType)) return;
468 if (!fgInstance) new AliLog;
469 fgInstance->CloseFile(type);
470 fgInstance->fOutputTypes[type] = 1;
473 //_____________________________________________________________________________
474 void AliLog::SetFileOutput(const char* fileName)
476 // write all log messages to the given file
478 if (!fgInstance) new AliLog;
479 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
480 if ((fgInstance->fOutputTypes[iType] == 2) &&
481 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
482 fgInstance->CloseFile(iType);
484 fgInstance->fOutputTypes[iType] = 2;
485 fgInstance->fFileNames[iType] = fileName;
486 fgInstance->fOutputFiles[iType] = NULL;
487 fgInstance->fOutputStreams[iType] = NULL;
491 //_____________________________________________________________________________
492 void AliLog::SetFileOutput(EType_t type, const char* fileName)
494 // write log messages of the given type to the given file
496 if ((type < kFatal) || (type >= kMaxType)) return;
497 if (!fgInstance) new AliLog;
498 if ((fgInstance->fOutputTypes[type] == 2) &&
499 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
500 fgInstance->CloseFile(type);
502 fgInstance->fOutputTypes[type] = 2;
503 fgInstance->fFileNames[type] = fileName;
504 fgInstance->fOutputFiles[type] = NULL;
505 fgInstance->fOutputStreams[type] = NULL;
508 //_____________________________________________________________________________
509 void AliLog::CloseFile(Int_t type)
511 // close the file for the given type if needed
513 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
514 Bool_t closeFile = kTRUE;
515 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
516 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
521 fclose(fOutputFiles[type]);
522 ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
524 delete fOutputStreams[type];
527 fOutputFiles[type] = NULL;
528 fOutputStreams[type] = NULL;
529 fFileNames[type] = "";
530 fOutputTypes[type] = 0;
533 //_____________________________________________________________________________
534 FILE* AliLog::GetOutputStream(Int_t type)
536 // get the output stream for the given type of messages
538 if (type > kDebug) type = kDebug;
539 if (fOutputTypes[type] == 0) return stdout;
540 else if (fOutputTypes[type] == 1) return stderr;
541 else if (fOutputTypes[type] == 2) {
542 if (!fOutputFiles[type]) {
544 ostream* stream = NULL;
545 if (!fFileNames[type].IsNull()) {
546 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
547 if ((iType != type) &&
548 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
549 fOutputFiles[iType]) {
550 file = fOutputFiles[iType];
551 stream = fOutputStreams[iType];
556 file = fopen(fFileNames[type], "a");
557 stream = new ofstream(fFileNames[type], ios::app);
560 fOutputFiles[type] = file;
561 fOutputStreams[type] = stream;
562 if (!file) CloseFile(type);
564 if (fOutputFiles[type]) return fOutputFiles[type];
570 //_____________________________________________________________________________
573 // flush the output streams
575 if (!fgInstance) new AliLog;
576 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
577 if (fgInstance->fOutputFiles[iType]) {
578 fflush(fgInstance->fOutputFiles[iType]);
579 fgInstance->fOutputStreams[iType]->flush();
587 //_____________________________________________________________________________
588 void AliLog::SetHandleRootMessages(Bool_t on)
590 // enable or disable the handling of messages form root
592 if (!fgInstance) new AliLog;
594 SetErrorHandler(RootErrorHandler);
596 SetErrorHandler(DefaultErrorHandler);
601 //_____________________________________________________________________________
602 void AliLog::SetPrintType(Bool_t on)
604 // switch on or off the printing of the message type for all message types
606 if (!fgInstance) new AliLog;
607 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
608 fgInstance->fPrintType[iType] = on;
612 //_____________________________________________________________________________
613 void AliLog::SetPrintType(EType_t type, Bool_t on)
615 // switch on or off the printing of the message type for the given message type
617 if ((type < kFatal) || (type >= kMaxType)) return;
618 if (!fgInstance) new AliLog;
619 fgInstance->fPrintType[type] = on;
622 //_____________________________________________________________________________
623 void AliLog::SetPrintModule(Bool_t on)
625 // switch on or off the printing of the module for all message types
627 if (!fgInstance) new AliLog;
628 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
629 fgInstance->fPrintModule[iType] = on;
633 //_____________________________________________________________________________
634 void AliLog::SetPrintModule(EType_t type, Bool_t on)
636 // switch on or off the printing of the module for the given message type
638 if ((type < kFatal) || (type >= kMaxType)) return;
639 if (!fgInstance) new AliLog;
640 fgInstance->fPrintModule[type] = on;
643 //_____________________________________________________________________________
644 void AliLog::SetPrintScope(Bool_t on)
646 // switch on or off the printing of the scope/class name for all message types
648 if (!fgInstance) new AliLog;
649 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
650 fgInstance->fPrintScope[iType] = on;
654 //_____________________________________________________________________________
655 void AliLog::SetPrintScope(EType_t type, Bool_t on)
657 // switch on or off the printing of the scope/class name
658 // for the given message type
660 if ((type < kFatal) || (type >= kMaxType)) return;
661 if (!fgInstance) new AliLog;
662 fgInstance->fPrintScope[type] = on;
665 //_____________________________________________________________________________
666 void AliLog::SetPrintLocation(Bool_t on)
668 // switch on or off the printing of the file name and line number
669 // for all message types
671 if (!fgInstance) new AliLog;
672 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
673 fgInstance->fPrintLocation[iType] = on;
677 //_____________________________________________________________________________
678 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
680 // switch on or off the printing of the file name and line number
681 // for the given message type
683 if ((type < kFatal) || (type >= kMaxType)) return;
684 if (!fgInstance) new AliLog;
685 fgInstance->fPrintLocation[type] = on;
689 //_____________________________________________________________________________
690 void AliLog::SetPrintRepetitions(Bool_t on)
692 // switch on or off the printing of the number of repetitions of a message
693 // instead of repeating the same message
695 if (!fgInstance) new AliLog;
696 if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
697 fgInstance->fPrintRepetitions = on;
701 //_____________________________________________________________________________
702 void AliLog::WriteToFile(const char* name, Int_t option)
704 // write the log object with the given name and option to the current file
706 if (!fgInstance) new AliLog;
707 fgInstance->TObject::Write(name, option);
711 //_____________________________________________________________________________
712 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
714 // get the logging level for the given module and class
716 if (!fgInstance) new AliLog;
718 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
719 if (obj) return obj->GetUniqueID();
722 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
723 if (obj) return obj->GetUniqueID();
725 return fgInstance->fGlobalLogLevel;
728 //_____________________________________________________________________________
729 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
731 // get the debug level for the given module and class
733 if (!fgInstance) new AliLog;
734 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
737 //_____________________________________________________________________________
738 void AliLog::PrintMessage(UInt_t type, const char* message,
739 const char* module, const char* className,
740 const char* function, const char* file, Int_t line)
742 // print the given message
744 // don't print the message if it is repeated
745 if (fPrintRepetitions &&
746 (fLastType == type) &&
747 (message && (fLastMessage.CompareTo(message) == 0)) &&
748 ((module && (fLastModule.CompareTo(module) == 0)) ||
749 (!module && fLastModule.IsNull())) &&
750 ((className && (fLastClassName.CompareTo(className) == 0)) ||
751 (!className && fLastClassName.IsNull())) &&
752 ((function && (fLastFunction.CompareTo(function) == 0)) ||
753 (!function && fLastFunction.IsNull()))&&
754 ((file && (fLastFile.CompareTo(file) == 0)) ||
755 (!file && fLastFile.IsNull())) &&
756 (fLastLine == line)) {
761 // print number of repetitions
762 if (fRepetitions > 0) PrintRepetitions();
764 // remember this message
767 fLastMessage = message;
768 fLastModule = module;
769 fLastClassName = className;
770 fLastFunction = function;
775 FILE* stream = GetOutputStream(type);
776 static const char* typeNames[kMaxType] =
777 {"Fatal", "Error", "Warning", "Info", "Debug"};
779 if (fPrintType[type]) {
780 PrintString(type, stream, "%c-", typeNames[type][0]);
782 if (fPrintModule[type] && module) {
783 PrintString(type, stream, "%s/", module);
785 if (fPrintScope[type] && className) {
786 PrintString(type, stream, "%s::", className);
789 PrintString(type, stream, "%s: %s", function, message);
791 PrintString(type, stream, "%s", function);
793 if (fPrintLocation[type] && file) {
794 PrintString(type, stream, " (%s:%.0d)", file, line);
797 PrintString(type, stream, "\n");
799 PrintString(type, stream, ": ");
801 if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
804 //_____________________________________________________________________________
805 void AliLog::PrintRepetitions()
807 // print number of repetitions
809 PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
810 fRepetitions, (fRepetitions > 1) ? "s" : "");
811 if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
814 //_____________________________________________________________________________
815 void AliLog::Message(UInt_t level, const char* message,
816 const char* module, const char* className,
817 const char* function, const char* file, Int_t line)
819 // print a log message
821 if (!fgInstance) new AliLog;
823 // get the message type
825 if (type >= kMaxType) type = kMaxType - 1;
827 // print the message if the debug level allows
828 if (level <= fgInstance->GetLogLevel(module, className)) {
829 fgInstance->PrintMessage(type, message,
830 module, className, function, file, line);
833 // abort in case of a fatal message
834 if (type == kFatal) {
837 gSystem->StackTrace();
845 //_____________________________________________________________________________
846 void AliLog::Debug(UInt_t level, const char* message,
847 const char* module, const char* className,
848 const char* function, const char* file, Int_t line)
850 // print a debug message
852 if (level == 0) level = 1;
853 level += kDebugOffset;
854 Message(level, message, module, className, function, file, line);
858 //_____________________________________________________________________________
859 Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
860 const char* className, const char* function,
861 const char* file, Int_t line, Bool_t print)
863 // redirect the standard output to the stream of the given type
865 if (!fgInstance) new AliLog;
866 return fgInstance->RedirectTo(stdout, type, level, module, className,
867 function, file, line, print);
870 //_____________________________________________________________________________
871 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
872 const char* className, const char* function,
873 const char* file, Int_t line, Bool_t print)
875 // redirect the standard error output to the stream of the given type
877 if (!fgInstance) new AliLog;
878 return fgInstance->RedirectTo(stderr, type, level, module, className,
879 function, file, line, print);
882 //_____________________________________________________________________________
883 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
884 const char* module, const char* className,
885 const char* function, const char* file, Int_t line,
888 // redirect the standard (error) output stream to the stream of the given type
890 // get the original file descriptor to be able to restore it later
891 Int_t original = dup(fileno(stream));
894 // flush the stream of the selected type
895 FILE* newStream = GetOutputStream(type);
899 if ((type == kDebug) && (level > 0)) level--;
900 if (type + level > GetLogLevel(module, className)) { // /dev/null
901 freopen("/dev/null", "a", stream);
902 } else if (fOutputTypes[type] == 0) { // stdout
903 if (stream != stdout) dup2(fileno(stdout), fileno(stream));
904 } else if (fOutputTypes[type] == 1) { // stderr
905 if (stream != stderr) dup2(fileno(stderr), fileno(stream));
906 } else if (fOutputTypes[type] == 2) { // file
907 freopen(fFileNames[type], "a", stream);
908 } else if (fOutputTypes[type] == 3) { // external C++ stream
909 // redirection is not possible for external C++ streams
914 PrintMessage(type, NULL, module, className, function, file, line);
921 //_____________________________________________________________________________
922 void AliLog::RestoreStdout(Int_t original)
924 // restore the standard output
927 dup2(original, fileno(stdout));
931 //_____________________________________________________________________________
932 void AliLog::RestoreStderr(Int_t original)
934 // restore the standard error output
937 dup2(original, fileno(stderr));
942 //_____________________________________________________________________________
943 ostream& AliLog::Stream(EType_t type, UInt_t level,
944 const char* module, const char* className,
945 const char* function, const char* file, Int_t line)
947 // get the stream object for the given output type
949 if (!fgInstance) new AliLog;
950 return fgInstance->GetStream(type, level, module, className,
951 function, file, line);
954 //_____________________________________________________________________________
955 ostream& AliLog::GetStream(EType_t type, UInt_t level,
956 const char* module, const char* className,
957 const char* function, const char* file, Int_t line)
959 // get the stream object for the given output type
961 if ((type == kDebug) && (level > 0)) level--;
962 Bool_t noOutput = (type + level > GetLogLevel(module, className));
965 PrintMessage(type, NULL, module, className, function, file, line);
967 fflush(GetOutputStream(type));
969 static ofstream nullStream("/dev/null");
972 } else if (fOutputTypes[type] == 0) {
974 } else if (fOutputTypes[type] == 1) {
976 } else if (fOutputTypes[type] == 2) {
977 return *fOutputStreams[type];
978 } else if (fOutputTypes[type] == 3) {
979 return *fOutputStreams[type];
985 void AliLog::SetStreamOutput(ostream* stream)
987 // set an external stream as target for log messages of all types
988 // the external stream is completely handled by the caller, the
989 // AliLog class just writes to it
991 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
992 SetStreamOutput((AliLog::EType_t)iType, stream);
996 void AliLog::SetStreamOutput(EType_t type, ostream* stream)
998 // set an external stream as target for log messages of the given type
999 // the external stream is completely handled by the caller, the
1000 // AliLog class just writes to it
1002 if ((type < kFatal) || (type >= kMaxType)) return;
1003 if (!fgInstance) new AliLog;
1004 if (fgInstance->fOutputTypes[type] == 2) {
1005 fgInstance->CloseFile(type);
1007 fgInstance->fOutputTypes[type] = 3;
1008 fgInstance->fFileNames[type] = "";
1009 fgInstance->fOutputFiles[type] = NULL;
1010 fgInstance->fOutputStreams[type] = stream;
1013 void AliLog::SetLogNotification(AliLogNotification pCallBack)
1015 // set a notification callback function for log messages of all types
1017 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1018 SetLogNotification((AliLog::EType_t)iType, pCallBack);
1022 void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
1024 // set a notifications call back function for log messages of all types
1025 // the callback fuction is invoced whenever an output was written
1026 // Note: does not work for c++ streamer classes, the external stream
1027 // has to handle this diectly (e.g. custom implementation of endl)
1029 if ((type < kFatal) || (type >= kMaxType)) return;
1030 if (!fgInstance) new AliLog;
1031 fgInstance->fCallBacks[type]=pCallBack;
1034 void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1036 // this is the general method to print a log message using variadac args
1037 // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1039 // Only in case of an external c++ ostream type output, the message is
1040 // written to that stream and the notifictaion callback is called.
1041 // The message is printed by a normal vfprintf function otherwise
1043 if (format==NULL) return;
1046 va_start(ap, format);
1047 if (fOutputTypes[type] != 3) {
1049 vfprintf(stream, format, ap);
1052 // build the string and write everthing to the corresponding ostream
1053 TString fmt(format);
1054 TArrayC tgt(fmt.Length()*10); // just take a number
1057 R__VA_COPY(bap, ap);
1062 iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1064 iResult=tgt.GetSize()*2;
1065 } else if (iResult<tgt.GetSize()) {
1069 if (iResult<10000) {
1072 R__VA_COPY(ap, bap);
1076 tgt[tgt.GetSize()-1]=0;
1084 if (fOutputStreams[type]) {
1085 *(fOutputStreams[type]) << tgt.GetArray();