109 lines
2.8 KiB
C++
109 lines
2.8 KiB
C++
//
|
|
// Created by marob on 12/27/2023.
|
|
//
|
|
|
|
#ifndef LOGGER_H
|
|
#define LOGGER_H
|
|
#include "ISXMr.h"
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
|
|
enum class LogLevel {
|
|
Debug,
|
|
Info,
|
|
Warning,
|
|
Error
|
|
};
|
|
|
|
class Logger {
|
|
public:
|
|
Logger(const Logger &) = delete;
|
|
|
|
Logger &operator=(const Logger &) = delete;
|
|
|
|
static Logger &instance() {
|
|
static Logger singleton;
|
|
return singleton;
|
|
}
|
|
|
|
void SetLogLevel(LogLevel level) {
|
|
currentLogLevel = level;
|
|
}
|
|
|
|
Logger &operator<<(LogLevel level) {
|
|
SetLogLevel(level);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
Logger &operator<<(const T &value) {
|
|
std::ostringstream &tss = getThreadLocalStream();
|
|
tss << value;
|
|
return *this;
|
|
}
|
|
|
|
Logger &operator<<(std::ostream & (*pf)(std::ostream &)) {
|
|
std::ostringstream &tss = getThreadLocalStream();
|
|
pf(tss);
|
|
if (pf == static_cast<std::ostream& (*)(std::ostream &)>(std::endl)) {
|
|
string str = tss.str();
|
|
pISInterface->Printf(formatMessage(str).c_str());
|
|
tss.str("");
|
|
tss.clear();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
Logger() = default;
|
|
|
|
LogLevel currentLogLevel = LogLevel::Info;
|
|
|
|
static std::ostringstream &getThreadLocalStream() {
|
|
thread_local std::ostringstream tss;
|
|
return tss;
|
|
}
|
|
|
|
static void rtrim_newlines(std::string &s) {
|
|
s.erase(std::find_if(s.rbegin(), s.rend(), [](const unsigned char ch) {
|
|
return ch != '\n' && ch != '\r';
|
|
}).base(), s.end());
|
|
}
|
|
|
|
std::string formatMessage(std::string &message) const {
|
|
const auto now = std::chrono::system_clock::now();
|
|
const auto now_c = std::chrono::system_clock::to_time_t(now);
|
|
|
|
std::tm now_tm;
|
|
localtime_s(&now_tm, &now_c); // Thread-safe on Windows
|
|
|
|
std::ostringstream oss;
|
|
rtrim_newlines(message);
|
|
oss << "[" << std::put_time(&now_tm, "%H:%M:%S") << "] - " << getColorCode(currentLogLevel) << message << "\ax";
|
|
// Reset color to default at the end
|
|
return oss.str();
|
|
}
|
|
|
|
static std::string getColorCode(const LogLevel level) {
|
|
switch (level) {
|
|
case LogLevel::Debug: return "\ay"; // Yellow
|
|
case LogLevel::Info: return "\ag"; // Green
|
|
case LogLevel::Warning: return "\ao"; // Orange
|
|
case LogLevel::Error: return "\ar"; // Red
|
|
default: return "\aw"; // White
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// Global logger instance for ease of access
|
|
#define logger Logger::instance()
|
|
#define log Logger::instance() << LogLevel::Info
|
|
#define logd Logger::instance() << LogLevel::Debug
|
|
#define logw Logger::instance() << LogLevel::Warning
|
|
#define loge Logger::instance() << LogLevel::Error
|
|
|
|
|
|
#endif //LOGGER_H
|