log.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "log.h"
  2. #include "uninitialized_creator.h"
  3. #include "filter.h"
  4. #include "null.h"
  5. #include "stream.h"
  6. #include "thread.h"
  7. #include <util/stream/printf.h>
  8. #include <util/system/yassert.h>
  9. #include <util/generic/scope.h>
  10. THolder<TLogBackend> CreateLogBackend(const TString& fname, ELogPriority priority, bool threaded) {
  11. TLogBackendCreatorUninitialized creator;
  12. creator.InitCustom(fname, priority, threaded);
  13. return creator.CreateLogBackend();
  14. }
  15. THolder<TLogBackend> CreateFilteredOwningThreadedLogBackend(const TString& fname, ELogPriority priority, size_t queueLen) {
  16. return MakeHolder<TFilteredLogBackend>(CreateOwningThreadedLogBackend(fname, queueLen), priority);
  17. }
  18. THolder<TOwningThreadedLogBackend> CreateOwningThreadedLogBackend(const TString& fname, size_t queueLen) {
  19. return MakeHolder<TOwningThreadedLogBackend>(CreateLogBackend(fname, LOG_MAX_PRIORITY, false).Release(), queueLen);
  20. }
  21. class TLog::TImpl: public TAtomicRefCount<TImpl> {
  22. class TPriorityLogStream final: public IOutputStream {
  23. public:
  24. inline TPriorityLogStream(ELogPriority p, const TImpl* parent)
  25. : Priority_(p)
  26. , Parent_(parent)
  27. {
  28. }
  29. void DoWrite(const void* buf, size_t len) override {
  30. Parent_->WriteData(Priority_, (const char*)buf, len);
  31. }
  32. private:
  33. ELogPriority Priority_ = LOG_DEF_PRIORITY;
  34. const TImpl* Parent_ = nullptr;
  35. };
  36. public:
  37. inline TImpl(THolder<TLogBackend> backend)
  38. : Backend_(std::move(backend))
  39. {
  40. }
  41. inline void ReopenLog() {
  42. if (!IsOpen()) {
  43. return;
  44. }
  45. Backend_->ReopenLog();
  46. }
  47. inline void ReopenLogNoFlush() {
  48. if (!IsOpen()) {
  49. return;
  50. }
  51. Backend_->ReopenLogNoFlush();
  52. }
  53. inline void AddLog(ELogPriority priority, const char* format, va_list args) const {
  54. if (!IsOpen()) {
  55. return;
  56. }
  57. TPriorityLogStream ls(priority, this);
  58. Printf(ls, format, args);
  59. }
  60. inline void ResetBackend(THolder<TLogBackend> backend) noexcept {
  61. Backend_ = std::move(backend);
  62. }
  63. inline THolder<TLogBackend> ReleaseBackend() noexcept {
  64. return std::move(Backend_);
  65. }
  66. inline bool IsNullLog() const noexcept {
  67. return !IsOpen() || (dynamic_cast<TNullLogBackend*>(Backend_.Get()) != nullptr);
  68. }
  69. inline bool IsOpen() const noexcept {
  70. return nullptr != Backend_.Get();
  71. }
  72. inline void CloseLog() noexcept {
  73. Backend_.Destroy();
  74. Y_ASSERT(!IsOpen());
  75. }
  76. inline void WriteData(ELogPriority priority, const char* data, size_t len, TLogRecord::TMetaFlags metaFlags = {}) const {
  77. if (IsOpen()) {
  78. Backend_->WriteData(TLogRecord(priority, data, len, std::move(metaFlags)));
  79. }
  80. }
  81. inline ELogPriority DefaultPriority() noexcept {
  82. return DefaultPriority_;
  83. }
  84. inline void SetDefaultPriority(ELogPriority priority) noexcept {
  85. DefaultPriority_ = priority;
  86. }
  87. inline ELogPriority FiltrationLevel() const noexcept {
  88. return Backend_->FiltrationLevel();
  89. }
  90. inline size_t BackEndQueueSize() const {
  91. return Backend_->QueueSize();
  92. }
  93. private:
  94. THolder<TLogBackend> Backend_;
  95. ELogPriority DefaultPriority_ = LOG_DEF_PRIORITY;
  96. };
  97. TLog::TLog()
  98. : Impl_(MakeIntrusive<TImpl>(nullptr))
  99. {
  100. }
  101. TLog::TLog(const TString& fname, ELogPriority priority)
  102. : TLog(CreateLogBackend(fname, priority, false))
  103. {
  104. }
  105. TLog::TLog(THolder<TLogBackend> backend)
  106. : Impl_(MakeIntrusive<TImpl>(std::move(backend)))
  107. {
  108. }
  109. TLog::TLog(const TLog&) = default;
  110. TLog::TLog(TLog&&) = default;
  111. TLog::~TLog() = default;
  112. TLog& TLog::operator=(const TLog&) = default;
  113. TLog& TLog::operator=(TLog&&) = default;
  114. bool TLog::IsOpen() const noexcept {
  115. return Impl_->IsOpen();
  116. }
  117. void TLog::AddLog(const char* format, ...) const {
  118. va_list args;
  119. va_start(args, format);
  120. Y_DEFER {
  121. va_end(args);
  122. };
  123. Impl_->AddLog(Impl_->DefaultPriority(), format, args);
  124. }
  125. void TLog::AddLog(ELogPriority priority, const char* format, ...) const {
  126. va_list args;
  127. va_start(args, format);
  128. Y_DEFER {
  129. va_end(args);
  130. };
  131. Impl_->AddLog(priority, format, args);
  132. }
  133. void TLog::AddLogVAList(const char* format, va_list lst) {
  134. Impl_->AddLog(Impl_->DefaultPriority(), format, lst);
  135. }
  136. void TLog::ReopenLog() {
  137. if (const auto copy = Impl_) {
  138. copy->ReopenLog();
  139. }
  140. }
  141. void TLog::ReopenLogNoFlush() {
  142. if (const auto copy = Impl_) {
  143. copy->ReopenLogNoFlush();
  144. }
  145. }
  146. void TLog::CloseLog() {
  147. Impl_->CloseLog();
  148. }
  149. void TLog::SetDefaultPriority(ELogPriority priority) noexcept {
  150. Impl_->SetDefaultPriority(priority);
  151. }
  152. ELogPriority TLog::FiltrationLevel() const noexcept {
  153. return Impl_->FiltrationLevel();
  154. }
  155. ELogPriority TLog::DefaultPriority() const noexcept {
  156. return Impl_->DefaultPriority();
  157. }
  158. bool TLog::OpenLog(const char* path, ELogPriority lp) {
  159. if (path) {
  160. ResetBackend(CreateLogBackend(path, lp));
  161. } else {
  162. ResetBackend(MakeHolder<TStreamLogBackend>(&Cerr));
  163. }
  164. return true;
  165. }
  166. void TLog::ResetBackend(THolder<TLogBackend> backend) noexcept {
  167. Impl_->ResetBackend(std::move(backend));
  168. }
  169. bool TLog::IsNullLog() const noexcept {
  170. return Impl_->IsNullLog();
  171. }
  172. THolder<TLogBackend> TLog::ReleaseBackend() noexcept {
  173. return Impl_->ReleaseBackend();
  174. }
  175. void TLog::Write(ELogPriority priority, const char* data, size_t len, TLogRecord::TMetaFlags metaFlags) const {
  176. if (Formatter_) {
  177. const auto formated = Formatter_(priority, TStringBuf{data, len});
  178. Impl_->WriteData(priority, formated.data(), formated.size(), std::move(metaFlags));
  179. } else {
  180. Impl_->WriteData(priority, data, len, std::move(metaFlags));
  181. }
  182. }
  183. void TLog::Write(ELogPriority priority, const TStringBuf data, TLogRecord::TMetaFlags metaFlags) const {
  184. Write(priority, data.data(), data.size(), std::move(metaFlags));
  185. }
  186. void TLog::Write(const char* data, size_t len, TLogRecord::TMetaFlags metaFlags) const {
  187. Write(Impl_->DefaultPriority(), data, len, std::move(metaFlags));
  188. }
  189. void TLog::SetFormatter(TLogFormatter formatter) noexcept {
  190. Formatter_ = std::move(formatter);
  191. }
  192. size_t TLog::BackEndQueueSize() const {
  193. return Impl_->BackEndQueueSize();
  194. }