logger.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "logger.h"
  2. #include <util/datetime/base.h>
  3. #include <util/stream/file.h>
  4. #include <util/stream/format.h>
  5. #include <util/stream/printf.h>
  6. #include <util/stream/str.h>
  7. #include <util/system/mutex.h>
  8. #include <util/system/rwlock.h>
  9. #include <util/system/thread.h>
  10. namespace NYT {
  11. ////////////////////////////////////////////////////////////////////////////////
  12. static TStringBuf StripFileName(TStringBuf path) {
  13. TStringBuf l, r;
  14. if (path.TryRSplit('/', l, r) || path.TryRSplit('\\', l, r)) {
  15. return r;
  16. } else {
  17. return path;
  18. }
  19. }
  20. static char GetLogLevelCode(ILogger::ELevel level) {
  21. switch (level) {
  22. case ILogger::FATAL: return 'F';
  23. case ILogger::ERROR: return 'E';
  24. case ILogger::INFO: return 'I';
  25. case ILogger::DEBUG: return 'D';
  26. }
  27. Y_UNREACHABLE();
  28. }
  29. ////////////////////////////////////////////////////////////////////////////////
  30. class TNullLogger
  31. : public ILogger
  32. {
  33. public:
  34. void Log(ELevel level, const TSourceLocation& sourceLocation, const char* format, va_list args) override
  35. {
  36. Y_UNUSED(level);
  37. Y_UNUSED(sourceLocation);
  38. Y_UNUSED(format);
  39. Y_UNUSED(args);
  40. }
  41. };
  42. ////////////////////////////////////////////////////////////////////////////////
  43. class TLoggerBase
  44. : public ILogger
  45. {
  46. public:
  47. TLoggerBase(ELevel cutLevel)
  48. : CutLevel_(cutLevel)
  49. { }
  50. virtual void OutputLine(const TString& line) = 0;
  51. void Log(ELevel level, const TSourceLocation& sourceLocation, const char* format, va_list args) override
  52. {
  53. if (level > CutLevel_) {
  54. return;
  55. }
  56. TStringStream stream;
  57. stream << TInstant::Now().ToStringLocal()
  58. << " " << GetLogLevelCode(level)
  59. << " [" << Hex(TThread::CurrentThreadId(), HF_FULL) << "] ";
  60. Printf(stream, format, args);
  61. stream << " - " << StripFileName(sourceLocation.File) << ':' << sourceLocation.Line << Endl;
  62. TGuard<TMutex> guard(Mutex_);
  63. OutputLine(stream.Str());
  64. }
  65. private:
  66. ELevel CutLevel_;
  67. TMutex Mutex_;
  68. };
  69. ////////////////////////////////////////////////////////////////////////////////
  70. class TStdErrLogger
  71. : public TLoggerBase
  72. {
  73. public:
  74. TStdErrLogger(ELevel cutLevel)
  75. : TLoggerBase(cutLevel)
  76. { }
  77. void OutputLine(const TString& line) override
  78. {
  79. Cerr << line;
  80. }
  81. };
  82. ILoggerPtr CreateStdErrLogger(ILogger::ELevel cutLevel)
  83. {
  84. return new TStdErrLogger(cutLevel);
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. class TFileLogger
  88. : public TLoggerBase
  89. {
  90. public:
  91. TFileLogger(ELevel cutLevel, const TString& path, bool append)
  92. : TLoggerBase(cutLevel)
  93. , Stream_(TFile(path, OpenAlways | WrOnly | Seq | (append ? ForAppend : EOpenMode())))
  94. { }
  95. void OutputLine(const TString& line) override
  96. {
  97. Stream_ << line;
  98. }
  99. private:
  100. TUnbufferedFileOutput Stream_;
  101. };
  102. ILoggerPtr CreateFileLogger(ILogger::ELevel cutLevel, const TString& path, bool append)
  103. {
  104. return new TFileLogger(cutLevel, path, append);
  105. }
  106. ////////////////////////////////////////////////////////////////////////////////
  107. class TBufferedFileLogger
  108. : public TLoggerBase
  109. {
  110. public:
  111. TBufferedFileLogger(ELevel cutLevel, const TString& path, bool append)
  112. : TLoggerBase(cutLevel)
  113. , Stream_(TFile(path, OpenAlways | WrOnly | Seq | (append ? ForAppend : EOpenMode())))
  114. { }
  115. void OutputLine(const TString& line) override
  116. {
  117. Stream_ << line;
  118. }
  119. private:
  120. TFileOutput Stream_;
  121. };
  122. ILoggerPtr CreateBufferedFileLogger(ILogger::ELevel cutLevel, const TString& path, bool append)
  123. {
  124. return new TBufferedFileLogger(cutLevel, path, append);
  125. }
  126. ////////////////////////////////////////////////////////////////////////////////
  127. static TRWMutex LoggerMutex;
  128. static ILoggerPtr Logger;
  129. struct TLoggerInitializer
  130. {
  131. TLoggerInitializer()
  132. {
  133. Logger = new TNullLogger;
  134. }
  135. } LoggerInitializer;
  136. void SetLogger(ILoggerPtr logger)
  137. {
  138. auto guard = TWriteGuard(LoggerMutex);
  139. if (logger) {
  140. Logger = logger;
  141. } else {
  142. Logger = new TNullLogger;
  143. }
  144. }
  145. ILoggerPtr GetLogger()
  146. {
  147. auto guard = TReadGuard(LoggerMutex);
  148. return Logger;
  149. }
  150. ////////////////////////////////////////////////////////////////////////////////
  151. }