179 lines
4.6 KiB
C++
179 lines
4.6 KiB
C++
#ifndef LOGGING_H
|
|
#define LOGGING_H
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <chrono>
|
|
#include <ctime>
|
|
|
|
// Logging levels
|
|
#define LOG_ERROR 0
|
|
#define LOG_WARN 1
|
|
#define LOG_INFO 2
|
|
#define LOG_DEBUG 3
|
|
#define LOG_TRACE 4
|
|
|
|
// Set logging arguments
|
|
// TODO: set these by compiler arguments or env vars or something
|
|
#define LOGGING LOG_DEBUG // logging level
|
|
#define LOGGING_COLOR true // enable color
|
|
#define LOGGING_TIMESTAMP true // enable timestamp
|
|
#define LOGGING_TIMESTAMP_FMT "%Y-%m-%dT%H:%M:%S%z" // timestamp format (local time)
|
|
#define LOGGING_POSITION true // display position (only works on C++20 or newer)
|
|
|
|
// Color codes
|
|
#define ANSI_RESET "\033[0m"
|
|
#define ANSI_BLACK "\033[30m" /* Black */
|
|
#define ANSI_RED "\033[31m" /* Red */
|
|
#define ANSI_GREEN "\033[32m" /* Green */
|
|
#define ANSI_YELLOW "\033[33m" /* Yellow */
|
|
#define ANSI_BLUE "\033[34m" /* Blue */
|
|
#define ANSI_MAGENTA "\033[35m" /* Magenta */
|
|
#define ANSI_CYAN "\033[36m" /* Cyan */
|
|
#define ANSI_WHITE "\033[37m" /* White */
|
|
#define ANSI_BOLD "\033[1m" /* Bold */
|
|
|
|
template <typename T>
|
|
void print(T t) {
|
|
std::cout << t << std::endl;
|
|
}
|
|
|
|
template <typename T, typename... Args>
|
|
void print(T t, Args... args) {
|
|
std::cout << t;
|
|
print(args...);
|
|
}
|
|
|
|
inline void printTimestamp() {
|
|
#if LOGGING_TIMESTAMP
|
|
auto now = std::chrono::system_clock::now();
|
|
auto time_c = std::chrono::system_clock::to_time_t(now);
|
|
std::tm time_tm;
|
|
localtime_r(&time_c, &time_tm);
|
|
std::cout << std::put_time(&time_tm, LOGGING_TIMESTAMP_FMT) << ": ";
|
|
#endif
|
|
}
|
|
|
|
// if we're on C++20 or later, then use the source_location header and add source location to logs
|
|
#if __cplusplus >= 202002L
|
|
#include <source_location>
|
|
|
|
inline void printPosition(std::source_location& location) {
|
|
#if LOGGING_POSITION
|
|
std::cout << location.file_name() << ":" << location.function_name << ":" << ANSI_CYAN << location.line() << ANSI_RESET << ": ";
|
|
#endif
|
|
}
|
|
|
|
inline void printHeader(std::string name, std::string color, std::source_location& location) {
|
|
#if LOGGING_COLOR
|
|
std::cout << ANSI_BOLD << color << "[" << name << "] " << ANSI_RESET;
|
|
printTimestamp();
|
|
printPosition(location);
|
|
#else
|
|
printHeader(name);
|
|
#endif
|
|
}
|
|
|
|
inline void printHeader(std::string name, std::source_location& location) {
|
|
std::cout << "[" << name << "] ";
|
|
printTimestamp();
|
|
printPosition(location);
|
|
}
|
|
|
|
template <typename... Args, typename Sl = std::source_location>
|
|
void trace(Args... args, Sl location = std::source_location::current()) {
|
|
#if LOGGING >= LOG_TRACE
|
|
printHeader("TRACE", ANSI_CYAN, location);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args, typename Sl = std::source_location>
|
|
void debug(Args... args, Sl location = std::source_location::current()) {
|
|
#if LOGGING >= LOG_DEBUG
|
|
printHeader("DEBUG", ANSI_MAGENTA, location);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args, typename Sl = std::source_location>
|
|
void info(Args... args, Sl location = std::source_location::current()) {
|
|
#if LOGGING >= LOG_INFO
|
|
printHeader("INFO", ANSI_GREEN, location);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args, typename Sl = std::source_location>
|
|
void warn(Args... args, Sl location = std::source_location::current()) {
|
|
#if LOGGING >= LOG_WARN
|
|
printHeader("WARN", ANSI_YELLOW, location);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args, typename Sl = std::source_location>
|
|
void error(Args... args, Sl location = std::source_location::current()) {
|
|
#if LOGGING >= LOG_ERROR
|
|
printHeader("ERROR", ANSI_RED, location);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
#else
|
|
inline void printHeader(std::string name, std::string color) {
|
|
#if LOGGING_COLOR
|
|
std::cout << ANSI_BOLD << color << "[" << name << "] " << ANSI_RESET;
|
|
printTimestamp();
|
|
#else
|
|
printHeader(name);
|
|
#endif
|
|
}
|
|
|
|
inline void printHeader(std::string name) {
|
|
std::cout << "[" << name << "] ";
|
|
printTimestamp();
|
|
}
|
|
|
|
template <typename... Args>
|
|
void trace(Args... args) {
|
|
#if LOGGING >= LOG_TRACE
|
|
printHeader("TRACE", ANSI_CYAN);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args>
|
|
void debug(Args... args) {
|
|
#if LOGGING >= LOG_DEBUG
|
|
printHeader("DEBUG", ANSI_MAGENTA);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args>
|
|
void info(Args... args) {
|
|
#if LOGGING >= LOG_INFO
|
|
printHeader("INFO", ANSI_GREEN);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args>
|
|
void warn(Args... args) {
|
|
#if LOGGING >= LOG_WARN
|
|
printHeader("WARN", ANSI_YELLOW);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
|
|
template <typename... Args>
|
|
void error(Args... args) {
|
|
#if LOGGING >= LOG_ERROR
|
|
printHeader("ERROR", ANSI_RED);
|
|
print(args...);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#endif //LOGGING_H
|