// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once #include "types.h" #include "fmt/core.h" #include #include #include #include enum LOGLEVEL { LOGLEVEL_NONE, // Silences all log traffic LOGLEVEL_ERROR, LOGLEVEL_WARNING, LOGLEVEL_INFO, LOGLEVEL_VERBOSE, LOGLEVEL_DEV, LOGLEVEL_DEBUG, LOGLEVEL_TRACE, LOGLEVEL_COUNT }; namespace Log { // log message callback type using CallbackFunctionType = void (*)(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level, std::string_view message); // registers a log callback void RegisterCallback(CallbackFunctionType callbackFunction, void* pUserParam); // unregisters a log callback void UnregisterCallback(CallbackFunctionType callbackFunction, void* pUserParam); // returns the time in seconds since the start of the process float GetCurrentMessageTime(); // adds a standard console output bool IsConsoleOutputEnabled(); void SetConsoleOutputParams(bool enabled, bool timestamps = true); // adds a debug console output [win32/android only] bool IsDebugOutputEnabled(); void SetDebugOutputParams(bool enabled); // adds a file output void SetFileOutputParams(bool enabled, const char* filename, bool timestamps = true); // Returns the current global filtering level. LOGLEVEL GetLogLevel(); // Returns true if log messages for the specified log level/filter would not be filtered (and visible). bool IsLogVisible(LOGLEVEL level, const char* channelName); // Sets global filtering level, messages below this level won't be sent to any of the logging sinks. void SetLogLevel(LOGLEVEL level); // Sets global filter, any messages from these channels won't be sent to any of the logging sinks. void SetLogFilter(std::string_view filter); // writes a message to the log void Write(const char* channelName, LOGLEVEL level, std::string_view message); void Write(const char* channelName, const char* functionName, LOGLEVEL level, std::string_view message); void WriteFmtArgs(const char* channelName, LOGLEVEL level, fmt::string_view fmt, fmt::format_args args); void WriteFmtArgs(const char* channelName, const char* functionName, LOGLEVEL level, fmt::string_view fmt, fmt::format_args args); ALWAYS_INLINE static void FastWrite(const char* channelName, LOGLEVEL level, std::string_view message) { if (level <= GetLogLevel()) Write(channelName, level, message); } ALWAYS_INLINE static void FastWrite(const char* channelName, const char* functionName, LOGLEVEL level, std::string_view message) { if (level <= GetLogLevel()) Write(channelName, functionName, level, message); } template ALWAYS_INLINE static void FastWrite(const char* channelName, LOGLEVEL level, fmt::format_string fmt, T&&... args) { if (level <= GetLogLevel()) WriteFmtArgs(channelName, level, fmt, fmt::make_format_args(args...)); } template ALWAYS_INLINE static void FastWrite(const char* channelName, const char* functionName, LOGLEVEL level, fmt::format_string fmt, T&&... args) { if (level <= GetLogLevel()) WriteFmtArgs(channelName, functionName, level, fmt, fmt::make_format_args(args...)); } } // namespace Log // log wrappers #define Log_SetChannel(ChannelName) [[maybe_unused]] static const char* ___LogChannel___ = #ChannelName; #define ERROR_LOG(...) Log::FastWrite(___LogChannel___, __func__, LOGLEVEL_ERROR, __VA_ARGS__) #define WARNING_LOG(...) Log::FastWrite(___LogChannel___, __func__, LOGLEVEL_WARNING, __VA_ARGS__) #define INFO_LOG(...) Log::FastWrite(___LogChannel___, LOGLEVEL_INFO, __VA_ARGS__) #define VERBOSE_LOG(...) Log::FastWrite(___LogChannel___, LOGLEVEL_VERBOSE, __VA_ARGS__) #define DEV_LOG(...) Log::FastWrite(___LogChannel___, LOGLEVEL_DEV, __VA_ARGS__) #ifdef _DEBUG #define DEBUG_LOG(...) Log::FastWrite(___LogChannel___, LOGLEVEL_DEBUG, __VA_ARGS__) #define TRACE_LOG(...) Log::FastWrite(___LogChannel___, LOGLEVEL_TRACE, __VA_ARGS__) #else #define DEBUG_LOG(...) \ do \ { \ } while (0) #define TRACE_LOG(...) \ do \ { \ } while (0) #endif