334 lines
6.4 KiB
C++
334 lines
6.4 KiB
C++
#ifndef LOGGER_H
|
|
#define LOGGER_H
|
|
|
|
// Custom includes
|
|
|
|
|
|
// Enums
|
|
enum class LogModule {
|
|
ENGINE,
|
|
RENDERER,
|
|
GLFW,
|
|
CLEANUP
|
|
};
|
|
|
|
enum class LogLevel {
|
|
EDEBUG,
|
|
EINIT, // Initialization related
|
|
EINFO, // General infos
|
|
EWARN,
|
|
EERROR,
|
|
EFATAL
|
|
};
|
|
|
|
class NetLogger {
|
|
public:
|
|
struct Server{
|
|
int priority;
|
|
char* url[]; // Put the url at the end for bit optimization
|
|
};
|
|
|
|
void initNetLogger(Server server);
|
|
|
|
void logNet(char* body[], char* head, Server server);
|
|
|
|
void logNetAsync(); // Todo
|
|
private:
|
|
|
|
};
|
|
|
|
class Logger {
|
|
public:
|
|
// Members
|
|
std::string logBuffer; // Log is empty by default
|
|
std::vector<std::string_view> lines;
|
|
|
|
// Functions
|
|
template<typename... Args>
|
|
void logDisk(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
); // Logs to a file on disk
|
|
// Overload
|
|
void logDisk(std::string_view message);
|
|
|
|
template<typename... Args>
|
|
void logRAM(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
); // Logs to ram (ImGUI)
|
|
|
|
template<typename... Args>
|
|
void logConsole(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
); // Logs to the console (crashes, etc...)
|
|
|
|
template<typename... Args>
|
|
void logAll(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
); // Logs using all of the above, RAM then console and finally disk, maybe multithread (?)
|
|
|
|
template<typename... Args>
|
|
void logError(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
); // Logs to console and file, in cases of crashes or errors
|
|
|
|
void merge(std::string_view source); // Merges a source dumped logs into this
|
|
|
|
void clear();
|
|
|
|
private:
|
|
// Helper functions
|
|
static std::string_view moduleToString(LogModule m);
|
|
static std::string_view levelToString(LogLevel l);
|
|
};
|
|
|
|
#endif // End of header
|
|
|
|
|
|
#ifdef LOGGER_IMPL
|
|
#ifndef LOGGER_IMPL_H
|
|
#define LOGGER_IMPL_H
|
|
// Implementation
|
|
|
|
// Includes
|
|
//#include <httplib.h> // Todo : add it in the flake
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <chrono>
|
|
|
|
/*
|
|
void NetLogger::initNetLogger(Server server) {
|
|
httplib::Client cli(server.url)
|
|
// Todo : add error handling
|
|
}
|
|
*/
|
|
template<typename... Args>
|
|
void Logger::logRAM(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
) {
|
|
auto now = std::chrono::system_clock::now();
|
|
auto timestamp = std::format("{:%Y-%m-%d %H:%M}", now);
|
|
auto start = logBuffer.size();
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(logBuffer),
|
|
"[{}] ",
|
|
timestamp
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(logBuffer),
|
|
"[{}:{}] ",
|
|
moduleToString(module),
|
|
levelToString(level)
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(logBuffer),
|
|
fmt::runtime(message),
|
|
std::forward<Args>(args)...
|
|
);
|
|
|
|
logBuffer.push_back('\n');
|
|
auto end = logBuffer.size();
|
|
lines.emplace_back(logBuffer.data() + start, end - start);
|
|
}
|
|
|
|
template<typename... Args>
|
|
void Logger::logConsole(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
) {
|
|
std::string tempBuffer;
|
|
auto now = std::chrono::system_clock::now();
|
|
auto timestamp = std::format("{:%Y-%m-%d %H:%M}", now);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
"[{}] ",
|
|
timestamp
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
"[{}:{}] ",
|
|
moduleToString(module),
|
|
levelToString(level)
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
fmt::runtime(message),
|
|
std::forward<Args>(args)...
|
|
);
|
|
|
|
std::cout.write(tempBuffer.data(), tempBuffer.size());
|
|
std::cout.put('\n');
|
|
}
|
|
|
|
template<typename... Args>
|
|
void Logger::logDisk(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
) {
|
|
// Open the logfile
|
|
std::ofstream logFile ("log.txt", std::ios::out | std::ios::app);
|
|
|
|
if (!logFile.good()) {
|
|
throw std::runtime_error("Failed to open logfile !");
|
|
}
|
|
|
|
// Create a temporary buffer
|
|
std::string tempBuffer;
|
|
auto now = std::chrono::system_clock::now();
|
|
auto timestamp = std::format("{:%Y-%m-%d %H:%M}", now);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
"[{}] ",
|
|
timestamp
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
"[{}:{}] ",
|
|
moduleToString(module),
|
|
levelToString(level)
|
|
);
|
|
|
|
fmt::format_to(
|
|
std::back_inserter(tempBuffer),
|
|
fmt::runtime(message),
|
|
std::forward<Args>(args)...
|
|
);
|
|
|
|
logFile << tempBuffer << '\n';
|
|
logFile.close();
|
|
}
|
|
|
|
// Overload to inject a message
|
|
void Logger::logDisk(std::string_view message) {
|
|
std::ofstream logFile ("log.txt", std::ios::out | std::ios::app);
|
|
|
|
if (!logFile.good()) {
|
|
throw std::runtime_error("Failed to open logfile !");
|
|
}
|
|
|
|
logFile << message << '\n';
|
|
logFile.close();
|
|
}
|
|
|
|
template<typename... Args>
|
|
void Logger::logAll(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
) {
|
|
// Logs to all targets !
|
|
logRAM(
|
|
module,
|
|
level,
|
|
message,
|
|
args...
|
|
);
|
|
|
|
logConsole(
|
|
module,
|
|
level,
|
|
message,
|
|
args...
|
|
);
|
|
|
|
logDisk(
|
|
module,
|
|
level,
|
|
message,
|
|
args...
|
|
);
|
|
}
|
|
|
|
template<typename... Args>
|
|
void Logger::logError(
|
|
LogModule module,
|
|
LogLevel level,
|
|
std::string_view message,
|
|
Args&&... args
|
|
) {
|
|
logDisk(
|
|
module,
|
|
level,
|
|
message,
|
|
args...
|
|
);
|
|
|
|
logConsole(
|
|
module,
|
|
level,
|
|
message,
|
|
args...
|
|
);
|
|
}
|
|
|
|
|
|
void Logger::merge(std::string_view source) {
|
|
/*
|
|
This merges a dumped logger into this one
|
|
Assumes the other logger is already formated.
|
|
This allows to add arbitrary strings into the logs
|
|
*/
|
|
logBuffer += source;
|
|
}
|
|
|
|
void Logger::clear() {
|
|
logBuffer.clear();
|
|
}
|
|
|
|
std::string_view Logger::moduleToString(LogModule m) {
|
|
using enum LogModule;
|
|
switch (m) {
|
|
case ENGINE: return "Engine";
|
|
case RENDERER: return "Renderer";
|
|
case GLFW: return "GLFW";
|
|
case CLEANUP: return "CLEANUP";
|
|
default: return "Unkown";
|
|
}
|
|
}
|
|
|
|
std::string_view Logger::levelToString(LogLevel l) {
|
|
using enum LogLevel;
|
|
switch (l) {
|
|
case EDEBUG: return "Debug";
|
|
case EINFO: return "Info";
|
|
case EINIT: return "Init";
|
|
case EWARN: return "Warn";
|
|
case EERROR: return "Error";
|
|
case EFATAL: return "Fatal";
|
|
default: return "???";
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#endif
|