Rewrote jlog entirely. Macros are no longer needed thanks to C++ builtin shit. There's a lot to cover, so just read the source code if you actually care.

This commit is contained in:
2024-08-08 14:25:34 -04:00
parent e0b6879ec5
commit 404c3dceba
7 changed files with 337 additions and 466 deletions

130
include/jlog/formatter.hpp Normal file
View File

@@ -0,0 +1,130 @@
#pragma once
#include "token.hpp"
namespace jlog {
/// Returns a string timestamp in the format of 'YYYY-MM-DD hh:mm:ss.ms'
std::string get_timestamp();
/// Returns a pseudo-"stacktrace" formatted sequence of tokens.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> trace_format(
const std::string &func,
const std::string &file,
int line);
/// Returns a formatted sequence of tokens given a severity and message.
/// @param severity_name The severity tag to prefix to the message. Could theoretically also be a context.
/// @param message The actual message to include
/// @param severity_cc The colorcode to assign to the severity.
std::vector<token> log_format(
const std::string &severity_name,
const std::string &message,
const mcolor::ansiColors::Colors &severity_cc = mcolor::ansiColors::Colors::FG_WHITE);
/// Returns a more detailed formatted sequence of tokens.
/// @param severity_name The severity tag to prefix to the message. Could theoretically also be a context.
/// @param message The actual message to include
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
/// @param severity_cc The colorcode to assign to the severity.
std::vector<token> log_format(
const std::string &severity_name,
const std::string &message,
const std::string &func,
const std::string &file,
int line,
const mcolor::ansiColors::Colors &severity_cc = mcolor::ansiColors::Colors::FG_WHITE);
/// Returns a token sequence pre-formatted for the INFO log level.
/// @param message The message to send out.
std::vector<token> info_format(const std::string &message);
/// Returns a token sequence pre-formatted for the INFO log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> info_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the WARNING log level.
/// @param message The message to send out.
std::vector<token> warning_format(const std::string &message);
/// Returns a token sequence pre-formatted for the WARNING log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> warning_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the ERROR log level.
/// @param message The message to send out.
std::vector<token> error_format(const std::string &message);
/// Returns a token sequence pre-formatted for the ERROR log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> error_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the FATAL log level.
/// @param message The message to send out.
std::vector<token> fatal_format(const std::string &message);
/// Returns a token sequence pre-formatted for the FATAL log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> fatal_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the VERBOSE log level.
/// @param message The message to send out.
std::vector<token> verbose_format(const std::string &message);
/// Returns a token sequence pre-formatted for the VERBOSE log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> verbose_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the DEBUG log level.
/// @param message The message to send out.
std::vector<token> debug_format(const std::string &message);
/// Returns a token sequence pre-formatted for the DEBUG log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> debug_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
}

View File

