Created
January 20, 2025 10:50
-
-
Save CoffeeVampir3/b9a77e2fab9af8b9d0315c541ce75ca1 to your computer and use it in GitHub Desktop.
Logging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export module Logging; | |
import std; | |
/* | |
Works exactly like std::print. Fail and ass will show verbose logging data (failure location.) | |
Logging::info("hello world"); | |
Logging::warn("{} + {}", "sweg and", 5); | |
Logging::fail("{} {}", "the ", " game"); | |
Logging::ass(false == true, "False was not true"); //outputs to cerr | |
*/ | |
namespace Logging { | |
constexpr const char *logName = "last_run_log.txt"; | |
bool logFileInitialized = false; | |
constexpr bool loggingToFileEnabled = true; | |
constexpr bool loggingToConsoleEnabled = true; | |
enum class Severity { Info, Warning, Failure, assion }; | |
constexpr auto minimumConsoleLoggingSeverity = Severity::Info; | |
constexpr auto minimumFileLoggingSeverity = Severity::Info; | |
constexpr const char *severityNameLookup[] = {"Info", "Warning", "Failure", "Assertion Failed"}; | |
constexpr const char *severityColorLookup[] = {"\033[32m", "\033[33m", "\033[31m", "\033[30m"}; //ANSI color codes | |
consteval bool meetsMinimumSeverity(Severity a, Severity b) { return static_cast<int>(a) >= static_cast<int>(b); } | |
consteval bool isSeverity(Severity a, Severity b) { return static_cast<int>(a) == static_cast<int>(b); } | |
template<Severity S, class... LogArgs> | |
struct log | |
{ | |
explicit log(std::format_string<LogArgs...> fmt, | |
LogArgs&&... args, | |
std::ostream& outputStream = std::cout, | |
const std::source_location& location = std::source_location::current()) | |
{ | |
std::ofstream logFile; | |
auto now = std::chrono::round<std::chrono::seconds>(std::chrono::system_clock::now()); | |
auto severityName = severityNameLookup[static_cast<int>(S)]; | |
auto severityColor = severityColorLookup[static_cast<int>(S)]; | |
std::string content = std::format(fmt, std::forward<LogArgs>(args)...); | |
if constexpr (loggingToConsoleEnabled && meetsMinimumSeverity(S, minimumConsoleLoggingSeverity)) { | |
constexpr auto resetColor = "\033[0m"; | |
if constexpr (meetsMinimumSeverity(S, Severity::Failure)) { | |
std::print(outputStream, | |
"[{:%Y-%m-%d %H:%M:%S}]\n {}[{}]{}\nFile name: {}\nFunction name: {}\nLine error: {}\nMessage: {}\n", | |
now, | |
severityColor, | |
severityName, | |
resetColor, | |
location.file_name(), | |
location.function_name(), | |
location.line(), | |
content); | |
} else { | |
std::print(outputStream, "[{:%Y-%m-%d %H:%M:%S}]\n {}[{}]{} {}\n", now, severityColor, severityName, resetColor, content); | |
} | |
} | |
if constexpr (!loggingToFileEnabled) { | |
return; | |
} | |
if (!logFileInitialized) { | |
logFileInitialized = true; | |
logFile.open(logName, std::ios::out | std::ios::trunc); | |
logFile.close(); | |
} | |
logFile.open(logName, std::ios::out | std::ios::app); | |
if (logFile.is_open() && meetsMinimumSeverity(S, minimumFileLoggingSeverity)) { | |
if constexpr (meetsMinimumSeverity(S, Severity::Failure)) { | |
std::print( | |
logFile, | |
"[{:%Y-%m-%d %H:%M:%S}]\n [{}]\nFile name: {}\nFunction name: {}\nLine error: {}\nMessage: {}\n", | |
now, | |
severityName, | |
location.file_name(), | |
location.function_name(), | |
location.line(), | |
content); | |
} else { | |
std::print(logFile, "[{:%Y-%m-%d %H:%M:%S}]\n [{}] {}\n", now, severityName, content); | |
} | |
logFile.close(); | |
} | |
} | |
}; | |
export template<class... LogArgs> | |
struct info : log<Severity::Info, LogArgs...> { | |
using log<Severity::Info, LogArgs...>::log; | |
}; | |
export template<class... LogArgs> | |
struct warn : log<Severity::Warning, LogArgs...> { | |
using log<Severity::Warning, LogArgs...>::log; | |
}; | |
export template<class... LogArgs> | |
struct fail : log<Severity::Failure, LogArgs...> { | |
using log<Severity::Failure, LogArgs...>::log; | |
}; | |
export template<typename... LogArgs> | |
struct ass { | |
ass( | |
const bool condition, | |
std::format_string<LogArgs...> fmt, | |
LogArgs&&... args, | |
const std::source_location& location = std::source_location::current()) | |
{ | |
if (!condition) return; | |
log<Severity::assion, LogArgs...>( | |
std::format_string<LogArgs...>(fmt), | |
std::forward<LogArgs>(args)..., | |
std::cerr, | |
location | |
); | |
std::abort(); | |
} | |
}; | |
//Deduction guides: | |
template<class... LogArgs> | |
info(std::format_string<LogArgs...>, LogArgs&&...) -> info<LogArgs...>; | |
template<class... LogArgs> | |
info(std::format_string<LogArgs...>, const std::source_location&, LogArgs&&...) -> info<LogArgs...>; | |
template<class... LogArgs> | |
warn(std::format_string<LogArgs...>, LogArgs&&...) -> warn<LogArgs...>; | |
template<class... LogArgs> | |
warn(std::format_string<LogArgs...>, const std::source_location&, LogArgs&&...) -> warn<LogArgs...>; | |
template<class... LogArgs> | |
fail(std::format_string<LogArgs...>, LogArgs&&...) -> fail<LogArgs...>; | |
template<class... LogArgs> | |
fail(std::format_string<LogArgs...>, const std::source_location&, LogArgs&&...) -> fail<LogArgs...>; | |
template<typename... LogArgs> | |
ass(bool, std::format_string<LogArgs...>, LogArgs&&...) -> ass<LogArgs...>; | |
template<typename... LogArgs> | |
ass(bool, std::format_string<LogArgs...>, const std::source_location&, LogArgs&&...) -> ass<LogArgs...>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment