log.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #pragma once
  2. #include "log_component.h"
  3. #include "log_level.h"
  4. #include "context.h"
  5. #include "profile.h"
  6. #include <library/cpp/logger/global/common.h>
  7. #include <library/cpp/deprecated/atomic/atomic.h>
  8. #include <util/stream/output.h>
  9. #include <util/generic/strbuf.h>
  10. #include <array>
  11. #define YQL_LOG_IMPL(logger, component, level, preprocessor, file, line) \
  12. logger.NeedToLog(component, level) && NPrivateGlobalLogger::TEatStream() | \
  13. (*preprocessor::Preprocess(logger.CreateLogElement(component, level, file, line)))
  14. #define YQL_LOG_IF_IMPL(logger, component, level, preprocessor, condition, file, line) \
  15. logger.NeedToLog(component, level) && (condition) && NPrivateGlobalLogger::TEatStream() | \
  16. (*preprocessor::Preprocess(logger.CreateLogElement(component, level, file, line)))
  17. // with component logger
  18. #define YQL_CLOG_PREP(level, component, preprocessor) YQL_LOG_IMPL(\
  19. ::NYql::NLog::YqlLogger(), \
  20. ::NYql::NLog::EComponent::component, \
  21. ::NYql::NLog::ELevel::level, \
  22. preprocessor, \
  23. __FILE__, __LINE__)
  24. #define YQL_CLOG(level, component) \
  25. YQL_CLOG_PREP(level, component, ::NYql::NLog::TContextPreprocessor)
  26. #define YQL_CLOG_ACTIVE(level, component) ::NYql::NLog::YqlLogger().NeedToLog( \
  27. ::NYql::NLog::EComponent::component, \
  28. ::NYql::NLog::ELevel::level)
  29. // with component/level values logger
  30. #define YQL_CVLOG_PREP(level, component, preprocessor) YQL_LOG_IMPL(\
  31. ::NYql::NLog::YqlLogger(), \
  32. component, \
  33. level, \
  34. preprocessor, \
  35. __FILE__, __LINE__)
  36. #define YQL_CVLOG(level, component) \
  37. YQL_CVLOG_PREP(level, component, ::NYql::NLog::TContextPreprocessor)
  38. #define YQL_CVLOG_ACTIVE(level, component) ::NYql::NLog::YqlLogger().NeedToLog( \
  39. component, \
  40. level)
  41. // default logger
  42. #define YQL_LOG_PREP(level, preprocessor) \
  43. YQL_CLOG_PREP(level, Default, preprocessor)
  44. #define YQL_LOG(level) \
  45. YQL_LOG_PREP(level, ::NYql::NLog::TContextPreprocessor)
  46. #define YQL_LOG_ACTIVE(level) YQL_CLOG_ACTIVE(level, Default)
  47. // conditional logger
  48. #define YQL_CLOG_PREP_IF(level, component, preprocessor, condition) YQL_LOG_IF_IMPL(\
  49. ::NYql::NLog::YqlLogger(), \
  50. ::NYql::NLog::EComponent::component, \
  51. ::NYql::NLog::ELevel::level, \
  52. preprocessor, \
  53. condition, \
  54. __FILE__, __LINE__)
  55. #define YQL_CLOG_IF(level, component, condition) \
  56. YQL_CLOG_PREP_IF(level, component, ::NYql::NLog::TContextPreprocessor, condition)
  57. #define YQL_LOG_PREP_IF(level, preprocessor, condition) \
  58. YQL_CLOG_PREP_IF(level, Default, preprocessor, condition)
  59. #define YQL_LOG_IF(level, condition) \
  60. YQL_LOG_PREP_IF(level, ::NYql::NLog::TContextPreprocessor, condition)
  61. namespace NYql {
  62. namespace NProto {
  63. class TLoggingConfig;
  64. } // NProto
  65. namespace NLog {
  66. using TComponentLevels =
  67. std::array<ELevel, EComponentHelpers::ToInt(EComponent::MaxValue)>;
  68. void WriteLocalTime(IOutputStream* out);
  69. /**
  70. * @brief Component based logger frontend.
  71. */
  72. class TYqlLog: public TLog {
  73. public:
  74. TYqlLog();
  75. TYqlLog(const TString& logType, const TComponentLevels& levels);
  76. TYqlLog(TAutoPtr<TLogBackend> backend, const TComponentLevels& levels);
  77. // XXX: not thread-safe
  78. void UpdateProcInfo(const TString& procName);
  79. ELevel GetComponentLevel(EComponent component) const {
  80. return ELevelHelpers::FromInt(AtomicGet(ComponentLevels_[EComponentHelpers::ToInt(component)]));
  81. }
  82. void SetComponentLevel(EComponent component, ELevel level) {
  83. AtomicSet(ComponentLevels_[EComponentHelpers::ToInt(component)], ELevelHelpers::ToInt(level));
  84. }
  85. bool NeedToLog(EComponent component, ELevel level) const {
  86. return ELevelHelpers::Lte(level, GetComponentLevel(component));
  87. }
  88. void SetMaxLogLimit(ui64 limit);
  89. TAutoPtr<TLogElement> CreateLogElement(EComponent component, ELevel level, TStringBuf file, int line) const;
  90. void WriteLogPrefix(IOutputStream* out, EComponent component, ELevel level, TStringBuf file, int line) const;
  91. private:
  92. TString ProcName_;
  93. pid_t ProcId_;
  94. std::array<TAtomic, EComponentHelpers::ToInt(EComponent::MaxValue)> ComponentLevels_{0};
  95. mutable TAtomic WriteTruncMsg_;
  96. };
  97. /**
  98. * @brief returns reference to YQL logger instance.
  99. */
  100. inline TYqlLog& YqlLogger() {
  101. return static_cast<TYqlLog&>(TLoggerOperator<TYqlLog>::Log());
  102. }
  103. /**
  104. * @brief returns true it YQL logger already initialized.
  105. */
  106. inline bool IsYqlLoggerInitialized() {
  107. return TLoggerOperator<TYqlLog>::Usage();
  108. }
  109. /**
  110. * @brief Initialize logger with selected backend type.
  111. *
  112. * @param log - one of { syslog, console, cout, cerr, null, /path/to/file }
  113. * @param startAsDaemon - true if process is demonized
  114. */
  115. void InitLogger(const TString& log, bool startAsDaemon = false);
  116. /**
  117. * @brief Initialize logger with backends described in config.
  118. */
  119. void InitLogger(const NProto::TLoggingConfig& loggingConfig, bool startAsDaemon = false);
  120. /**
  121. * @brief Initialize logger with concrete backend.
  122. *
  123. * @param backend - logger backend
  124. */
  125. void InitLogger(TAutoPtr<TLogBackend> backend);
  126. /**
  127. * @brief Initialize logger with concrete output stream.
  128. *
  129. * @param out - output stream
  130. */
  131. void InitLogger(IOutputStream* out);
  132. void CleanupLogger();
  133. void ReopenLog();
  134. class YqlLoggerScope {
  135. public:
  136. YqlLoggerScope(const TString& log, bool startAsDaemon = false) { InitLogger(log, startAsDaemon); }
  137. YqlLoggerScope(TAutoPtr<TLogBackend> backend) { InitLogger(backend); }
  138. YqlLoggerScope(IOutputStream* out) { InitLogger(out); }
  139. ~YqlLoggerScope() { CleanupLogger(); }
  140. };
  141. } // namespace NLog
  142. } // namespace NYql
  143. template <>
  144. NYql::NLog::TYqlLog* CreateDefaultLogger<NYql::NLog::TYqlLog>();