@@ -10,22 +10,14 @@
#include <string>
#include <Event.h>
#include <mcolor.h>
#include "token.hpp"
#include "formatter.hpp"
#include "source_location"
#ifdef __linux__
#define FUNCTION __PRETTY_FUNCTION__
#endif
#ifdef _WIN32
#define FUNCTION __FUNCSIG__
#endif
namespace jlog
{
namespace jlog {
/// Severity levels for logging. Higher numbers filter less messages out.
/// @see LOG_LEVEL macro
enum class severity : uint8_t
{
enum class severity : uint8_t {
none, // Show no output
fatal, // Show only fatal errors
error, // Show fatal and not-necessarily-fatal errors
@@ -34,210 +26,47 @@ namespace jlog
debug, // Show debugging messages (Basically everything).
};
inline severity loglevel = severity::debug; // Default log level always debug
inline bool console_logging = true;
struct LogEntry
{
severity level;
std::string content;
std::string timestamp;
};
// TODO: Fully implement logging callback.
static Event<LogEntry> on_log = Event<LogEntry>();
inline std::vector<LogEntry> log_history;
/// A single piece of a logging message, with color code, content, and delimiter
/// These are strung together to build full logger messages in a flexible manner.
struct token
{
mcolor::ansiColors::Colors colorCode = mcolor::ansiColors::Colors::FG_DEFAULT;
std::string content = "";
std::string delimiter = "[]";
};
void set_default_logfile(const std::string& filename);
/// Returns a string timestamp in the format of 'YYYY-MM-DD hh:mm:ss.ms'
std::string get_timestamp();
/// Writes an input string directly to standard output
/// @note Does not append a newline to the message.
void log_to_console(const std::string& message);
/// Writes an input string directly to the default destination logfile
/// @note Does not append a newline to the message.
/// @see set_default_logfile()
void log_to_file(const std::string& message);
void log_to_console(const std::string &message);
/// Writes an input string directly to the specified destination logfile
/// @note Does not append a newline to the message.
void log_to_file(const std::string& filename, const std::string& message);
/// Writes an input string directly to the specified output stream
/// @note Does not append a newline to the message.
void log_to_stream(std::ostream stream, const std::string& message);
void log_to_file(const std::string &filename, const std::string &message);
/// These are helper functions designed to be wrapped around for easier custom logger building.
/// @note This file is implemented differently per-platform to handle differences in console color handling.
/// @see windows/jlog.cpp linux/jlog.cpp
std::string toks2msg(std::vector<token> tokens, std::function<std::string(token)> formatter);
std::string consoleMsgFormatter(token t);
std::string logfileMsgFormatter(token t);
std::string toks2consoleMsg(std::vector<token> tokens);
std::string toks2logfileMsg(std::vector<token> tokens);
class Logger {
public:
//Logger(const std::string& context, const mcolor::ansiColors::Colors&);
virtual void log(const std::string &message) = 0;
/// Parses a sequence of tokens into a printable message, and logs to the following destinations:
/// standard output (console)
/// output file (default)
/// logging callback (Event)
/// @note This file is implemented differently per-platform to handle differences in console color handling.
/// @see windows/jlog.cpp linux/jlog.cpp
void log(const std::vector<token>& tokens, const std::string& filename);
void log(const std::vector<token>& tokens);
void ltlog(const std::vector<token>& tokens); // Just for debug purposes
virtual void log_trace(const std::string &message, const std::source_location& location = std::source_location::current()) = 0;
#pragma region Generic Formatters
/// Returns a pseudo-"stacktrace" formatted sequence of tokens.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> trace_format(
const std::string& func,
const std::string& file,
int line);
/// Returns a formatted sequence of tokens given a severity and message.
/// @param severity_name The severity tag to prefix to the message. Could theoretically also be a context.
/// @param message The actual message to include
/// @param severity_cc The colorcode to assign to the severity.
std::vector<token> log_format(
const std::string& severity_name,
const std::string& message,
const mcolor::ansiColors::Colors& severity_cc = mcolor::ansiColors::Colors::FG_WHITE);
/// Returns a more detailed formatted sequence of tokens.
/// @param severity_name The severity tag to prefix to the message. Could theoretically also be a context.
/// @param message The actual message to include
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
/// @param severity_cc The colorcode to assign to the severity.
std::vector<token> log_detailed_format(
const std::string& severity_name,
const std::string& message,
const std::string& func,
const std::string& file,
int line,
const mcolor::ansiColors::Colors& severity_cc = mcolor::ansiColors::Colors::FG_WHITE);
/// Returns a token sequence pre-formatted for the INFO log level.
/// @param message The message to send out.
std::vector<token> info_format(const std::string& message);
/// Returns a token sequence pre-formatted for the INFO log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> info_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the WARNING log level.
/// @param message The message to send out.
std::vector<token> warning_format(const std::string& message);
/// Returns a token sequence pre-formatted for the WARNING log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> warning_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the ERROR log level.
/// @param message The message to send out.
std::vector<token> error_format(const std::string& message);
/// Returns a token sequence pre-formatted for the ERROR log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> error_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the FATAL log level.
/// @param message The message to send out.
std::vector<token> fatal_format(const std::string& message);
/// Returns a token sequence pre-formatted for the FATAL log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> fatal_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the VERBOSE log level.
/// @param message The message to send out.
std::vector<token> verbose_format(const std::string& message);
/// Returns a token sequence pre-formatted for the VERBOSE log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> verbose_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
/// Returns a token sequence pre-formatted for the DEBUG log level.
/// @param message The message to send out.
std::vector<token> debug_format(const std::string& message);
/// Returns a token sequence pre-formatted for the DEBUG log level.
/// @param message The message to send out.
/// @param func The function name/signature to trace back to. Should be provided by a __FUNCTION__ macro variant.
/// @param file The file name to trace back to. Should be provided by a __FILE__ macro variant.
/// @param line The source-code line to trace back to. Should be provided by a __LINE__ macro variant.
std::vector<token> debug_detailed_format(
const std::string &message,
const std::string &func,
const std::string &file,
int line);
#pragma endregion
};
}
#define INFO(i) if (jlog::loglevel >= jlog::severity::none) { jlog::log(jlog::info_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
namespace jlog::GlobalLogger {
class GlobalLogger : jlog::Logger {
public:
GlobalLogger(const std::string& context, const mcolor::ansiColors::Colors& colorcode);
void log(const std::string &message);
void log_trace(const std::string &message, const std::source_location& location = std::source_location::current());
std::string Context() { return context; };
public:
bool enabled = true;
//bool record_console = true;
//bool record_file = true;
// Changing this is bad practice, but we're allowing it for niche cases
std::string logfile = "latest.log";
private:
std::string context;
mcolor::ansiColors::Colors colorcode;
#define VERBOSE(i) if (jlog::loglevel >= jlog::severity::verbose) { jlog::log(jlog::verbose_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
#define DEBUG(i) if (jlog::loglevel >= jlog::severity::debug) { jlog::log(jlog::debug_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
#define WARNING(i) if (jlog::loglevel >= jlog::severity::warning) { jlog::log(jlog::warning_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
#define ERROR(i) if (jlog::loglevel >= jlog::severity::error) { jlog::log(jlog::error_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
#define FATAL(i) if (jlog::loglevel >= jlog::severity::fatal) { jlog::log(jlog::fatal_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
#define LOGLEVEL(i) jlog::loglevel = i;
#define CONSOLELOGGING(i) jlog::console_logging = i
#define LOGTEST(i) if (jlog::loglevel >= jlog::severity::none) { jlog::ltlog(jlog::info_detailed_format(i, FUNCTION, __FILE__, __LINE__)); }
};
GlobalLogger INFO{"INFO", mcolor::ansiColors::Colors::FG_GREEN};
GlobalLogger WARNING{"WARNING", mcolor::ansiColors::Colors::FG_YELLOW};
GlobalLogger ERROR{"ERROR", mcolor::ansiColors::Colors::FG_RED};
GlobalLogger FATAL{"FATAL", mcolor::ansiColors::Colors::FG_BRIGHT_RED};
GlobalLogger VERBOSE{"VERBOSE", mcolor::ansiColors::Colors::FG_CYAN};
GlobalLogger DEBUG{"DEBUG", mcolor::ansiColors::Colors::FG_MAGENTA};
}

20
include/jlog/token.hpp Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <functional>
namespace jlog {
/// A single piece of a logging message, with color code, content, and delimiter
/// These are strung together to build full logger messages in a flexible manner.
struct token {
mcolor::ansiColors::Colors colorCode = mcolor::ansiColors::Colors::FG_DEFAULT;
std::string content = "";
std::string delimiter = "[]";
};
/// These are helper functions designed to be wrapped around for easier custom logger building.
std::string toks2msg(std::vector<token> tokens, std::function<std::string(token)> formatter);
std::string consoleMsgFormatter(token t);
std::string logfileMsgFormatter(token t);
std::string toks2consoleMsg(std::vector<token> tokens);
std::string toks2logfileMsg(std::vector<token> tokens);
}

View File

@@ -4,44 +4,23 @@
// Contact: josh@redacted.cc
// Contributors: william@redacted.cc maxi@redacted.cc
// This work is dedicated to the public domain.
#include <jlog/jlog.hpp>
// Writing custom wrappers for jlog is super easy!
/*void coollog(std::vector<jlog::token> tokens) {
std::vector<jlog::token> wtokens;
auto group = jlog::token{.content = "COOLLOGGER"};
wtokens.push_back(group);
wtokens.insert(wtokens.end(), tokens.begin(), tokens.end());
jlog::log(wtokens);
}*/
// We can either define custom logging macros or redefine jlog's builtin macros.
//#define COOLINFO(i) coollog(jlog::info_format(i));
//#define COOLINFOTRACE(i) coollog(jlog::info_detailed_format(i, FUNCTION, __FILE__, __LINE__));
int main()
{
LOGLEVEL(jlog::severity::debug); // <- see jlog::severity for full list of log levels
CONSOLELOGGING(true); // <- Set to true or false to enable/disable logging to console. Useful for release builds of a program.
#ifdef _WIN32
jlog::set_default_logfile("NUL");
#else
jlog::set_default_logfile("/dev/null");
#endif
jlog::GlobalLogger::INFO.log("This dick");
jlog::GlobalLogger::DEBUG.log("This dick");
jlog::GlobalLogger::VERBOSE.log("This dick");
jlog::GlobalLogger::WARNING.log("This dick");
jlog::GlobalLogger::ERROR.log("This dick");
jlog::GlobalLogger::FATAL.log("This dick");
INFO("This is barely useful information.");
DEBUG("Debugging Information");
VERBOSE("Yadda Yadda Yadda");
WARNING("Slight miscalculation!");
ERROR("Oops, something went wrong.");
FATAL("Unrecoverable Error!!!");
//COOLINFO("This is really cool!!!");
//COOLINFOTRACE("THIS IS EVEN COOLER!!!");
LOGTEST("This is a really cool test man :3");
LOGTEST("Go check cmake-build-debug/logtest.log and cmake-build-debug/latest.log");
jlog::GlobalLogger::INFO.log_trace("This dick");
jlog::GlobalLogger::DEBUG.log_trace("This dick");
jlog::GlobalLogger::VERBOSE.log_trace("This dick");
jlog::GlobalLogger::WARNING.log_trace("This dick");
jlog::GlobalLogger::ERROR.log_trace("This dick");
jlog::GlobalLogger::FATAL.log_trace("This dick");
return 0;
}

63
src/jlog/formatter.cpp Normal file
View File

@@ -0,0 +1,63 @@
#include <string>
#include <format>
#include <vector>
#include <chrono>
#include "mcolor.h"
#include "jlog/formatter.hpp"
#include "jlog/token.hpp"
namespace jlog {
std::string get_timestamp() {
using namespace std::chrono;
auto const timestamp = current_zone()->to_local(system_clock::now());
auto dp = floor<days>(timestamp);
year_month_day ymd{floor<days>(timestamp)};
hh_mm_ss time{floor<milliseconds>(timestamp - dp)};
auto y = ymd.year();
auto m = ymd.month();
auto d = ymd.day();
auto h = time.hours();
auto M = time.minutes();
auto s = time.seconds();
auto ms = time.subseconds();
return std::format("{}-{}-{} {}:{}:{}.{}", y, m, d, h.count(), M.count(), s.count(), ms.count());
}
std::vector<token> trace_format(
const std::string& func,
const std::string& file,
int line)
{
auto trace = token{.content = func};
auto filedata = token{.content = std::format("{}:{}", file, line)};
return {trace, filedata};
}
std::vector<token> log_format(
const std::string& severity_name,
const std::string& message,
const mcolor::ansiColors::Colors& severity_cc)
{
auto severity = token{.colorCode = severity_cc, .content = severity_name};
auto content = token{.content = message, .delimiter = ""};
return {severity, content};
}
std::vector<token> log_format(
const std::string& severity_name,
const std::string& message,
const std::string& func,
const std::string& file,
int line,
const mcolor::ansiColors::Colors& severity_cc)
{
std::vector<token> tokens;
auto timestamp = token{.content = jlog::get_timestamp()};
auto tf_tokens = jlog::trace_format(func, file, line);
auto lf_tokens = jlog::log_format(severity_name, message, severity_cc);
tokens.push_back(timestamp);
tokens.insert(tokens.end(), tf_tokens.begin(), tf_tokens.end());
tokens.insert(tokens.end(), lf_tokens.begin(), lf_tokens.end());
return tokens;
}
}

View File

@@ -3,37 +3,16 @@
#include <iostream>
#include <chrono>
/*
#ifdef WIN32
#define NOMINMAX
#include <windows.h>
#endif
*/
namespace jlog
{
static std::string default_logfile = "latest.log";
void set_default_logfile(const std::string& filename)
{
default_logfile = filename;
}
std::string get_timestamp()
{
using namespace std::chrono;
auto const timestamp = current_zone()->to_local(system_clock::now());
auto dp = floor<days>(timestamp);
year_month_day ymd{floor<days>(timestamp)};
hh_mm_ss time{floor<milliseconds>(timestamp - dp)};
auto y = ymd.year();
auto m = ymd.month();
auto d = ymd.day();
auto h = time.hours();
auto M = time.minutes();
auto s = time.seconds();
auto ms = time.subseconds();
return std::format("{}-{}-{} {}:{}:{}.{}", y, m, d, h.count(), M.count(), s.count(), ms.count());
}
void log_to_console(const std::string& message)
{
@@ -43,211 +22,40 @@ namespace jlog
std::cout << message;
}
void log_to_file(const std::string& message)
{
std::ofstream latest_log(default_logfile, std::ios_base::app);
latest_log << message;
latest_log.close();
}
void log_to_file(const std::string& filename, const std::string& message)
{
std::ofstream latest_log(filename, std::ios_base::app);
latest_log << message;
latest_log.close();
}
void log_to_stream(std::ostream stream, const std::string& message)
{
stream << message;
}
std::string toks2msg(std::vector<token> tokens, std::function<std::string(token)> formatter)
{
std::string msg;
for (const token& t: tokens)
{
msg += formatter(t);
}
return msg;
}
std::string toks2consoleMsg(std::vector<token> tokens)
{
return toks2msg(tokens, consoleMsgFormatter);
}
std::string toks2logfileMsg(std::vector<token> tokens)
{
return toks2msg(tokens, logfileMsgFormatter);
}
std::string consoleMsgFormatter(token t)
{
if (!t.delimiter.empty())
{
return std::format("{}{}{}{}{} ", mcolor::toEscapeCode(t.colorCode), t.delimiter[0], t.content, t.delimiter[1], mcolor::toEscapeCode(mcolor::ansiColors::Colors::RESET));
}
return std::format("{}{}{} ", mcolor::toEscapeCode(t.colorCode), t.content, mcolor::toEscapeCode(mcolor::ansiColors::Colors::RESET));
}
std::string logfileMsgFormatter(token t)
{
if (!t.delimiter.empty())
{
return std::format("{}{}{} ", t.delimiter[0], t.content, t.delimiter[1]);
}
return t.content + " ";
}
void log(const std::vector<token>& tokens, const std::string& filename)
{
if (console_logging) {
log_to_console(toks2consoleMsg(tokens));
log_to_console("\n");
}
log_to_file(filename, toks2logfileMsg(tokens));
log_to_file(filename, "\n");
}
void log(const std::vector<token>& tokens)
{
log(tokens, default_logfile);
}
// Mainly for debug purposes
void ltlog(const std::vector<token>& tokens)
{
std::vector<token> wtokens;
//auto head = token{.colorCode = ansi_escape_codes::true_color(color_codes::BG_RED.rgb.r, color_codes::BG_RED.rgb.g, color_codes::BG_RED.rgb.b), .content = "GAS"};
//wtokens.push_back(head);
wtokens.insert(wtokens.end(), tokens.begin(), tokens.end());
log(wtokens);
log_to_file("logtest.log", toks2logfileMsg(wtokens) + "\n");
}
std::vector<token> trace_format(
const std::string& func,
const std::string& file,
int line)
{
auto trace = token{.content = func};
auto filedata = token{.content = std::format("{}:{}", file, line)};
return {trace, filedata};
}
std::vector<token> info_format(const std::string& message)
{
return log_format("INFO", message);
}
std::vector<token> warning_format(const std::string& message)
{
return log_format("INFO", message, mcolor::ansiColors::Colors::FG_YELLOW);
}
std::vector<token> error_format(const std::string& message)
{
return log_format("ERROR", message, mcolor::ansiColors::Colors::FG_RED);
}
std::vector<token> fatal_format(const std::string& message)
{
return log_format("FATAL", message, mcolor::ansiColors::Colors::FG_BRIGHT_RED);
}
std::vector<token> verbose_format(const std::string& message)
{
return log_format("VERBOSE", message, mcolor::ansiColors::Colors::FG_CYAN);
}
std::vector<token> debug_format(const std::string& message)
{
return log_format("DEBUG", message, mcolor::ansiColors::Colors::FG_GREEN);
}
std::vector<token> debug_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("DEBUG", message, func, file, line, mcolor::ansiColors::Colors::FG_GREEN);
}
std::vector<token> info_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("INFO", message, func, file, line);
}
std::vector<token> warning_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("WARNING", message, func, file, line, mcolor::ansiColors::Colors::FG_YELLOW);
}
std::vector<token> error_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("ERROR", message, func, file, line, mcolor::ansiColors::Colors::FG_RED);
}
std::vector<token> verbose_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("VERBOSE", message, func, file, line, mcolor::ansiColors::Colors::FG_CYAN);
}
std::vector<token> fatal_detailed_format(
const std::string& message,
const std::string& func,
const std::string& file,
int line)
{
return log_detailed_format("FATAL", message, func, file, line, mcolor::ansiColors::Colors::FG_BRIGHT_RED);
}
std::vector<token> log_format(
const std::string& severity_name,
const std::string& message,
const mcolor::ansiColors::Colors& severity_cc)
{
auto severity = token{.colorCode = severity_cc, .content = severity_name};
auto content = token{.content = message, .delimiter = ""};
return {severity, content};
}
std::vector<token> log_detailed_format(
const std::string& severity_name,
const std::string& message,
const std::string& func,
const std::string& file,
int line,
const mcolor::ansiColors::Colors& severity_cc)
{
std::vector<token> tokens;
auto timestamp = token{.content = jlog::get_timestamp()};
auto tf_tokens = jlog::trace_format(func, file, line);
auto lf_tokens = jlog::log_format(severity_name, message, severity_cc);
tokens.push_back(timestamp);
tokens.insert(tokens.end(), tf_tokens.begin(), tf_tokens.end());
tokens.insert(tokens.end(), lf_tokens.begin(), lf_tokens.end());
return tokens;
}
}
namespace jlog::GlobalLogger {
GlobalLogger::GlobalLogger(const std::string &context, const mcolor::ansiColors::Colors& colorcode) {
this->context = context;
this->colorcode = colorcode;
}
void GlobalLogger::log(const std::string &message) {
if (!enabled)
return;
std::vector<jlog::token> fmt = log_format(this->context, message, this->colorcode);
jlog::log_to_console(jlog::toks2consoleMsg(fmt) + '\n');
jlog::log_to_file(this->logfile, jlog::toks2logfileMsg(fmt) + '\n');
}
void GlobalLogger::log_trace(const std::string &message, const std::source_location &location) {
if (!enabled)
return;
//std::vector<jlog::token> fmt = log_format(this->context, message, func, file, line,this->colorcode);
std::vector<jlog::token> fmt = log_format(this->context, message, location.function_name(), location.file_name(), location.line(),this->colorcode);
jlog::log_to_console(jlog::toks2consoleMsg(fmt) + '\n');
jlog::log_to_file(this->logfile, jlog::toks2logfileMsg(fmt) + '\n');
}
}

