Compare commits
No commits in common. "ea1f25d26b17de384e7983ecf1dc81c7505f66d0" and "8afaa3cce30f46d74d00e1af702af75bdc9723d7" have entirely different histories.
ea1f25d26b
...
8afaa3cce3
58
.clang-format
Normal file
58
.clang-format
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# Generated from CLion C/C++ Code Style settings
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
ColumnLimit: 120
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^".*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 4
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: All
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
TabWidth: 4
|
||||||
|
...
|
@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <format>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
@ -6,166 +6,13 @@
|
|||||||
|
|
||||||
#include <pch.hpp>
|
#include <pch.hpp>
|
||||||
|
|
||||||
namespace ICEngine {
|
class Logger {
|
||||||
|
public:
|
||||||
|
void logVersion() {
|
||||||
|
std::cout << "ICEngine Version: " << PROJECT_VERSION << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
enum LogLevel {
|
void logCrash(const std::string& errorMessage) {
|
||||||
OFF = 0,
|
std::cerr << "Crash detected in version " << PROJECT_VERSION << ": " << errorMessage << std::endl;
|
||||||
TRACE,
|
}
|
||||||
DEBUG,
|
};
|
||||||
WARN,
|
|
||||||
ERROR,
|
|
||||||
CRITICAL,
|
|
||||||
FATAL
|
|
||||||
};
|
|
||||||
|
|
||||||
class Logger {
|
|
||||||
private:
|
|
||||||
Logger(const char *name, std::ostream *stream) : name(name) {
|
|
||||||
if (stream) {
|
|
||||||
streams.push_back(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
friend class Log;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void SetLevel(LogLevel level) {
|
|
||||||
this->level = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddStream(std::ostream * stream) {
|
|
||||||
this->streams.push_back(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... 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: Allow user to create their own class that inherits Fatal Handler so they can implement it themselves
|
|
||||||
if (level < this->level) return;
|
|
||||||
std::string formattedMessage = format(formatStr, std::forward<Args>(args)...);
|
|
||||||
std::string logMessage = formatMessage(level, file, line, func, formattedMessage);
|
|
||||||
|
|
||||||
for (auto stream: streams) {
|
|
||||||
(*stream) << logMessage << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char *name;
|
|
||||||
std::vector<std::ostream *> streams;
|
|
||||||
LogLevel level = DEBUG;
|
|
||||||
|
|
||||||
static const char *levelToString(LogLevel level) {
|
|
||||||
switch (level) {
|
|
||||||
case TRACE: return "TRACE";
|
|
||||||
case DEBUG: return "DEBUG";
|
|
||||||
case WARN: return "WARN";
|
|
||||||
case ERROR: return "ERROR";
|
|
||||||
case CRITICAL: return "CRITICAL";
|
|
||||||
case FATAL: return "FATAL";
|
|
||||||
default: return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getCurrentTime() {
|
|
||||||
auto now = std::chrono::system_clock::now();
|
|
||||||
std::time_t time = std::chrono::system_clock::to_time_t(now);
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::put_time(std::localtime(&time), "%Y/%m/%d %H:%M:%S");
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string truncateFilePath(const char *file) {
|
|
||||||
std::string path(file);
|
|
||||||
size_t pos = path.find_last_of("/\\");
|
|
||||||
if (pos != std::string::npos && pos > 3) {
|
|
||||||
return "..." + path.substr(pos - 3);
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
std::string format(const std::string &formatStr, Args&&... args) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
formatHelper(oss, formatStr, std::forward<Args>(args)...);
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void formatHelper(std::ostringstream &oss, const std::string &formatStr) {
|
|
||||||
oss << formatStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
void formatHelper(std::ostringstream &oss, const std::string &formatStr, T &&firstArg, Args&&... remainingArgs) {
|
|
||||||
size_t pos = formatStr.find("{}");
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
oss << formatStr.substr(0, pos) << std::forward<T>(firstArg);
|
|
||||||
formatHelper(oss, formatStr.substr(pos + 2), std::forward<Args>(remainingArgs)...);
|
|
||||||
} else {
|
|
||||||
oss << formatStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formats the log message with metadata (timestamp, file, line, etc.)
|
|
||||||
std::string formatMessage(LogLevel level, const char *file, int line, const char *func, const std::string &message) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << getCurrentTime() << " ";
|
|
||||||
oss << truncateFilePath(file) << ":" << line << ":" << func << " ";
|
|
||||||
oss << "[" << levelToString(level) << "] ";
|
|
||||||
oss << "[" << name << "]: " << message;
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Log {
|
|
||||||
public:
|
|
||||||
static void Init() {
|
|
||||||
GetCoreLogger();
|
|
||||||
GetAppLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<Logger> &GetCoreLogger() {
|
|
||||||
static std::shared_ptr<Logger> CoreLogger(new Logger("CORE", &std::cout));
|
|
||||||
return CoreLogger;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<Logger> &GetAppLogger() {
|
|
||||||
static std::shared_ptr<Logger> AppLogger(new Logger("APP", &std::cout));
|
|
||||||
return AppLogger;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Log() = delete;
|
|
||||||
Log(const Log &) = delete;
|
|
||||||
Log &operator=(const Log &) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define CORE_LOG_TRACE(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::TRACE, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define CORE_LOG_DEBUG(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::DEBUG, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define CORE_LOG_WARN(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::WARN, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define CORE_LOG_ERROR(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::ERROR, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define CORE_LOG_CRITICAL(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::CRITICAL, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define CORE_LOG_FATAL(message, ...) ICEngine::Log::GetCoreLogger()->Log(ICEngine::FATAL, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define LOG_TRACE(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::TRACE, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define LOG_DEBUG(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::DEBUG, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define LOG_WARN(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::WARN, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define LOG_ERROR(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::ERROR, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define LOG_CRITICAL(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::CRITICAL, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#define LOG_FATAL(message, ...) ICEngine::Log::GetAppLogger()->Log(ICEngine::FATAL, __FILE__, __LINE__, __FUNCTION__, message, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define CORE_LOG_TRACE(message, ...)
|
|
||||||
#define CORE_LOG_DEBUG(message, ...)
|
|
||||||
#define CORE_LOG_WARN(message, ...)
|
|
||||||
#define CORE_LOG_ERROR(message, ...)
|
|
||||||
#define CORE_LOG_CRITICAL(message, ...)
|
|
||||||
#define CORE_LOG_FATAL(message, ...)
|
|
||||||
|
|
||||||
#define LOG_TRACE(message, ...)
|
|
||||||
#define LOG_DEBUG(message, ...)
|
|
||||||
#define LOG_WARN(message, ...)
|
|
||||||
#define LOG_ERROR(message, ...)
|
|
||||||
#define LOG_CRITICAL(message, ...)
|
|
||||||
#define LOG_FATAL(message, ...)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
@ -3,69 +3,9 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <ICEngine.hpp>
|
#include <ICEngine.hpp>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
void ShowLogger();
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ShowLogger();
|
Logger logger;
|
||||||
return 0;
|
logger.logVersion();
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
void ShowLogger() {
|
|
||||||
// The logger needs to be initialized before you can use it.
|
|
||||||
// This will be done by the engine, NEVER the user.
|
|
||||||
ICEngine::Log::Init();
|
|
||||||
|
|
||||||
// Before using the logger macros, you may want to configure logging options such as log levels and output streams.
|
|
||||||
// By default, the logger outputs to std::cout, but you can add more streams (e.g., files) or set the log level as needed.
|
|
||||||
|
|
||||||
// Logging Levels:
|
|
||||||
// - OFF
|
|
||||||
// - TRACE
|
|
||||||
// - DEBUG
|
|
||||||
// - WARN
|
|
||||||
// - ERROR
|
|
||||||
// - CRITICAL
|
|
||||||
// - FATAL
|
|
||||||
ICEngine::Log::GetCoreLogger()->SetLevel(ICEngine::TRACE);
|
|
||||||
ICEngine::Log::GetAppLogger()->SetLevel(ICEngine::TRACE);
|
|
||||||
|
|
||||||
// You can have multiple log streams, ie console + file etc
|
|
||||||
// You do not need to have the same streams for each logger
|
|
||||||
#include <fstream>
|
|
||||||
std::ofstream coreFileStream("core_logs.txt");
|
|
||||||
std::ofstream appFileStream("app_logs.txt");
|
|
||||||
|
|
||||||
ICEngine::Log::GetCoreLogger()->AddStream(&coreFileStream);
|
|
||||||
ICEngine::Log::GetAppLogger()->AddStream(&appFileStream);
|
|
||||||
|
|
||||||
// You can log multiple different types with formatting
|
|
||||||
int age = 30;
|
|
||||||
std::string module = "Network";
|
|
||||||
|
|
||||||
// CORE logger is intended for internal engine or core-level logging
|
|
||||||
// In most cases, you won't need to use CORE logging in game/application code,
|
|
||||||
// but it’s available for engine-level diagnostics if necessary
|
|
||||||
CORE_LOG_TRACE("Initializing {} with age {}", module, age); // Logs a trace-level message, useful for very detailed information
|
|
||||||
CORE_LOG_DEBUG("This is an example of a debug message"); // Logs a debug message, typically used for debugging purposes
|
|
||||||
CORE_LOG_WARN("This is an example of a warn message"); // Logs a warning, indicating a non-critical issue that should be investigated
|
|
||||||
CORE_LOG_ERROR("This is an example of an error message"); // Logs an error, signaling that something has gone wrong but the engine can still run
|
|
||||||
CORE_LOG_CRITICAL("This is an example of a critical message\n"); // Logs a critical issue, often indicating a major problem in the core system that needs immediate attention.
|
|
||||||
// CORE_LOG_FATAL: Logs a fatal error that crashes the application. Fatal errors in the core usually lead to dumping information into crash logs
|
|
||||||
// and stopping the program. Use with extreme caution and only in situations where the application can't recover
|
|
||||||
// CORE_LOG_FATAL("This is an example of a fatal message");
|
|
||||||
|
|
||||||
|
|
||||||
// These macros are designed for logging from your game or application code
|
|
||||||
// They allow you to monitor application flow, errors, and warnings from the perspective of the game logic or app layer
|
|
||||||
LOG_TRACE("App took longer to respond than expected: {} seconds", 2.34); // Logs a trace message, ideal for fine-grained, verbose debugging details
|
|
||||||
LOG_DEBUG("This is an example of a debug message"); // Logs a debug message, typically used to help trace the execution during development
|
|
||||||
LOG_WARN("This is an example of a warn message"); // Logs a warning, indicating something unexpected happened, but the application can continue running
|
|
||||||
LOG_ERROR("This is an example of an error message"); // Logs an error, signaling that an issue occurred that may require attention but is not catastrophic
|
|
||||||
LOG_CRITICAL("This is an example of a critical message"); // Logs a critical message, suggesting something very wrong happened, but the program may still attempt to run
|
|
||||||
|
|
||||||
// LOG_FATAL: Logs a fatal error in the application layer. This will trigger the Fatal Handler, which you can override
|
|
||||||
// The Fatal Handler provides a mechanism for handling unrecoverable errors gracefully, allowing you to define how the application reacts to fatal crashes
|
|
||||||
// LOG_FATAL("This is an example of log fatal crash!");
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user