AliRoot Core  edcc906 (edcc906)
AliLog.cxx
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  * *
4  * Author: The ALICE Off-line Project. *
5  * Contributors are mentioned in the code where appropriate. *
6  * *
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  **************************************************************************/
15 
16 /* $Id$ */
17 
19 // //
20 // class for logging debug, info and error messages //
21 // //
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 //
24 // methods. //
25 // //
26 // It also handles the messages produces by the preprocessor macros defined //
27 // in the header file: AliDebug, AliInfo, AliWarning, AliError, AliFatal. //
28 // //
29 // More details about the message logging can be found on the ALICE Offline //
30 // web page. //
31 // //
33 
34 #include <cstdlib>
35 #include <strings.h>
36 #include <Riostream.h>
37 #include <TError.h>
38 #include <TNamed.h>
39 #include <TSystem.h>
40 #include <TEnv.h>
41 #include <TArrayC.h>
42 #include <Varargs.h> // platform independent definition of va_copy
43 
44 #include "AliLog.h"
45 // STD
46 #include <iostream>
47 #include <algorithm>
48 #include <sstream>
49 #include <stdexcept>
50 #include <functional>
51 
52 
53 
54 using std::endl;
55 using std::cout;
56 using std::ostream;
57 using std::cerr;
58 using std::ofstream;
59 using std::ios;
60 ClassImp(AliLog)
61 
62 // implementation of a singleton here
63 AliLog* AliLog::fgInstance = NULL;
64 
65 Bool_t AliLog::fgDebugEnabled = kTRUE;
66 Bool_t AliLog::fgCoreEnabled = kFALSE;
67 
71 AliLog *AliLog::GetRootLogger()
72 {
73  if (fgInstance == NULL)
74  {
75  // creating singleton
76  fgInstance = new AliLog;
77  }
78 
79  return fgInstance;
80 }
81 
86 {
87  if (fgInstance != NULL)
88  {
89  delete fgInstance;
90  fgInstance = NULL;
91  }
92 }
93 
98  TObject(),
102  fPrintRepetitions(kTRUE),
103  fRepetitions(0),
104  fLastType(0),
105  fLastMessage(),
106  fLastModule(),
107  fLastClassName(),
108  fLastFunction(),
109  fLastFile(),
110  fLastLine(0)
111 {
112 // default constructor: set default values
113 
114  for (Int_t iType = kFatal; iType < kMaxType; iType++)
115  {
116  fOutputTypes[iType] = 0;
117  fFileNames[iType] = "";
118  fOutputFiles[iType] = NULL;
119  fOutputStreams[iType] = NULL;
120  fCallBacks[iType]=NULL;
121 
122  fPrintType[iType] = kTRUE;
123  fPrintModule[iType] = kFALSE;
124  fPrintScope[iType] = kTRUE;
125  fPrintLocation[iType] = (iType == kDebug);
126  }
127 
128  // TO BE REVIEWED
129  // replace the previous instance by this one
130  if (fgInstance) delete fgInstance;
131  fgInstance = this;
132 
133  SetHandleRootMessages(kTRUE);
134 
135  // read the .rootrc settings
136  ReadEnvSettings();
137 }
138 
143 {
144 // destructor: clean up and reset instance pointer
145 
146  if (fRepetitions > 0) PrintRepetitions();
147 
148  for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
149  {
150  if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
151  }
152 
153  fClassDebugLevels.Delete();
154 
155  for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
156  {
157  if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
158  }
159 
160  fClassDebugLevels.Delete();
161 
162  for (Int_t iType = kFatal; iType < kMaxType; iType++)
163  {
164  CloseFile(iType);
165  }
166 
167  fflush(stderr);
168  fflush(stdout);
169 
170  fgInstance = NULL;
171 }
172 
173 // NOT IMPLEMENTED!?
174 //_____________________________________________________________________________
175 AliLog::AliLog(const AliLog& log) :
176  TObject(log),
182  fLastType(log.fLastType),
187  fLastFile(log.fLastFile),
188  fLastLine(log.fLastLine)
189 {
190 // copy constructor
191 
192  Fatal("AliLog", "copy constructor not implemented");
193 }
194 
195 // NOT IMPLEMENTED!?
196 //_____________________________________________________________________________
198 {
199 // assignment operator
200 
201  Fatal("operator =", "assignment operator not implemented");
202  return *this;
203 }
204 
205 
214 //_____________________________________________________________________________
216 {
217 // load settings from the root configuration file (.rootrc)
218 // and from environment variables
219 
220  static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
221 
222  // debug en- or disabling
223  if (gSystem->Getenv("LOG_NO_DEBUG"))
224  {
225  fgDebugEnabled = kFALSE;
226  }
227  else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
228  {
229  fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
230  AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
231  }
232 
233  // global log level
234  if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
235  {
236  const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
237 
238  for (Int_t iType = kFatal; iType < kMaxType; iType++)
239  {
240  if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
241  }
242 
243  AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
244  }
245 
246  // global debug level
247  if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
248  {
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));
253  }
254 
255  // module debug level
256  if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
257  {
258  TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
259  char* p = const_cast<char*>(levels.Data());
260 
261  while (const char* module = strtok(p, " "))
262  {
263  p = NULL;
264  char* pos = const_cast<char*>(index(module, ':'));
265  if (!pos) continue;
266  *(pos++) = '\0';
267  Int_t level = atoi(pos);
268  SetModuleDebugLevel(module, level);
269  AliDebug(3, Form("debug level for module %s set to %d", module, level));
270  }
271  }
272 
273  // class debug level
274  if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
275  {
276  TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
277  char* p = const_cast<char*>(levels.Data());
278 
279  while (const char* className = strtok(p, " "))
280  {
281  p = NULL;
282  char* pos = const_cast<char*>(index(className, ':'));
283  if (!pos) continue;
284  *(pos++) = '\0';
285  Int_t level = atoi(pos);
286  SetClassDebugLevel(className, level);
287  AliDebug(3, Form("debug level for class %s set to %d", className, level));
288  }
289  }
290 
291  // general output stream
292  if (gEnv->Defined("AliRoot.AliLog.Output"))
293  {
294  TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
295 
296  if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
297  {
299  AliDebug(3, "output stream set to standard output for all types");
300  }
301  else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
302  {
303  SetErrorOutput();
304  AliDebug(3, "output stream set to error output for all types");
305  }
306  else if (!stream.IsNull())
307  {
308  SetFileOutput(stream);
309  AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
310  }
311  }
312 
313  // individual output streams
314  for (Int_t iType = kFatal; iType < kMaxType; iType++)
315  {
316  TString name("AliRoot.AliLog.Output.");
317  name += &typeNames[iType][1];
318 
319  if (gEnv->Defined(name))
320  {
321  TString stream = gEnv->GetValue(name, "Standard");
322 
323  if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
324  {
325  SetStandardOutput(EType_t(iType));
326  AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
327  }
328  else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
329  {
330  SetErrorOutput(EType_t(iType));
331  AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
332  }
333  else if (!stream.IsNull())
334  {
335  SetFileOutput(EType_t(iType), stream);
336  AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
337  }
338  }
339  }
340 
341  // handling of root error messages
342  if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
343  {
344  Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
346  AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
347  }
348 
349  // printout settings
350  static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
351  Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
352 
353  for (Int_t iSetting = 0; iSetting < 4; iSetting++)
354  {
355  TString name("AliRoot.AliLog.Print");
356  name += settingNames[iSetting];
357 
358  if (gEnv->Defined(name))
359  {
360  Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
361 
362  for (Int_t iType = kFatal; iType < kMaxType; iType++)
363  {
364  settings[iSetting][iType] = on;
365  }
366  AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
367  }
368 
369  for (Int_t iType = kFatal; iType < kMaxType; iType++)
370  {
371  TString nameType = name + "." + &typeNames[iType][1];
372 
373  if (gEnv->Defined(nameType))
374  {
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]));
378  }
379  }
380  }
381 
382  // repetition of messages
383  if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
384  {
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")));
388  }
389  if (gSystem->Getenv("ALIROOT_FORCE_COREDUMP")){
390  EnableCoreDump(kTRUE);
391  }
392 
393 }
394 
395 
396 //_____________________________________________________________________________
397 void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
398  const char* location, const char* message)
399 {
400 // new error handler for messages from root
401 
402  switch (level)
403  {
404  case ::kFatal : level = kFatal; break;
405  case ::kSysError :
406  DefaultErrorHandler(level, abort, location, message);
407  return;
408  case ::kBreak :
409  DefaultErrorHandler(level, abort, location, message);
410  return;
411  case ::kError : level = kError; break;
412  case ::kWarning : level = kWarning; break;
413  case ::kInfo : level = kInfo; break;
414  default : level = kDebug; break;
415  }
416  AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
417 }
418 
419 
420 // DEPRECATED: USE A CONFIGURATION FILE INSTEAD
421 //_____________________________________________________________________________
422 void AliLog::EnableDebug(Bool_t enabled)
423 {
424 // enable or disable debug output
425 
426  fgDebugEnabled = enabled;
427 }
428 
429 void AliLog::EnableCoreDump(Bool_t enabled)
430 {
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);
436  if (enabled) {
437  printf("Core dump enabled\n");
438  }
439  else {
440  printf("Core dump disabled\n");
441  }
442 }
443 
444 
445 
446 //_____________________________________________________________________________
448 {
449 // set the global debug level
450 
451  // TO BE DELETED
452  if (!fgInstance) new AliLog;
453  fgInstance->fGlobalLogLevel = type;
454 }
455 
456 //_____________________________________________________________________________
458 {
459 // get the global debug level
460 
461  if (!fgInstance) new AliLog;
462  return fgInstance->fGlobalLogLevel;
463 }
464 
465 //_____________________________________________________________________________
467 {
468 // set the global debug level
469 
470  if (!fgInstance) new AliLog;
471  if (level < -kDebugOffset) level = -kDebugOffset;
473 }
474 
475 //_____________________________________________________________________________
477 {
478 // get the global debug level
479 
480  if (!fgInstance) new AliLog;
482 }
483 
484 //_____________________________________________________________________________
485 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
486 {
487 // set the debug level for the given module
488 
489  if (!module) return;
490  if (!fgInstance) new AliLog;
491  TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
492  if (!obj) {
493  obj = new TNamed(module, module);
494  fgInstance->fModuleDebugLevels.Add(obj);
495  }
496  level += kDebugOffset;
497  if (level < kFatal) level = kFatal;
498  obj->SetUniqueID(level);
499 }
500 
501 //_____________________________________________________________________________
502 void AliLog::ClearModuleDebugLevel(const char* module)
503 {
504 // remove the setting of the debug level for the given module
505 
506  if (!module) return;
507  if (!fgInstance) new AliLog;
508  TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
509  if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
510 }
511 
512 //_____________________________________________________________________________
513 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
514 {
515 // set the debug level for the given class
516 
517  if (!className) return;
518  if (!fgInstance) new AliLog;
519  TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
520  if (!obj) {
521  obj = new TNamed(className, className);
522  fgInstance->fClassDebugLevels.Add(obj);
523  }
524  level += kDebugOffset;
525  if (level < kFatal) level = kFatal;
526  obj->SetUniqueID(level);
527 }
528 
529 //_____________________________________________________________________________
530 void AliLog::ClearClassDebugLevel(const char* className)
531 {
532 // remove the setting of the debug level for the given class
533 
534  if (!className) return;
535  if (!fgInstance) new AliLog;
536  TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
537  if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
538 }
539 
540 
541 //_____________________________________________________________________________
543 {
544 // write all log messages to the standard output (stdout)
545 
546  if (!fgInstance) new AliLog;
547  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
548  fgInstance->CloseFile(iType);
549  fgInstance->fOutputTypes[iType] = 0;
550  }
551 }
552 
553 //_____________________________________________________________________________
555 {
556 // write log messages of the given type to the standard output (stdout)
557 
558  if ((type < kFatal) || (type >= kMaxType)) return;
559  if (!fgInstance) new AliLog;
560  fgInstance->CloseFile(type);
561  fgInstance->fOutputTypes[type] = 0;
562 }
563 
564 //_____________________________________________________________________________
566 {
567 // write all log messages to the error output (stderr)
568 
569  if (!fgInstance) new AliLog;
570  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
571  fgInstance->CloseFile(iType);
572  fgInstance->fOutputTypes[iType] = 1;
573  }
574 }
575 
576 //_____________________________________________________________________________
578 {
579 // write log messages of the given type to the error output (stderr)
580 
581  if ((type < kFatal) || (type >= kMaxType)) return;
582  if (!fgInstance) new AliLog;
583  fgInstance->CloseFile(type);
584  fgInstance->fOutputTypes[type] = 1;
585 }
586 
587 //_____________________________________________________________________________
589 {
590 // write all log messages to the given file
591 
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);
597  }
598  fgInstance->fOutputTypes[iType] = 2;
599  fgInstance->fFileNames[iType] = fileName;
600  fgInstance->fOutputFiles[iType] = NULL;
601  fgInstance->fOutputStreams[iType] = NULL;
602  }
603 }
604 
605 //_____________________________________________________________________________
606 void AliLog::SetFileOutput(EType_t type, const char* fileName)
607 {
608 // write log messages of the given type to the given file
609 
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);
615  }
616  fgInstance->fOutputTypes[type] = 2;
617  fgInstance->fFileNames[type] = fileName;
618  fgInstance->fOutputFiles[type] = NULL;
619  fgInstance->fOutputStreams[type] = NULL;
620 }
621 
622 //_____________________________________________________________________________
623 void AliLog::CloseFile(Int_t type)
624 {
625 // close the file for the given type if needed
626 
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])) {
631  closeFile = kFALSE;
632  }
633  }
634  if (closeFile) {
635  fclose(fOutputFiles[type]);
636  ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
637  stream->close();
638  delete fOutputStreams[type];
639  }
640  }
641  fOutputFiles[type] = NULL;
642  fOutputStreams[type] = NULL;
643  fFileNames[type] = "";
644  fOutputTypes[type] = 0;
645 }
646 
647 //_____________________________________________________________________________
648 FILE* AliLog::GetOutputStream(Int_t type)
649 {
650 // get the output stream for the given type of messages
651 
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]) {
657  FILE* file = NULL;
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];
666  break;
667  }
668  }
669  if (!file) {
670  file = fopen(fFileNames[type], "a");
671  stream = new ofstream(fFileNames[type], ios::app);
672  }
673  }
674  fOutputFiles[type] = file;
675  fOutputStreams[type] = stream;
676  if (!file) CloseFile(type);
677  }
678  if (fOutputFiles[type]) return fOutputFiles[type];
679  }
680 
681  return stdout;
682 }
683 
684 //_____________________________________________________________________________
686 {
687 // flush the output streams
688 
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();
694  }
695  }
696  fflush(stderr);
697  fflush(stdout);
698 }
699 
700 
701 //_____________________________________________________________________________
703 {
704 // enable or disable the handling of messages form root
705 
706  if (!fgInstance) new AliLog;
707  if (on) {
708  SetErrorHandler(RootErrorHandler);
709  } else {
710  SetErrorHandler(DefaultErrorHandler);
711  }
712 }
713 
714 
715 //_____________________________________________________________________________
716 void AliLog::SetPrintType(Bool_t on)
717 {
718 // switch on or off the printing of the message type for all message types
719 
720  if (!fgInstance) new AliLog;
721  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
722  fgInstance->fPrintType[iType] = on;
723  }
724 }
725 
726 //_____________________________________________________________________________
727 void AliLog::SetPrintType(EType_t type, Bool_t on)
728 {
729 // switch on or off the printing of the message type for the given message type
730 
731  if ((type < kFatal) || (type >= kMaxType)) return;
732  if (!fgInstance) new AliLog;
733  fgInstance->fPrintType[type] = on;
734 }
735 
736 //_____________________________________________________________________________
737 void AliLog::SetPrintModule(Bool_t on)
738 {
739 // switch on or off the printing of the module for all message types
740 
741  if (!fgInstance) new AliLog;
742  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
743  fgInstance->fPrintModule[iType] = on;
744  }
745 }
746 
747 //_____________________________________________________________________________
748 void AliLog::SetPrintModule(EType_t type, Bool_t on)
749 {
750 // switch on or off the printing of the module for the given message type
751 
752  if ((type < kFatal) || (type >= kMaxType)) return;
753  if (!fgInstance) new AliLog;
754  fgInstance->fPrintModule[type] = on;
755 }
756 
757 //_____________________________________________________________________________
758 void AliLog::SetPrintScope(Bool_t on)
759 {
760 // switch on or off the printing of the scope/class name for all message types
761 
762  if (!fgInstance) new AliLog;
763  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
764  fgInstance->fPrintScope[iType] = on;
765  }
766 }
767 
768 //_____________________________________________________________________________
769 void AliLog::SetPrintScope(EType_t type, Bool_t on)
770 {
771 // switch on or off the printing of the scope/class name
772 // for the given message type
773 
774  if ((type < kFatal) || (type >= kMaxType)) return;
775  if (!fgInstance) new AliLog;
776  fgInstance->fPrintScope[type] = on;
777 }
778 
779 //_____________________________________________________________________________
781 {
782 // switch on or off the printing of the file name and line number
783 // for all message types
784 
785  if (!fgInstance) new AliLog;
786  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
787  fgInstance->fPrintLocation[iType] = on;
788  }
789 }
790 
791 //_____________________________________________________________________________
792 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
793 {
794 // switch on or off the printing of the file name and line number
795 // for the given message type
796 
797  if ((type < kFatal) || (type >= kMaxType)) return;
798  if (!fgInstance) new AliLog;
799  fgInstance->fPrintLocation[type] = on;
800 }
801 
802 
803 //_____________________________________________________________________________
805 {
806 // switch on or off the printing of the number of repetitions of a message
807 // instead of repeating the same message
808 
809  if (!fgInstance) new AliLog;
810  if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
812 }
813 
814 
815 //_____________________________________________________________________________
816 void AliLog::WriteToFile(const char* name, Int_t option)
817 {
818 // write the log object with the given name and option to the current file
819 
820  if (!fgInstance) new AliLog;
821  fgInstance->TObject::Write(name, option);
822 }
823 
824 
825 //_____________________________________________________________________________
826 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
827 {
828 // get the logging level for the given module and class
829 
830  if (!fgInstance) new AliLog;
831  if (className) {
832  TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
833  if (obj) return obj->GetUniqueID();
834  }
835  if (module) {
836  TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
837  if (obj) return obj->GetUniqueID();
838  }
839  return fgInstance->fGlobalLogLevel;
840 }
841 
842 //_____________________________________________________________________________
843 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
844 {
845 // get the debug level for the given module and class
846 
847  if (!fgInstance) new AliLog;
848  return fgInstance->GetLogLevel(module, className) - kDebugOffset;
849 }
850 
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)
855 {
856 // print the given message
857 
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)) {
871  fRepetitions++;
872  return;
873  }
874 
875  // print number of repetitions
876  if (fRepetitions > 0) PrintRepetitions();
877 
878  // remember this message
879  fRepetitions = 0;
880  fLastType = type;
881  fLastMessage = message;
882  fLastModule = module;
883  fLastClassName = className;
884  fLastFunction = function;
885  fLastFile = file;
886  fLastLine = line;
887 
888  // print the message
889  FILE* stream = GetOutputStream(type);
890  static const char* typeNames[kMaxType] =
891  {"Fatal", "Error", "Warning", "Info", "Debug"};
892 
893  if (fPrintType[type]) {
894  PrintString(type, stream, "%c-", typeNames[type][0]);
895  }
896  if (fPrintModule[type] && module) {
897  PrintString(type, stream, "%s/", module);
898  }
899  if (fPrintScope[type] && className) {
900  PrintString(type, stream, "%s::", className);
901  }
902  if (message) {
903  PrintString(type, stream, "%s: %s", function, message);
904  } else {
905  PrintString(type, stream, "%s", function);
906  }
907  if (fPrintLocation[type] && file) {
908  PrintString(type, stream, " (%s:%.0d)", file, line);
909  }
910  if (message) {
911  PrintString(type, stream, "\n");
912  } else {
913  PrintString(type, stream, ": ");
914  }
915  if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
916 }
917 
918 //_____________________________________________________________________________
920 {
921 // print number of repetitions
922 
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);
926 }
927 
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)
932 {
933 // print a log message
934 
935  if (!fgInstance) new AliLog;
936 
937  // get the message type
938  UInt_t type = level;
939  if (type >= kMaxType) type = kMaxType - 1;
940 
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);
945  }
946 
947  // abort in case of a fatal message
948  if (type == kFatal) {
949  fgInstance->PrintMessage(type, "aborting execution due to AliFatal",
950  module, className, function, file, line);
951  delete fgInstance;
952  if (gSystem) {
953  gSystem->StackTrace();
954  if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
955  gSystem->Abort();
956  } else {
957  if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
958  ::abort();
959  }
960  }
961 }
962 
963 
964 
965 //_____________________________________________________________________________
966 void AliLog::Debug(UInt_t level, const char* message,
967  const char* module, const char* className,
968  const char* function, const char* file, Int_t line)
969 {
970 // print a debug message
971 
972  if (level == 0) level = 1;
973  level += kDebugOffset;
974  Message(level, message, module, className, function, file, line);
975 }
976 
977 
978 //_____________________________________________________________________________
979 Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
980  const char* className, const char* function,
981  const char* file, Int_t line, Bool_t print)
982 {
983 // redirect the standard output to the stream of the given type
984 
985  if (!fgInstance) new AliLog;
986  return fgInstance->RedirectTo(stdout, type, level, module, className,
987  function, file, line, print);
988 }
989 
990 //_____________________________________________________________________________
991 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
992  const char* className, const char* function,
993  const char* file, Int_t line, Bool_t print)
994 {
995 // redirect the standard error output to the stream of the given type
996 
997  if (!fgInstance) new AliLog;
998  return fgInstance->RedirectTo(stderr, type, level, module, className,
999  function, file, line, print);
1000 }
1001 
1002 //_____________________________________________________________________________
1003 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
1004  const char* module, const char* className,
1005  const char* function, const char* file, Int_t line,
1006  Bool_t print)
1007 {
1008 // redirect the standard (error) output stream to the stream of the given type
1009 
1010  // get the original file descriptor to be able to restore it later
1011  Int_t original = dup(fileno(stream));
1012  fflush(stream);
1013 
1014  // flush the stream of the selected type
1015  FILE* newStream = GetOutputStream(type);
1016  fflush(newStream);
1017 
1018  // redirect stream
1019  if ((type == kDebug) && (level > 0)) level--;
1020  if (type + level > GetLogLevel(module, className)) { // /dev/null
1021  if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
1022  } else if (fOutputTypes[type] == 0) { // stdout
1023  if (stream != stdout) dup2(fileno(stdout), fileno(stream));
1024  } else if (fOutputTypes[type] == 1) { // stderr
1025  if (stream != stderr) dup2(fileno(stderr), fileno(stream));
1026  } else if (fOutputTypes[type] == 2) { // file
1027  if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
1028  } else if (fOutputTypes[type] == 3) { // external C++ stream
1029  // redirection is not possible for external C++ streams
1030  }
1031 
1032  // print information
1033  if (print) {
1034  PrintMessage(type, NULL, module, className, function, file, line);
1035  fflush(newStream);
1036  }
1037 
1038  return original;
1039 }
1040 
1041 //_____________________________________________________________________________
1042 void AliLog::RestoreStdout(Int_t original)
1043 {
1044 // restore the standard output
1045 
1046  fflush(stdout);
1047  dup2(original, fileno(stdout));
1048  close(original);
1049 }
1050 
1051 //_____________________________________________________________________________
1052 void AliLog::RestoreStderr(Int_t original)
1053 {
1054 // restore the standard error output
1055 
1056  fflush(stderr);
1057  dup2(original, fileno(stderr));
1058  close(original);
1059 }
1060 
1061 
1062 //_____________________________________________________________________________
1063 ostream& AliLog::Stream(EType_t type, UInt_t level,
1064  const char* module, const char* className,
1065  const char* function, const char* file, Int_t line)
1066 {
1067 // get the stream object for the given output type
1068 
1069  if (!fgInstance) new AliLog;
1070  return fgInstance->GetStream(type, level, module, className,
1071  function, file, line);
1072 }
1073 
1074 //_____________________________________________________________________________
1075 ostream& AliLog::GetStream(EType_t type, UInt_t level,
1076  const char* module, const char* className,
1077  const char* function, const char* file, Int_t line)
1078 {
1079 // get the stream object for the given output type
1080 
1081  if ((type == kDebug) && (level > 0)) level--;
1082  Bool_t noOutput = (type + level > GetLogLevel(module, className));
1083 
1084  if (!noOutput) {
1085  PrintMessage(type, NULL, module, className, function, file, line);
1086  }
1087  fflush(GetOutputStream(type));
1088 
1089  static ofstream nullStream("/dev/null");
1090  if (noOutput) {
1091  return nullStream;
1092  } else if (fOutputTypes[type] == 0) {
1093  return cout;
1094  } else if (fOutputTypes[type] == 1) {
1095  return cerr;
1096  } else if (fOutputTypes[type] == 2) {
1097  return *fOutputStreams[type];
1098  } else if (fOutputTypes[type] == 3) {
1099  return *fOutputStreams[type];
1100  }
1101 
1102  return nullStream;
1103 }
1104 
1105 void AliLog::SetStreamOutput(ostream* stream)
1106 {
1107  // set an external stream as target for log messages of all types
1108  // the external stream is completely handled by the caller, the
1109  // AliLog class just writes to it
1110 
1111  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1112  SetStreamOutput((AliLog::EType_t)iType, stream);
1113  }
1114 }
1115 
1116 void AliLog::SetStreamOutput(EType_t type, ostream* stream)
1117 {
1118  // set an external stream as target for log messages of the given type
1119  // the external stream is completely handled by the caller, the
1120  // AliLog class just writes to it
1121 
1122  if ((type < kFatal) || (type >= kMaxType)) return;
1123  if (!fgInstance) new AliLog;
1124  if (fgInstance->fOutputTypes[type] == 2) {
1125  fgInstance->CloseFile(type);
1126  }
1127  fgInstance->fOutputTypes[type] = 3;
1128  fgInstance->fFileNames[type] = "";
1129  fgInstance->fOutputFiles[type] = NULL;
1130  fgInstance->fOutputStreams[type] = stream;
1131 }
1132 
1134 {
1135  // set a notification callback function for log messages of all types
1136 
1137  for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1138  SetLogNotification((AliLog::EType_t)iType, pCallBack);
1139  }
1140 }
1141 
1143 {
1144  // set a notifications call back function for log messages of all types
1145  // the callback fuction is invoced whenever an output was written
1146  // Note: does not work for c++ streamer classes, the external stream
1147  // has to handle this diectly (e.g. custom implementation of endl)
1148 
1149  if ((type < kFatal) || (type >= kMaxType)) return;
1150  if (!fgInstance) new AliLog;
1151  fgInstance->fCallBacks[type]=pCallBack;
1152 }
1153 
1154 void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1155 {
1156  // this is the general method to print a log message using variadac args
1157  // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1158  // opened by fopen.
1159  // Only in case of an external c++ ostream type output, the message is
1160  // written to that stream and the notifictaion callback is called.
1161  // The message is printed by a normal vfprintf function otherwise
1162 
1163  if (format==NULL) return;
1164 
1165  va_list ap;
1166  va_start(ap, format);
1167  if (fOutputTypes[type] != 3) {
1168  if (stream!=NULL) {
1169  vfprintf(stream, format, ap);
1170  }
1171  } else {
1172  // build the string and write everthing to the corresponding ostream
1173  TString fmt(format);
1174  TArrayC tgt(fmt.Length()*10); // just take a number
1175 #ifdef R__VA_COPY
1176  va_list bap;
1177  R__VA_COPY(bap, ap);
1178 #else
1179 #warning definition of R__VA_COPY has disappeared
1180 #endif //R__VA_COPY
1181 
1182  Int_t iResult=0;
1183  while (1) {
1184  iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1185  if (iResult==-1) {
1186  iResult=tgt.GetSize()*2;
1187  } else if (iResult<tgt.GetSize()) {
1188  break;
1189  }
1190 #ifdef R__VA_COPY
1191  if (iResult<10000) {
1192  tgt.Set(iResult+1);
1193  va_end(ap);
1194  R__VA_COPY(ap, bap);
1195  } else
1196 #endif //R__VA_COPY
1197  {
1198  tgt[tgt.GetSize()-1]=0;
1199  break;
1200  }
1201  }
1202 #ifdef R__VA_COPY
1203  va_end(bap);
1204 #endif //R__VA_COPY
1205 
1206  if (fOutputStreams[type]) {
1207  *(fOutputStreams[type]) << tgt.GetArray();
1208  }
1209  }
1210  va_end(ap);
1211 }
1212 
1213 
1214 void AliLog::MakeCoreDump(const char *fout){
1215  //
1216  // Functionality to make a program snapshot
1217  // gcore - Generate a core file for a running process
1218  // gcore dmake a current snapshot, program can continue further
1219  // We assum that gcore is installed
1220  // for details see: man gcore
1221  //
1222  // Example use - make default core file for current process: AliLog::MakeCoreDump(0)
1223  //
1224  //
1225  // Automatic core dump creation in case of the AliFatal can be specified using
1226  // static void EnableCoreDump(Bool_t enabled);
1227  // Core dump is created in addition to the stack trace ()
1228  // marian.ivanov@cern.ch
1229  //
1230  if (!gSystem) return;
1231  printf("AliLog::MakeCoreDump\n");
1232  if (fout){
1233  gSystem->Exec(Form("gcore -o %s %d",fout, gSystem->GetPid()));
1234  }else{
1235  gSystem->Exec(Form("gcore %d", gSystem->GetPid()));
1236  }
1237 }
1238 
1239 
1240 void AliLog::TestException(Int_t level){
1241  //
1242  // Dummy function to throw exception
1243  //
1244  printf("AliLog::TestException(%d)\n",level);
1245  if (level>0){
1246  level--;
1247  TestException(level);
1248  }else{
1249  throw std::runtime_error("Test exception");
1250  }
1251 }
AliLogNotification fCallBacks[kMaxType]
line number of last message
Definition: AliLog.h:179
TString fLastMessage
type of last message
Definition: AliLog.h:173
static void ClearModuleDebugLevel(const char *module)
Definition: AliLog.cxx:502
FILE * fOutputFiles[kMaxType]
Definition: AliLog.h:161
printf("Chi2/npoints = %f\n", TMath::Sqrt(chi2/npoints))
void(* AliLogNotification)(EType_t type, const char *message)
Definition: AliLog.h:33
void PrintString(Int_t type, FILE *stream, const char *format,...)
Definition: AliLog.cxx:1154
static void MakeCoreDump(const char *fout)
Definition: AliLog.cxx:1214
AliLog()
Definition: AliLog.cxx:97
static void SetGlobalLogLevel(EType_t type)
Definition: AliLog.cxx:447
TObjArray fClassDebugLevels
Definition: AliLog.h:157
static void SetClassDebugLevel(const char *className, Int_t level)
Definition: AliLog.cxx:513
static void RestoreStdout(Int_t original)
Definition: AliLog.cxx:1042
FILE * GetOutputStream(Int_t type)
Definition: AliLog.cxx:648
static void RootErrorHandler(Int_t level, Bool_t abort, const char *location, const char *message)
Definition: AliLog.cxx:397
Bool_t fPrintLocation[kMaxType]
Definition: AliLog.h:167
static void Message(UInt_t level, const char *message, const char *module, const char *className, const char *function, const char *file, Int_t line)
Definition: AliLog.cxx:929
static void SetFileOutput(const char *fileName)
Definition: AliLog.cxx:588
Int_t fOutputTypes[kMaxType]
Definition: AliLog.h:159
Float_t p[]
Definition: kNNTest.C:133
static void SetStreamOutput(ostream *stream)
Definition: AliLog.cxx:1105
static Bool_t fgDebugEnabled
pointer to current instance
Definition: AliLog.h:152
static void SetHandleRootMessages(Bool_t on)
Definition: AliLog.cxx:702
TString fLastFunction
class name of last message
Definition: AliLog.h:176
UInt_t fLastType
counter of repetitions
Definition: AliLog.h:172
TString fileName(const char *dir, int runNumber, const char *da, int i, const char *type)
#define AliWarning(message)
Definition: AliLog.h:541
static Bool_t fgCoreEnabled
Definition: AliLog.h:153
UInt_t fGlobalLogLevel
Definition: AliLog.h:155
ostream & GetStream(EType_t type, UInt_t level, const char *module, const char *className, const char *function, const char *file, Int_t line)
Definition: AliLog.cxx:1075
static void TestException(Int_t level=10)
Definition: AliLog.cxx:1240
static ostream & Stream(EType_t type, UInt_t level, const char *module, const char *className, const char *function, const char *file, Int_t line)
Definition: AliLog.cxx:1063
static AliLog * fgInstance
Definition: AliLog.h:151
static void SetLogNotification(AliLogNotification pCallBack)
Definition: AliLog.cxx:1133
static Int_t GetGlobalDebugLevel()
Definition: AliLog.cxx:476
virtual ~AliLog()
Definition: AliLog.cxx:142
static void WriteToFile(const char *name, Int_t option=0)
Definition: AliLog.cxx:816
AliLog & operator=(const AliLog &log)
Definition: AliLog.cxx:197
#define AliInfo(message)
Definition: AliLog.h:484
static Int_t RedirectStderrTo(EType_t type, UInt_t level, const char *module, const char *className, const char *function, const char *file, Int_t line, Bool_t print)
Definition: AliLog.cxx:991
Bool_t fPrintType[kMaxType]
log output streams
Definition: AliLog.h:164
Int_t fRepetitions
Definition: AliLog.h:171
TString fLastFile
function name of last message
Definition: AliLog.h:177
Bool_t fPrintModule[kMaxType]
Definition: AliLog.h:165
void ReadEnvSettings()
Definition: AliLog.cxx:215
Definition: AliLog.h:27
TFile * fout
Definition: PlotSys.C:39
static void SetModuleDebugLevel(const char *module, Int_t level)
Definition: AliLog.cxx:485
static void SetPrintModule(Bool_t on)
Definition: AliLog.cxx:737
static void SetPrintType(Bool_t on)
Definition: AliLog.cxx:716
static void EnableDebug(Bool_t enabled)
Definition: AliLog.cxx:422
static void Flush()
Definition: AliLog.cxx:685
#define AliDebug(logLevel, message)
Definition: AliLog.h:300
TString fLastModule
last message
Definition: AliLog.h:174
static void SetGlobalDebugLevel(Int_t level)
Definition: AliLog.cxx:466
EType_t
Definition: AliLog.h:32
static void Debug(UInt_t level, const char *message, const char *module, const char *className, const char *function, const char *file, Int_t line)
Definition: AliLog.cxx:966
TString fLastClassName
module name of last message
Definition: AliLog.h:175
Bool_t fPrintRepetitions
Definition: AliLog.h:169
static void SetPrintRepetitions(Bool_t on)
Definition: AliLog.cxx:804
static void SetPrintScope(Bool_t on)
Definition: AliLog.cxx:758
static Int_t RedirectStdoutTo(EType_t type, UInt_t level, const char *module, const char *className, const char *function, const char *file, Int_t line, Bool_t print)
Definition: AliLog.cxx:979
static Int_t GetDebugLevel(const char *module, const char *className)
Definition: AliLog.cxx:843
void PrintMessage(UInt_t type, const char *message, const char *module, const char *className, const char *function, const char *file, Int_t line)
Definition: AliLog.cxx:852
void PrintRepetitions()
Definition: AliLog.cxx:919
Int_t fLastLine
file name of last message
Definition: AliLog.h:178
ostream * fOutputStreams[kMaxType]
log output files
Definition: AliLog.h:162
static void ClearClassDebugLevel(const char *className)
Definition: AliLog.cxx:530
Int_t RedirectTo(FILE *stream, EType_t type, UInt_t level, const char *module, const char *className, const char *function, const char *file, Int_t line, Bool_t print)
Definition: AliLog.cxx:1003
static Int_t GetGlobalLogLevel()
Definition: AliLog.cxx:457
UInt_t GetLogLevel(const char *module, const char *className) const
Definition: AliLog.cxx:826
TString fFileNames[kMaxType]
Definition: AliLog.h:160
static void SetStandardOutput()
Definition: AliLog.cxx:542
static void SetPrintLocation(Bool_t on)
Definition: AliLog.cxx:780
void CloseFile(Int_t type)
Definition: AliLog.cxx:623
static void DeleteRootLogger()
Definition: AliLog.cxx:85
static void EnableCoreDump(Bool_t enabled)
Definition: AliLog.cxx:429
static void RestoreStderr(Int_t original)
Definition: AliLog.cxx:1052
static void SetErrorOutput()
Definition: AliLog.cxx:565
Bool_t fPrintScope[kMaxType]
Definition: AliLog.h:166
TObjArray fModuleDebugLevels
Definition: AliLog.h:156