aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/logger/global/common.h
blob: 7dcf650decb9208b130b396dcdaa4a038857a93e (plain) (tree)
1
2
3
4
5
6
7




                                   
                                



                                     
                                   
 


                                         



                          












                                                    
                                                                                    
         
 
                                
                                                                                    

                                      
                                                                                
         
      





                                            
 

                                                                                                
                               
                                           
     
  
                        
                                  
 
                                      
                                                                                               

                                                                                                          
                                                                                                                                                 
     

                          



                                                                                                                       

                                   
                          





                                 


                                                                                                 
                                                                                                                                                 
                    







                                                                    


                                                                                                                       





                                                                                                                                                 
                                                                                                                                         









                                                                                                 
                                
                                                                   

                        
 
 
                                                                                                                                                                 
                                                                                                                                                                                                                                         

                                                                                                                                                                
#pragma once

#include <util/datetime/base.h>

#include <util/folder/path.h>
#include <util/generic/singleton.h>
#include <util/generic/string.h>
#include <util/generic/ptr.h>
#include <util/generic/yexception.h>
#include <util/string/printf.h>
#include <util/system/src_location.h>

#include <library/cpp/logger/log.h>

namespace NLoggingImpl {
    const size_t SingletonPriority = 500;
}

template <class T>
T* CreateDefaultLogger() {
    return nullptr;
}

namespace NLoggingImpl {
    template<class T, class TTraits>
    class TOperatorBase {
        struct TPtr {
            TPtr()
                : Instance(TTraits::CreateDefault())
            {
            }

            THolder<T> Instance;
        };

    public:
        inline static bool Usage() {
            return SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Get();
        }

        inline static T* Get() {
            return SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Get();
        }

        inline static void Set(T* v) {
            SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Reset(v);
        }
    };

    template<class T>
    struct TLoggerTraits {
        static T* CreateDefault() {
            return CreateDefaultLogger<T>();
        }
    };
}

template <class T>
class TLoggerOperator : public NLoggingImpl::TOperatorBase<T, NLoggingImpl::TLoggerTraits<T>>  {
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 <class TLoggerType>
    void InitLogImpl(TString logType, const int logLevel, const bool rotation, const bool startAsDaemon) {
        TLoggerOperator<TLoggerType>::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 <class... R>
struct TLogRecordPreprocessor;

template <>
struct TLogRecordPreprocessor<> {
    inline static bool CheckLoggingContext(TLog& /*log*/, const TLogRecordContext& /*context*/) {
        return true;
    }

    inline static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
        if (earlier)
            return earlier;
        TSimpleSharedPtr<TLogElement> result(new TLogElement(&log));
        *result << context.Priority;
        return result;
    }
};

template <class H, class... R>
struct TLogRecordPreprocessor<H, R...> {
    inline static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context) {
        return H::CheckLoggingContext(log, context) && TLogRecordPreprocessor<R...>::CheckLoggingContext(log, context);
    }

    inline static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
        TSimpleSharedPtr<TLogElement> first = H::StartRecord(log, context, earlier);
        return TLogRecordPreprocessor<R...>::StartRecord(log, context, first);
    }
};

struct TLogFilter {
    static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context);
    static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier);
};

class TNullLog;

template <class TPreprocessor>
TSimpleSharedPtr<TLogElement> GetLoggerForce(TLog& log, const TLogRecordContext& context) {
    if (TSimpleSharedPtr<TLogElement> result = TPreprocessor::StartRecord(log, context, nullptr))
        return result;
    return new TLogElement(&TLoggerOperator<TNullLog>::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<preprocessor>(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<type>::Log(), preprocessor, level, message)
#define SINGLETON_CHECKED_GENERIC_LOG(type, preprocessor, level, message) LOGGER_CHECKED_GENERIC_LOG(TLoggerOperator<type>::Log(), preprocessor, level, message)