#include "log.h" #include "uninitialized_creator.h" #include "filter.h" #include "null.h" #include "stream.h" #include "thread.h" #include #include #include THolder CreateLogBackend(const TString& fname, ELogPriority priority, bool threaded) { TLogBackendCreatorUninitialized creator; creator.InitCustom(fname, priority, threaded); return creator.CreateLogBackend(); } THolder CreateFilteredOwningThreadedLogBackend(const TString& fname, ELogPriority priority, size_t queueLen) { return MakeHolder(CreateOwningThreadedLogBackend(fname, queueLen), priority); } THolder CreateOwningThreadedLogBackend(const TString& fname, size_t queueLen) { return MakeHolder(CreateLogBackend(fname, LOG_MAX_PRIORITY, false).Release(), queueLen); } class TLog::TImpl: public TAtomicRefCount { class TPriorityLogStream final: public IOutputStream { public: inline TPriorityLogStream(ELogPriority p, const TImpl* parent) : Priority_(p) , Parent_(parent) { } void DoWrite(const void* buf, size_t len) override { Parent_->WriteData(Priority_, (const char*)buf, len); } private: ELogPriority Priority_ = LOG_DEF_PRIORITY; const TImpl* Parent_ = nullptr; }; public: inline TImpl(THolder backend) : Backend_(std::move(backend)) { } inline void ReopenLog() { if (!IsOpen()) { return; } Backend_->ReopenLog(); } inline void ReopenLogNoFlush() { if (!IsOpen()) { return; } Backend_->ReopenLogNoFlush(); } inline void AddLog(ELogPriority priority, const char* format, va_list args) const { if (!IsOpen()) { return; } TPriorityLogStream ls(priority, this); Printf(ls, format, args); } inline void ResetBackend(THolder backend) noexcept { Backend_ = std::move(backend); } inline THolder ReleaseBackend() noexcept { return std::move(Backend_); } inline bool IsNullLog() const noexcept { return !IsOpen() || (dynamic_cast(Backend_.Get()) != nullptr); } inline bool IsOpen() const noexcept { return nullptr != Backend_.Get(); } inline void CloseLog() noexcept { Backend_.Destroy(); Y_ASSERT(!IsOpen()); } inline void WriteData(ELogPriority priority, const char* data, size_t len, TLogRecord::TMetaFlags metaFlags = {}) const { if (IsOpen()) { Backend_->WriteData(TLogRecord(priority, data, len, std::move(metaFlags))); } } inline ELogPriority DefaultPriority() noexcept { return DefaultPriority_; } inline void SetDefaultPriority(ELogPriority priority) noexcept { DefaultPriority_ = priority; } inline ELogPriority FiltrationLevel() const noexcept { return Backend_->FiltrationLevel(); } inline size_t BackEndQueueSize() const { return Backend_->QueueSize(); } private: THolder Backend_; ELogPriority DefaultPriority_ = LOG_DEF_PRIORITY; }; TLog::TLog() : Impl_(MakeIntrusive(nullptr)) { } TLog::TLog(const TString& fname, ELogPriority priority) : TLog(CreateLogBackend(fname, priority, false)) { } TLog::TLog(THolder backend) : Impl_(MakeIntrusive(std::move(backend))) { } TLog::TLog(const TLog&) = default; TLog::TLog(TLog&&) = default; TLog::~TLog() = default; TLog& TLog::operator=(const TLog&) = default; TLog& TLog::operator=(TLog&&) = default; bool TLog::IsOpen() const noexcept { return Impl_->IsOpen(); } void TLog::AddLog(const char* format, ...) const { va_list args; va_start(args, format); Y_DEFER { va_end(args); }; Impl_->AddLog(Impl_->DefaultPriority(), format, args); } void TLog::AddLog(ELogPriority priority, const char* format, ...) const { va_list args; va_start(args, format); Y_DEFER { va_end(args); }; Impl_->AddLog(priority, format, args); } void TLog::AddLogVAList(const char* format, va_list lst) { Impl_->AddLog(Impl_->DefaultPriority(), format, lst); } void TLog::ReopenLog() { if (const auto copy = Impl_) { copy->ReopenLog(); } } void TLog::ReopenLogNoFlush() { if (const auto copy = Impl_) { copy->ReopenLogNoFlush(); } } void TLog::CloseLog() { Impl_->CloseLog(); } void TLog::SetDefaultPriority(ELogPriority priority) noexcept { Impl_->SetDefaultPriority(priority); } ELogPriority TLog::FiltrationLevel() const noexcept { return Impl_->FiltrationLevel(); } ELogPriority TLog::DefaultPriority() const noexcept { return Impl_->DefaultPriority(); } bool TLog::OpenLog(const char* path, ELogPriority lp) { if (path) { ResetBackend(CreateLogBackend(path, lp)); } else { ResetBackend(MakeHolder(&Cerr)); } return true; } void TLog::ResetBackend(THolder backend) noexcept { Impl_->ResetBackend(std::move(backend)); } bool TLog::IsNullLog() const noexcept { return Impl_->IsNullLog(); } THolder TLog::ReleaseBackend() noexcept { return Impl_->ReleaseBackend(); } void TLog::Write(ELogPriority priority, const char* data, size_t len, TLogRecord::TMetaFlags metaFlags) const { if (Formatter_) { const auto formated = Formatter_(priority, TStringBuf{data, len}); Impl_->WriteData(priority, formated.data(), formated.size(), std::move(metaFlags)); } else { Impl_->WriteData(priority, data, len, std::move(metaFlags)); } } void TLog::Write(ELogPriority priority, const TStringBuf data, TLogRecord::TMetaFlags metaFlags) const { Write(priority, data.data(), data.size(), std::move(metaFlags)); } void TLog::Write(const char* data, size_t len, TLogRecord::TMetaFlags metaFlags) const { Write(Impl_->DefaultPriority(), data, len, std::move(metaFlags)); } void TLog::SetFormatter(TLogFormatter formatter) noexcept { Formatter_ = std::move(formatter); } size_t TLog::BackEndQueueSize() const { return Impl_->BackEndQueueSize(); }