log.cpp 6.1 KB

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