Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 65c277f8a7ee1fdabc10a6b4ff3bee4ecf094f4d
  • master par défaut protégée
  • rust-playlist-sync
  • rust
  • fix-qt-deprecated-qvariant-type
  • fix-mpris-qtwindow-race-condition
  • rust-appimage-wayland
  • windows-build-rebased
  • v2.5 protégée
  • v2.4 protégée
  • v2.3-1 protégée
  • v2.3 protégée
  • v2.2 protégée
  • v2.1 protégée
  • v2.0 protégée
  • v1.8-3 protégée
  • v1.8-2 protégée
  • v1.8-1 protégée
  • v1.8 protégée
  • v1.7 protégée
  • v1.6 protégée
  • v1.5 protégée
  • v1.4 protégée
  • v1.3 protégée
  • v1.2 protégée
  • v1.1 protégée
  • v1.0 protégée
27 résultats

launch.c

Blame
  • Log.hh 7,03 Kio
    #pragma once
    
    #include "Utils.hh"
    
    // Create a logger with a category
    #define VIVY_GET_LOGGER(sink, cat) std::make_shared<Logger>((sink).get(), std::string_view{ #cat })
    
    // Log something in a logger
    #define VIVY_LOG_WITH_LEVEL(log, level) log->logEvent(__FILE__, __func__, __LINE__, level)
    #define VIVY_LOG_WARN(log)              VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Warning)
    #define VIVY_LOG_DEBUG(log)             VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Debug)
    #define VIVY_LOG_INFO(log)              VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Info)
    #define VIVY_LOG_ERR(log)               VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Error)
    #define VIVY_LOG_FATAL(log)             VIVY_LOG_WITH_LEVEL(log, Vivy::LogLevel::Critical)
    
    // Declare a sink, with the utility function/method `flushLogSink`. This is
    // intended to be used in an object to not polluate namespaces.
    #define VIVY_DCL_LOG_SINK(sink)                          \
        std::shared_ptr<LogSink> sink{ LogSink::newSink() }; \
        void flushLogSink() const noexcept { sink->flush(); }
    
    // Declare a dispatch for a sink with no arguments in the constructor.
    #define VIVY_DCL_LOG_DISPATCH(sink, name, dispatch) \
        std::shared_ptr<dispatch> name{ sink->newDispatcher<dispatch>() };
    
    // Declare a dispatch for a sink with arguments in the constructor.
    #define VIVY_DCL_LOG_DISPATCH_WITH(sink, name, dispatch, ...) \
        std::shared_ptr<dispatch> name{ sink->newDispatcher<dispatch>(__VA_ARGS__) };
    
    // Install logger for the object.
    #define VIVY_LOGGABLE_OBJECT(sink, name, logger)                             \
        std::shared_ptr<Logger> logger{ VIVY_GET_LOGGER(sink, name) };           \
        LogMessage logFatal() const noexcept { return VIVY_LOG_FATAL(logger); }  \
        LogMessage logError() const noexcept { return VIVY_LOG_ERR(logger); }    \
        LogMessage logWarning() const noexcept { return VIVY_LOG_WARN(logger); } \
        LogMessage logInfo() const noexcept { return VIVY_LOG_INFO(logger); }    \
        LogMessage logDebug() const noexcept { return VIVY_LOG_DEBUG(logger); }
    
    #define VIVY_LOG_CTOR(classname) logDebug() << #classname "::CTOR "
    #define VIVY_LOG_DTOR(classname) logDebug() << #classname "::DTOR "
    
    // Install logger, use the global LogSink
    #define VIVY_APP_LOGGABLE_OBJECT(name, logger) \
        VIVY_LOGGABLE_OBJECT(vivyApp->getLogSink(), name, logger)
    
    namespace Vivy
    {
    class LogSinkDispatcher;
    class LogSink;
    class Logger;
    class LogMessage;
    
    // The severity of an event. Critical will cause the LogSink to flush all
    // messages to its emeters and then abort.
    enum class LogLevel : int {
        Critical = std::numeric_limits<int>::max(), // Will trigger qFatal
        Error    = 4,
        Warning  = 3,
        Info     = 2,
        Debug    = 1,
        None     = std::numeric_limits<int>::min() // In option setup to disable logs
    };
    
    // A LogSinkDispatcher will excavate LogMessages from the Sink and do something
    // with them (save to a file, display in stderr/Vivy console, etc).
    class LogSinkDispatcher {
        VIVY_UNMOVABLE_OBJECT(LogSinkDispatcher)
    
        const std::string dispatcherName;
    
    protected:
        explicit LogSinkDispatcher(const std::string_view name) noexcept
            : dispatcherName(name)
        {
        }
    
    public:
        const std::string_view getDispatcherName() const noexcept { return dispatcherName; }
        virtual ~LogSinkDispatcher() noexcept;
    
        virtual void handleLogMessage(const std::string_view, const LogMessage &) noexcept = 0;
    };
    
    // The stderr dispatcher for logs
    class StderrLogSinkDispatcher : public LogSinkDispatcher {
        VIVY_UNMOVABLE_OBJECT(StderrLogSinkDispatcher)
    
    public:
        explicit StderrLogSinkDispatcher() noexcept;
        void handleLogMessage(const std::string_view, const LogMessage &) noexcept override;
    };
    
    // LogSink is the parent logger. It will recieve messages and display them to a
    // console or to std::cerr or to a file, etc. The save to over file, etc will
    // be donne by the LogSinkDispatcher.
    class LogSink {
        VIVY_UNMOVABLE_OBJECT(LogSink)
    
        explicit LogSink() noexcept = default;
    
    public:
        static std::shared_ptr<LogSink> newSink() noexcept;
        ~LogSink() noexcept;
    
        void registerLogDispatcher(std::shared_ptr<LogSinkDispatcher>) noexcept;
        void recieveLogMessage(const Logger *const, LogMessage &&) noexcept;
        void flush() noexcept;
    
        template <Derived<LogSinkDispatcher> DispatcherType, typename... Args>
        std::shared_ptr<DispatcherType> newDispatcher(Args &&...args) noexcept
        {
            std::shared_ptr<DispatcherType> dispatch =
                std::make_shared<DispatcherType>(std::forward<Args>(args)...);
            registerLogDispatcher(dispatch);
            return dispatch;
        }
    
    private:
        std::mutex messageQueueLock{};
        std::vector<std::tuple<const std::string_view, LogMessage>> messageQueue;
        std::vector<std::shared_ptr<LogSinkDispatcher>> logDispatchers;
    };
    
    // Message to be logged, constructed by a logger then send
    class LogMessage final {
    public:
        using TimeStamp = chrono::milliseconds;
    
        // The header of the LogMessage
        struct Header final {
            const char *fileName;
            const char *functionName;
            const LogLevel severity;
            const int lineNumberInFile;
        };
    
    private:
        const Header messageHeader;
        const TimeStamp timeStamp{ duration_cast<TimeStamp>(
            chrono::system_clock::now().time_since_epoch()) };
    
        static constexpr inline size_t messageBufferLength = 2048;
        std::array<char, messageBufferLength> textBuffer{};
        std::size_t indexInArray{ 0 };
        const Logger *parentLogger{ nullptr };
    
    public:
        VIVY_DISABLE_COPY_CTOR(LogMessage)
        VIVY_DISABLE_ASSIGN_OPERATORS(LogMessage)
    
        explicit LogMessage(const Logger *const, const Header) noexcept;
        explicit LogMessage(LogMessage &&) noexcept;
        ~LogMessage() noexcept; // The message will be send on destruction
    
        Header const &getHeader() const noexcept { return messageHeader; }
        const std::string_view getTextBuffer() const noexcept;
        const TimeStamp getTimeStamp() const noexcept { return timeStamp; }
    
        LogMessage &&sink() noexcept;
    
        LogMessage &operator<<(const std::string &) noexcept;
        LogMessage &operator<<(const QString &) noexcept;
        LogMessage &operator<<(const char *) noexcept;
        LogMessage &operator<<(const char) noexcept;
        LogMessage &operator<<(const int) noexcept;
        LogMessage &operator<<(const long) noexcept;
    };
    
    // A logger class, a client to LogSink. Will generate and send instances of
    // LogMessage.
    class Logger final : public std::enable_shared_from_this<Logger> {
        VIVY_UNMOVABLE_OBJECT(Logger)
    
        LogSink *const parentLogSink;
        const std::string logCategory;
    
    public:
        // Templated constructor, construct from anything that can be considered as
        // a string.
        explicit Logger(LogSink *const sink, const StringType auto category) noexcept
            : parentLogSink(sink)
            , logCategory(Utils::anyStringToStdString(category))
        {
        }
    
        const std::string_view getCategoryView() const noexcept { return logCategory; }
    
        void sendLogMessage(LogMessage &&) const noexcept;
        LogMessage logEvent(const char *fileName, const char *functionName, const int lineNumber,
                            const LogLevel) noexcept;
    };
    }