42
src/jlog/token.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include <string>
#include <vector>
#include <functional>
#include <format>
#include "mcolor.h"
#include "jlog/token.hpp"
namespace jlog {
std::string toks2msg(std::vector <token> tokens, std::function<std::string(token)> formatter) {
std::string msg;
for (const token &t: tokens) {
msg += formatter(t);
}
return msg;
}
std::string toks2consoleMsg(std::vector <token> tokens) {
return toks2msg(tokens, consoleMsgFormatter);
}
std::string toks2logfileMsg(std::vector <token> tokens) {
return toks2msg(tokens, logfileMsgFormatter);
}
std::string consoleMsgFormatter(token t) {
if (!t.delimiter.empty()) {
return std::format("{}{}{}{}{} ", mcolor::toEscapeCode(t.colorCode), t.delimiter[0], t.content,
t.delimiter[1], mcolor::toEscapeCode(mcolor::ansiColors::Colors::RESET));
}
return std::format("{}{}{} ", mcolor::toEscapeCode(t.colorCode), t.content,
mcolor::toEscapeCode(mcolor::ansiColors::Colors::RESET));
}
std::string logfileMsgFormatter(token t) {
if (!t.delimiter.empty()) {
return std::format("{}{}{} ", t.delimiter[0], t.content, t.delimiter[1]);
}
return t.content + " ";
}
}