#pragma once #include #include #include #include #include #include #include #include #include #define YLOG(logPriority, message, logger) \ do { \ const auto __logPriority = logPriority; \ if (auto* log = logger.Accept(__logPriority, false); log != nullptr) { \ logger.Log(*log, __logPriority, message); \ } \ } while (false) #define YLOG_EMERG(msg) YLOG(TLOG_EMERG, msg, Logger) #define YLOG_ALERT(msg) YLOG(TLOG_ALERT, msg, Logger) #define YLOG_CRIT(msg) YLOG(TLOG_CRIT, msg, Logger) #define YLOG_ERR(msg) YLOG(TLOG_ERR, msg, Logger) #define YLOG_WARNING(msg) YLOG(TLOG_WARNING, msg, Logger) #define YLOG_NOTICE(msg) YLOG(TLOG_NOTICE, msg, Logger) #define YLOG_INFO(msg) YLOG(TLOG_INFO, msg, Logger) #define YLOG_DEBUG(msg) YLOG(TLOG_DEBUG, msg, Logger) #define YLOG_RESOURCES(msg) YLOG(TLOG_RESOURCES , msg, Logger) #define YLOG_FATAL(msg) \ YLOG(TLOG_CRIT, msg, Logger); \ _Exit(1); namespace NUnifiedAgent { class TScopeLogger; class TLogger { public: TLogger(TLog& log, TFMaybe rateLimitBytes); void StartTracing(ELogPriority logPriority) noexcept; void FinishTracing() noexcept; inline TScopeLogger Child(const TString& v, NMonitoring::TDeprecatedCounter* errors = nullptr); inline void SetErrorsCounter(NMonitoring::TDeprecatedCounter* counter) noexcept { Errors = counter; } inline void SetDroppedBytesCounter(NMonitoring::TDeprecatedCounter* counter) noexcept { DroppedBytes = counter; } inline bool HasRateLimit() const noexcept { return Throttler != nullptr; } friend class TScopeLogger; private: void Log(TLog& log, ELogPriority logPriority, const TStringBuf message, const TString& scope) const; inline TLog* Accept(ELogPriority logPriority, NMonitoring::TDeprecatedCounter* errors) const noexcept { if ((logPriority <= TLOG_ERR) && (errors != nullptr)) { ++(*errors); } auto* result = CurrentLogContext_.load(std::memory_order_acquire); return result != nullptr && static_cast(logPriority) <= static_cast(result->Priority) ? &result->Log : nullptr; } private: struct TLogContext { TLog Log; ELogPriority Priority; }; class TThrottlerWithLock { public: explicit TThrottlerWithLock(size_t rateLimitBytes); bool TryConsume(double tokens); private: TThrottler Throttler; TAdaptiveLock Lock; }; private: void SetCurrentLogContext(TLogContext& logContext); TLogContext& GetOrCreateTracingLogContext(ELogPriority logPriority); void SetTracing(TLogContext& logContext, const char* action); private: TLogContext DefaultLogContext; TVector> TracingLogContexts; std::atomic CurrentLogContext_; NMonitoring::TDeprecatedCounter* Errors; NMonitoring::TDeprecatedCounter* DroppedBytes; const THolder Throttler; TAdaptiveLock Lock; }; class TScopeLogger { public: TScopeLogger(); inline void Log(TLog& log, ELogPriority logPriority, const TStringBuf message) const { if (Logger) { Logger->Log(log, logPriority, message, Scope); } } inline TLog* Accept(ELogPriority logPriority, bool silent) const noexcept { return Logger ? Logger->Accept(logPriority, silent ? nullptr : Errors) : nullptr; } inline TScopeLogger Child(const TString& v, NMonitoring::TDeprecatedCounter* errors = nullptr) { return Logger ? Logger->Child(Join('/', Scope, v), errors == nullptr ? Errors : errors) : TScopeLogger(); } inline TLogger* Unwrap() noexcept { return Logger; } ELogPriority FiltrationLevel() const { if (Logger) { return Logger->CurrentLogContext_.load()->Priority; } return LOG_DEF_PRIORITY; } friend class TLogger; private: TScopeLogger(TLogger* logger, const TString& scope, NMonitoring::TDeprecatedCounter* errors); private: TLogger* Logger; TString Scope; NMonitoring::TDeprecatedCounter* Errors; }; inline TScopeLogger TLogger::Child(const TString& v, NMonitoring::TDeprecatedCounter* errors) { return TScopeLogger(this, v, errors == nullptr ? Errors : errors); } inline ELogPriority ToLogPriority(int level) noexcept { const auto result = ClampVal(level, 0, static_cast(TLOG_RESOURCES)); return static_cast(result); } }