feat(logger): handles ownership of streams
This commit is contained in:
parent
567c1ae1c0
commit
b17c160d5c
@ -8,5 +8,6 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <utility>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <pch.hpp>
|
#include <pch.hpp>
|
||||||
|
|
||||||
namespace ICEngine {
|
namespace ICEngine {
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
OFF = 0,
|
OFF = 0,
|
||||||
TRACE,
|
TRACE,
|
||||||
@ -22,9 +21,10 @@ namespace ICEngine {
|
|||||||
private:
|
private:
|
||||||
Logger(const char *name, std::ostream *stream) : name(name) {
|
Logger(const char *name, std::ostream *stream) : name(name) {
|
||||||
if (stream) {
|
if (stream) {
|
||||||
streams.push_back(stream);
|
streams.push_back(std::unique_ptr<std::ostream>(stream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class Log;
|
friend class Log;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -32,26 +32,27 @@ namespace ICEngine {
|
|||||||
this->level = level;
|
this->level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddStream(std::ostream * stream) {
|
void AddStream(std::unique_ptr<std::ostream> stream) {
|
||||||
this->streams.push_back(stream);
|
this->streams.push_back(std::move(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Log(LogLevel level, const char *file, int line, const char *func, const std::string &formatStr, Args &&... args) {
|
void Log(LogLevel level, const char *file, int line, const char *func, const std::string &formatStr,
|
||||||
|
Args &&... args) {
|
||||||
// TODO: Create a crash handler and manage fatal messages separately (creates crashdump)
|
// TODO: Create a crash handler and manage fatal messages separately (creates crashdump)
|
||||||
// TODO: Allow user to create their own class that inherits Fatal Handler so they can implement it themselves
|
// TODO: Allow user to create their own class that inherits Fatal Handler so they can implement it themselves
|
||||||
if (level < this->level) return;
|
if (level < this->level) return;
|
||||||
std::string formattedMessage = format(formatStr, std::forward<Args>(args)...);
|
std::string formattedMessage = format(formatStr, std::forward<Args>(args)...);
|
||||||
std::string logMessage = formatMessage(level, file, line, func, formattedMessage);
|
std::string logMessage = formatMessage(level, file, line, func, formattedMessage);
|
||||||
|
|
||||||
for (auto stream: streams) {
|
for (const auto &stream: streams) {
|
||||||
(*stream) << logMessage << std::endl;
|
(*stream) << logMessage << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *name;
|
const char *name;
|
||||||
std::vector<std::ostream *> streams;
|
std::vector<std::unique_ptr<std::ostream> > streams;
|
||||||
LogLevel level = DEBUG;
|
LogLevel level = DEBUG;
|
||||||
|
|
||||||
static const char *levelToString(LogLevel level) {
|
static const char *levelToString(LogLevel level) {
|
||||||
@ -84,7 +85,7 @@ namespace ICEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
std::string format(const std::string &formatStr, Args&&... args) {
|
std::string format(const std::string &formatStr, Args &&... args) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
formatHelper(oss, formatStr, std::forward<Args>(args)...);
|
formatHelper(oss, formatStr, std::forward<Args>(args)...);
|
||||||
return oss.str();
|
return oss.str();
|
||||||
@ -95,7 +96,8 @@ namespace ICEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
void formatHelper(std::ostringstream &oss, const std::string &formatStr, T &&firstArg, Args&&... remainingArgs) {
|
void formatHelper(std::ostringstream &oss, const std::string &formatStr, T &&firstArg,
|
||||||
|
Args &&... remainingArgs) {
|
||||||
size_t pos = formatStr.find("{}");
|
size_t pos = formatStr.find("{}");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
oss << formatStr.substr(0, pos) << std::forward<T>(firstArg);
|
oss << formatStr.substr(0, pos) << std::forward<T>(firstArg);
|
||||||
@ -105,13 +107,14 @@ namespace ICEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formats the log message with metadata (timestamp, file, line, etc.)
|
std::string formatMessage(LogLevel level, const char *file, int line, const char *func,
|
||||||
std::string formatMessage(LogLevel level, const char *file, int line, const char *func, const std::string &message) {
|
const std::string &message) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << getCurrentTime() << " ";
|
oss << getCurrentTime() << " ";
|
||||||
oss << truncateFilePath(file) << ":" << line << ":" << func << " ";
|
oss << truncateFilePath(file) << ":" << line << ":" << func << " ";
|
||||||
oss << "[" << levelToString(level) << "] ";
|
oss << "[" << name << "] ";
|
||||||
oss << "[" << name << "]: " << message;
|
oss << "[" << levelToString(level) << "]: ";
|
||||||
|
oss << message;
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -119,8 +122,16 @@ namespace ICEngine {
|
|||||||
class Log {
|
class Log {
|
||||||
public:
|
public:
|
||||||
static void Init() {
|
static void Init() {
|
||||||
|
static bool isInitialized = false;
|
||||||
|
if (isInitialized) {
|
||||||
|
GetCoreLogger()->Log(WARN, __FILE__, __LINE__, __FUNCTION__,
|
||||||
|
"Logger already initialized. Skipping re-initialization.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
GetCoreLogger();
|
GetCoreLogger();
|
||||||
GetAppLogger();
|
GetAppLogger();
|
||||||
|
|
||||||
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Logger> &GetCoreLogger() {
|
static std::shared_ptr<Logger> &GetCoreLogger() {
|
||||||
@ -135,7 +146,9 @@ namespace ICEngine {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Log() = delete;
|
Log() = delete;
|
||||||
|
|
||||||
Log(const Log &) = delete;
|
Log(const Log &) = delete;
|
||||||
|
|
||||||
Log &operator=(const Log &) = delete;
|
Log &operator=(const Log &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,5 +180,5 @@ namespace ICEngine {
|
|||||||
#define LOG_ERROR(message, ...)
|
#define LOG_ERROR(message, ...)
|
||||||
#define LOG_CRITICAL(message, ...)
|
#define LOG_CRITICAL(message, ...)
|
||||||
#define LOG_FATAL(message, ...)
|
#define LOG_FATAL(message, ...)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user