TeaSpeakLibrary/src/log/LogUtils.h

136 lines
6.7 KiB
C++

#pragma once
#ifdef SPDLOG_FINAL
#undef SPDLOG_FINAL
#endif
#define SPDLOG_FINAL
#define SPDLOG_ALLOW_PROTECT
#define SPDLOG_NO_FINAL //We need to override the rotating logger
#ifdef byte
#undef byte
#endif
#include <spdlog/logger.h>
#include <sstream>
#include <string>
#include <chrono>
#include "../Definitions.h"
#include "LogSinks.h"
#ifdef HAVE_CXX_TERMINAL
#include <CXXTerminal/Terminal.h>
#endif
#define lstream std::stringstream()
#ifdef log
#undef log
#endif
namespace logger {
struct LoggerConfig {
spdlog::level::level_enum logfileLevel = spdlog::level::info;
spdlog::level::level_enum terminalLevel = spdlog::level::info;
bool file_colored;
std::string logPath = "log_${time}.log";
size_t vs_group_size = 1;
std::chrono::system_clock::time_point timestamp;
};
extern std::shared_ptr<spdlog::logger> logger(int);
extern void setup(const std::shared_ptr<LoggerConfig>&);
extern const std::shared_ptr<LoggerConfig>& currentConfig();
extern void uninstall();
extern void updateLogLevels();
extern void flush();
}
#define LOG_LICENSE_CONTROLL (-0x10)
#define LOG_LICENSE_WEB (-0x11)
#define LOG_INSTANCE (-1)
#define LOG_QUERY (-2)
#define LOG_FT (-3)
#define LOG_GENERAL 0
#ifdef HAVE_CXX_TERMINAL
#define DEFINE_LOG_IMPL_NO_LOGGER(prefix, message) \
if(terminal::active()) \
terminal::instance()->writeMessage("[" + std::string(prefix) + "] " + message); \
else \
std::cout << "[" + std::string(prefix) + "] " + message << std::endl;
#else
#define DEFINE_LOG_IMPL_NO_LOGGER(prefix, message) \
std::cout << "[" + std::string(prefix) + "] " + message << std::endl;
#endif
#define DEFINE_LOG_IMPL(name, level, _default_prefix) \
template <typename... Args> \
inline void name ##Fmt(bool forced, int serverId, const std::string& message, const Args&... args){ \
auto _logger = ::logger::logger(serverId); \
std::string fmt_message; \
try { \
fmt::MemoryWriter writer; \
writer.write(message, args...); \
fmt_message = writer.str(); \
} catch (const std::exception &ex) { \
fmt_message = "failed to format message '" + message + "': " + ex.what(); \
} \
if(!_logger) { \
DEFINE_LOG_IMPL_NO_LOGGER(_default_prefix, fmt_message); \
return; \
} \
if (!_logger->should_log(level) && !forced) return; \
\
try { \
::logger::force_log_msg log_msg(&_logger->_name, level, forced); \
auto fmt = "§8{0:>5} | §r{1}"; \
if(serverId > 0); \
else if(serverId == LOG_INSTANCE) \
fmt = "§8GLOBL | §r{1}"; \
else if(serverId == LOG_QUERY) \
fmt = "§8QUERY | §r{1}"; \
else if(serverId == LOG_FT) \
fmt = "§8 FILE | §r{1}"; \
else if(serverId == LOG_GENERAL) \
fmt = "§8 GEN | §r{1}"; \
else if(serverId == LOG_LICENSE_CONTROLL) \
fmt = "§8 CONTR | §r{1}"; \
else if(serverId == LOG_LICENSE_WEB) \
fmt = "§8 WEBST | §r{1}"; \
log_msg.raw.write(fmt, serverId, fmt_message); \
_logger->_sink_it(log_msg); \
} catch (const std::exception &ex) { \
_logger->_err_handler(ex.what()); \
} catch(...) { \
_logger->_err_handler("Unknown exception in logger " + _logger->_name); \
throw; \
} \
}
DEFINE_LOG_IMPL(logMessage, spdlog::level::info, "INFO")
DEFINE_LOG_IMPL(logError, spdlog::level::err, "ERROR")
DEFINE_LOG_IMPL(logWarning, spdlog::level::warn, "WARNING")
DEFINE_LOG_IMPL(logCritical, spdlog::level::critical, "CRITICAL")
DEFINE_LOG_IMPL(logTrace, spdlog::level::trace, "TRACE")
DEFINE_LOG_IMPL(debugMessage, spdlog::level::debug, "DEBUG")
#define LOG_METHOD(name) \
template <typename... Args> \
inline void name(int serverId, const std::string& message, const Args&... args){ name ##Fmt(false, serverId, message, args...); } \
inline void name(int serverId, const std::string& message){ name ##Fmt(false, serverId, message); } \
inline void name(int serverId, std::ostream& str){ std::stringstream s; s << str.rdbuf(); name(serverId, s.str()); } \
inline void name(const std::string& message) { name ##Fmt(false, 0, message); } \
inline void name(std::ostream& str){ std::stringstream s; s << str.rdbuf(); name(s.str()); } \
inline void name(bool, int, const std::string&) = delete;
LOG_METHOD(logError);
LOG_METHOD(logWarning);
LOG_METHOD(logMessage);
LOG_METHOD(logCritical);
LOG_METHOD(logTrace);
LOG_METHOD(debugMessage);
#undef LOG_METHOD
void hexDump(void* addr, int length, int numLength = 16, int columnLength = 8);
void hexDump(void* addr, int length, int numLength, int columnLength, void (*)(std::string));