#pragma once #include #include #include #include #include #include #include #include #include namespace NLoggingImpl { const size_t SingletonPriority = 500; } template T* CreateDefaultLogger() { return nullptr; } namespace NLoggingImpl { template class TOperatorBase { struct TPtr { TPtr() : Instance(TTraits::CreateDefault()) { } THolder Instance; }; public: inline static bool Usage() { return SingletonWithPriority()->Instance.Get(); } inline static T* Get() { return SingletonWithPriority()->Instance.Get(); } inline static void Set(T* v) { SingletonWithPriority()->Instance.Reset(v); } }; template struct TLoggerTraits { static T* CreateDefault() { return CreateDefaultLogger(); } }; } template class TLoggerOperator : public NLoggingImpl::TOperatorBase> { public: inline static TLog& Log() { Y_ASSERT(TLoggerOperator::Usage()); return *TLoggerOperator::Get(); } }; namespace NLoggingImpl { TString GetLocalTimeSSimple(); // Returns correct log type to use TString PrepareToOpenLog(TString logType, int logLevel, bool rotation, bool startAsDaemon); template void InitLogImpl(TString logType, const int logLevel, const bool rotation, const bool startAsDaemon) { TLoggerOperator::Set(new TLoggerType(PrepareToOpenLog(logType, logLevel, rotation, startAsDaemon), (ELogPriority)logLevel)); } } struct TLogRecordContext { constexpr TLogRecordContext(const TSourceLocation& sourceLocation, TStringBuf customMessage, ELogPriority priority) : SourceLocation(sourceLocation) , CustomMessage(customMessage) , Priority(priority) {} TSourceLocation SourceLocation; TStringBuf CustomMessage; ELogPriority Priority; }; template struct TLogRecordPreprocessor; template <> struct TLogRecordPreprocessor<> { inline static bool CheckLoggingContext(TLog& /*log*/, const TLogRecordContext& /*context*/) { return true; } inline static TSimpleSharedPtr StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr earlier) { if (earlier) return earlier; TSimpleSharedPtr result(new TLogElement(&log)); *result << context.Priority; return result; } }; template struct TLogRecordPreprocessor { inline static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context) { return H::CheckLoggingContext(log, context) && TLogRecordPreprocessor::CheckLoggingContext(log, context); } inline static TSimpleSharedPtr StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr earlier) { TSimpleSharedPtr first = H::StartRecord(log, context, earlier); return TLogRecordPreprocessor::StartRecord(log, context, first); } }; struct TLogFilter { static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context); static TSimpleSharedPtr StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr earlier); }; class TNullLog; template TSimpleSharedPtr GetLoggerForce(TLog& log, const TLogRecordContext& context) { if (TSimpleSharedPtr result = TPreprocessor::StartRecord(log, context, nullptr)) return result; return new TLogElement(&TLoggerOperator::Log()); } namespace NPrivateGlobalLogger { struct TEatStream { Y_FORCE_INLINE bool operator|(const IOutputStream&) const { return true; } }; } #define LOGGER_GENERIC_LOG_CHECKED(logger, preprocessor, level, message) (*GetLoggerForce(logger, TLogRecordContext(__LOCATION__, message, level))) #define LOGGER_CHECKED_GENERIC_LOG(logger, preprocessor, level, message) \ (preprocessor::CheckLoggingContext(logger, TLogRecordContext(__LOCATION__, message, level))) && NPrivateGlobalLogger::TEatStream() | (*(preprocessor::StartRecord(logger, TLogRecordContext(__LOCATION__, message, level), nullptr))) #define SINGLETON_GENERIC_LOG_CHECKED(type, preprocessor, level, message) LOGGER_GENERIC_LOG_CHECKED(TLoggerOperator::Log(), preprocessor, level, message) #define SINGLETON_CHECKED_GENERIC_LOG(type, preprocessor, level, message) LOGGER_CHECKED_GENERIC_LOG(TLoggerOperator::Log(), preprocessor, level, message)