#pragma once #include #include #include #include #include #include #include #include #include #include namespace RenderCadenceCompositor { enum class LogLevel { Log, Warning, Error }; struct LoggerConfig { LogLevel minimumLevel = LogLevel::Log; bool writeToConsole = true; bool writeToDebugOutput = true; bool writeToFile = true; std::string filePath = "logs/render-cadence-compositor.log"; std::size_t maxQueuedMessages = 1024; }; struct LoggerCounters { uint64_t queued = 0; uint64_t written = 0; uint64_t dropped = 0; }; const char* LogLevelName(LogLevel level); class Logger { public: struct Record { std::chrono::system_clock::time_point timestamp; std::thread::id threadId; LogLevel level = LogLevel::Log; std::string subsystem; std::string message; }; static Logger& Instance(); Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; ~Logger(); void Start(LoggerConfig config = LoggerConfig()); void Stop(); void Write(LogLevel level, const std::string& subsystem, const std::string& message); bool TryWrite(LogLevel level, const std::string& subsystem, const std::string& message); void Log(const std::string& subsystem, const std::string& message); void Warning(const std::string& subsystem, const std::string& message); void Error(const std::string& subsystem, const std::string& message); LoggerCounters Counters() const; bool IsRunning() const; private: Logger() = default; bool ShouldWrite(LogLevel level) const; bool Enqueue(Record record, bool block); void ThreadMain(); void WriteRecord(const Record& record); void OpenFileSink(); void CloseFileSink(); LoggerConfig mConfig; std::ofstream mFile; std::thread mThread; mutable std::mutex mMutex; std::condition_variable mCondition; std::deque mQueue; bool mStopping = false; bool mRunning = false; mutable std::mutex mCountersMutex; LoggerCounters mCounters; }; bool TryLog(LogLevel level, const std::string& subsystem, const std::string& message); void Log(const std::string& subsystem, const std::string& message); void LogWarning(const std::string& subsystem, const std::string& message); void LogError(const std::string& subsystem, const std::string& message); }