From 889f24d402e147312a0dc1d7e5bca4e69d04fca8 Mon Sep 17 00:00:00 2001 From: Brett Date: Fri, 21 Jul 2023 03:32:42 -0400 Subject: [PATCH] logging 2.0 is almost at first working build --- include/blt/math/log_util.h | 2 +- include/blt/profiling/profiler.h | 2 +- include/blt/std/loader.h | 2 +- include/blt/std/logging.h | 274 +++++++++++++++++++++++++++++-- include/blt/std/logging_old.h | 153 ----------------- include/blt/std/memory.h | 6 +- include/blt/std/string.h | 2 +- src/blt/profiling/profiler.cpp | 8 +- src/blt/std/format.cpp | 2 +- src/blt/std/logging_old.cpp | 245 --------------------------- src/tests/logging.h | 8 +- src/tests/main.cpp | 8 +- src/tests/nbt_tests.h | 2 +- src/tests/profiling_tests.h | 2 +- src/tests/queue_tests.h | 2 +- 15 files changed, 285 insertions(+), 433 deletions(-) delete mode 100644 include/blt/std/logging_old.h delete mode 100644 src/blt/std/logging_old.cpp diff --git a/include/blt/math/log_util.h b/include/blt/math/log_util.h index e0c7dbc..dec9035 100644 --- a/include/blt/math/log_util.h +++ b/include/blt/math/log_util.h @@ -9,7 +9,7 @@ #include #include -#include +#include namespace blt { diff --git a/include/blt/profiling/profiler.h b/include/blt/profiling/profiler.h index fe0953a..b0f5075 100644 --- a/include/blt/profiling/profiler.h +++ b/include/blt/profiling/profiler.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/blt/std/loader.h b/include/blt/std/loader.h index e754394..f0d288e 100644 --- a/include/blt/std/loader.h +++ b/include/blt/std/loader.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace blt::fs { std::vector getLinesFromFile(const std::string& path); diff --git a/include/blt/std/logging.h b/include/blt/std/logging.h index e0e727d..a403cdf 100644 --- a/include/blt/std/logging.h +++ b/include/blt/std/logging.h @@ -11,25 +11,34 @@ #include #include #include +#include namespace blt::logging { + template + using hashmap = std::unordered_map; + enum class log_level { + // default + NONE, // low level TRACE0, TRACE1, TRACE2, TRACE3, // normal TRACE, DEBUG, INFO, // errors WARN, ERROR, FATAL, - // default - NONE }; - struct log_tag { + struct tag_func_param { + blt::logging::log_level level; + const std::string& file, line, raw_string, formatted_string; + }; + + struct tag { // tag without the ${{ or }} std::string tag; - // function to run, log level and raw user input string are provided - std::function func; + // function to run: log level, file, line, and raw user input string are provided + std::function func; }; struct log_format { @@ -43,9 +52,15 @@ namespace blt::logging { * - ${{HOUR}} // current hour * - ${{MINUTE}} // current minute * - ${{SECOND}} // current second - * - ${{MS}} // current millisecond - * - ${{LF}} // log level color (ASCII color code) - * - ${{R}} // ASCII color reset + * - ${{MS}} // current unix time + * - ${{NS}} // current ns from the high resolution system timer + * - ${{ISO_YEAR}} // ISO formatted 'year-month-day' in a single variable + * - ${{TIME}} // 'hour:minute:second' formatted string in a single variable + * - ${{FULL_TIME}} // 'year-month-day hour:minute:second' in a single variable + * - ${{LF}} // log level color (ANSI color code) + * - ${{ER}} // Error red + * - ${{CNR}} // conditional error red (only outputs if log level is an error!) + * - ${{RC}} // ANSI color reset * - ${{LOG_LEVEL}} // current log level * - ${{THREAD_NAME}} // current thread name, NOTE: thread names must be set by calling "setThreadName()" from the thread in question! * - ${{FILE}} // file from which the macro is invoked @@ -53,34 +68,247 @@ namespace blt::logging { * - ${{RAW_STR}} // raw user string without formatting applied (NOTE: format args are not provided!) * - ${{STR}} // the user supplied string (format applied!) */ - std::string logOutputFormat = "[${{HOUR}}:${{MINUTE}}:${{SECOND}] ${{LF}}[${{LOG_LEVEL}}]${{R}} ${{STR}}"; + std::string logOutputFormat = "[${{HOUR}}:${{MINUTE}}:${{SECOND}] ${{LF}}[${{LOG_LEVEL}}]${{R}} ${{CNR}}${{STR}}"; + std::string levelNames[10] = {"STDOUT", "TRACE0, TRACE1, TRACE2", "TRACE3", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; + std::string levelColors[10] = {"\033[0m", "\033[22;97m", "\033[97m", "\033[97m", "\033[97m", "\033[36m", "\033[92m", "\033[93m", "\033[91m", "\033[97;41m"}; }; - void log(log_level level, const std::string& format, const char* file, int line, ...); + struct logger { + log_level level; + std::string file; + std::string line; + }; + + struct empty_logger { + + }; + + void log(const std::string& format, log_level level, const char* file, int line, ...); + void log_stream(const std::string& str, const logger& logger); template::value>::type* = nullptr> inline void log(T t, log_level level, const char* file, int line) { log(std::to_string(t), level, file, line); } + template::value>::type* = nullptr> + inline void log_stream(T t, const logger& logger) { + log_stream(std::to_string(t), logger); + } + + static inline const blt::logging::logger& operator<<(const blt::logging::logger& out, const std::string& str) { + log_stream(str, out); + return out; + } + + template::value>::type* = nullptr> + static inline const blt::logging::logger& operator<<(const blt::logging::logger& out, T t) { + log_stream(std::to_string(t), out); + return out; + } + + static inline const blt::logging::empty_logger& operator<<(const blt::logging::empty_logger& out, const std::string&) { + return out; + } + + template::value>::type* = nullptr> + static inline const blt::logging::empty_logger& operator<<(const blt::logging::empty_logger& out, T) { + return out; + } + void flush(); void setThreadName(const std::string& name); - } +#define BLT_LOGGING_IMPLEMENTATION #ifdef BLT_LOGGING_IMPLEMENTATION - + #include + #include + #include + #include + #include namespace blt::logging { + /** + * Used to store fast associations between built in tags and their respective values + */ + class tag_map { + private: + tag* tags; + size_t size; + + [[nodiscard]] inline size_t hash(const tag& t) const { + size_t h = t.tag[0]+ t.tag[1] * 3; + return h; + } + + inline void expand(){ + auto newSize = size * 2; + tag* newTags = new tag[newSize]; + for (size_t i = 0; i < size; i++) + newTags[i] = tags[i]; + delete[] tags; + tags = newTags; + size = newSize; + } + public: + tag_map(std::initializer_list initial_tags){ + tags = new tag[(size = 16)]; + for (auto& t : initial_tags) + insert(t); + } + + tag_map& insert(const tag& t){ + auto h = hash(t); + if (h > size) + expand(); + if (!tags[h].tag.empty()) + std::cerr << "Tag not empty! " << tags[h].tag << "!!!\n"; + tags[h] = t; + return *this; + } + + tag& operator[](const std::string& name){ + auto h = hash(tag{name, nullptr}); + if (h > size) + std::cerr << "Tag out of bounds"; + return tags[h]; + } + + ~tag_map(){ + delete[] tags; + } + }; + + #define BLT_NOW() auto t = std::time(nullptr); auto now = std::localtime(&t) + #define BLT_ISO_YEAR(S) auto S = std::to_string(now->tm_year); \ + S += '-'; \ + S += std::to_string(now->tm_mon); \ + S += '-'; \ + S += std::to_string(now->tm_mday); + #define BLT_CUR_TIME(S) auto S = std::to_string(now->tm_hour); \ + S += '-'; \ + S += std::to_string(now->tm_min); \ + S += '-'; \ + S += std::to_string(now->tm_sec); + + static inline std::string ensureHasDigits(int current, int digits) { + std::string asString = std::to_string(current); + auto length = digits - asString.length(); + if (length <= 0) + return asString; + std::string zeros; + zeros.reserve(length); + for (unsigned int i = 0; i < length; i++){ + zeros += '0'; + } + return zeros + asString; + } + + log_format loggingFormat {}; + hashmap loggingThreadNames; + hashmap> loggingStreamLines; + + const tag_map tagMap = { + {"YEAR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return std::to_string(now->tm_year); + }}, + {"MONTH", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now->tm_mon, 2); + }}, + {"DAY", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now->tm_mday, 2); + }}, + {"HOUR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now->tm_hour, 2); + }}, + {"MINUTE", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now->tm_min, 2); + }}, + {"SECOND", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now->tm_sec, 2); + }}, + {"MS", [](const tag_func_param&) -> std::string { + return std::to_string(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count() + ); + }}, + {"NS", [](const tag_func_param&) -> std::string { + return std::to_string(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count() + ); + }}, + {"ISO_YEAR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_ISO_YEAR(returnStr); + return returnStr; + }}, + {"TIME", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_CUR_TIME(returnStr); + return returnStr; + }}, + {"FULL_TIME", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_ISO_YEAR(ISO); + BLT_CUR_TIME(TIME); + ISO += ' '; + ISO += TIME; + return ISO; + }}, + {"LF", [](const tag_func_param& f) -> std::string { + return loggingFormat.levelColors[(int)f.level]; + }}, + {"ER", [](const tag_func_param&) -> std::string { + return loggingFormat.levelColors[(int)log_level::ERROR]; + }}, + {"CNR", [](const tag_func_param& f) -> std::string { + return f.level >= log_level::ERROR ? loggingFormat.levelColors[(int)log_level::ERROR] : ""; + }}, + {"RC", [](const tag_func_param&) -> std::string { + return "\033[0m"; + }}, + {"LOG_LEVEL", [](const tag_func_param& f) -> std::string { + return loggingFormat.levelNames[(int)f.level]; + }}, + {"THREAD_NAME", [](const tag_func_param&) -> std::string { + if (loggingThreadNames.find(std::this_thread::get_id()) == loggingThreadNames.end()) + return "UNKNOWN"; + return loggingThreadNames[std::this_thread::get_id()]; + }}, + {"FILE", [](const tag_func_param& f) -> std::string { + return f.file; + }}, + {"LINE", [](const tag_func_param& f) -> std::string { + return f.line; + }}, + {"RAW_STR", [](const tag_func_param& f) -> std::string { + return f.raw_string; + }}, + {"STR", [](const tag_func_param& f) -> std::string { + return f.formatted_string; + }}, + }; + void log(const std::string& format, log_level level, const char* file, int line, ...) { } + void log_stream(const std::string& str, const logger& logger) { + loggingStreamLines[] + } + void setThreadName(const std::string& name) { - + loggingThreadNames[std::this_thread::get_id()] = name; } void flush() { @@ -104,38 +332,58 @@ namespace blt::logging { #define BLT_LOG(format, level, ...) log(format, level, __FILE__, __LINE__, ##__VA_ARGS__) #ifndef BLT_ENABLE_TRACE #define BLT_TRACE(format, ...) + #define BLT_TRACE0_STREAM blt::logging::empty_logger{} + #define BLT_TRACE1_STREAM blt::logging::empty_logger{} + #define BLT_TRACE2_STREAM blt::logging::empty_logger{} + #define BLT_TRACE3_STREAM blt::logging::empty_logger{} + #define BLT_TRACE_STREAM blt::logging::empty_logger{} #else #define BLT_TRACE(format, ...) BLT_LOG(format, blt::logging::log_level::TRACE, ##__VA_ARGS__) + #define BLT_TRACE0_STREAM blt::logging::logger{blt::logging::log_level::TRACE0, std::string(__FILE__), std::to_string(__LINE__)} + #define BLT_TRACE1_STREAM blt::logging::logger{blt::logging::log_level::TRACE1, std::string(__FILE__), std::to_string(__LINE__)} + #define BLT_TRACE2_STREAM blt::logging::logger{blt::logging::log_level::TRACE2, std::string(__FILE__), std::to_string(__LINE__)} + #define BLT_TRACE3_STREAM blt::logging::logger{blt::logging::log_level::TRACE3, std::string(__FILE__), std::to_string(__LINE__)} + #define BLT_TRACE_STREAM blt::logging::logger{blt::logging::log_level::TRACE, std::string(__FILE__), std::to_string(__LINE__)} #endif #ifndef BLT_ENABLE_DEBUG #define BLT_DEBUG(format, ...) + #define BLT_DEBUG_STREAM blt::logging::empty_logger{} #else #define BLT_DEBUG(format, ...) BLT_LOG(format, blt::logging::log_level::DEBUG, ##__VA_ARGS__) + #define BLT_DEBUG_STREAM blt::logging::logger{blt::logging::log_level::DEBUG, std::string(__FILE__), std::to_string(__LINE__)} #endif #ifndef BLT_ENABLE_INFO #define BLT_INFO(format, ...) + #define BLT_INFO_STREAM blt::logging::empty_logger{} #else #define BLT_INFO(format, ...) BLT_LOG(format, blt::logging::log_level::INFO, ##__VA_ARGS__) + #define BLT_INFO_STREAM blt::logging::logger{blt::logging::log_level::INFO, std::string(__FILE__), std::to_string(__LINE__)} #endif #ifndef BLT_ENABLE_WARN #define BLT_WARN(format, ...) + #define BLT_WARN_STREAM blt::logging::empty_logger{} #else #define BLT_WARN(format, ...) BLT_LOG(format, blt::logging::log_level::WARN, ##__VA_ARGS__) + #define BLT_WARN_STREAM blt::logging::logger{blt::logging::log_level::WARN, std::string(__FILE__), std::to_string(__LINE__)} #endif #ifndef BLT_ENABLE_ERROR #define BLT_ERROR(format, ...) + #define BLT_ERROR_STREAM blt::logging::empty_logger{} #else #define BLT_ERROR(format, ...) BLT_LOG(format, blt::logging::log_level::ERROR, ##__VA_ARGS__) + #define BLT_ERROR_STREAM blt::logging::logger{blt::logging::log_level::ERROR, std::string(__FILE__), std::to_string(__LINE__)} #endif #ifndef BLT_ENABLE_FATAL #define BLT_FATAL(format, ...) + #define BLT_FATAL_STREAM blt::logging::empty_logger{} #else #define BLT_FATAL(format, ...) BLT_LOG(format, blt::logging::log_level::FATAL, ##__VA_ARGS__) + #define BLT_FATAL_STREAM blt::logging::logger{blt::logging::log_level::FATAL, std::string(__FILE__), std::to_string(__LINE__)} #endif #endif diff --git a/include/blt/std/logging_old.h b/include/blt/std/logging_old.h deleted file mode 100644 index 39b28e9..0000000 --- a/include/blt/std/logging_old.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Created by Brett on 23/01/23. - * Licensed under GNU General Public License V3.0 - * See LICENSE file for license detail - */ - -#ifndef BLT_LOGGING_H -#define BLT_LOGGING_H - -#include -#include -#include - -namespace blt::logging { - - enum class log_level { - // low level - TRACE0, TRACE1, TRACE2, TRACE3, - // normal - TRACE, DEBUG, INFO, - WARN, - // errors - ERROR, FATAL, - // default - NONE - }; - - class ILogHandler { - public: - virtual void log(std::string message, log_level level) = 0; - }; - - struct LOG_PROPERTIES { - bool m_useColor = true; - bool m_logToConsole = true; - bool m_logToFile = true; - // include file + line data? - bool m_logWithData = true; - // print the whole path or just the file name? - bool m_logFullPath = false; - const char* m_directory = "./"; - log_level minLevel = log_level::TRACE; - - explicit constexpr LOG_PROPERTIES( - bool useColor, bool logToConsole, bool logToFile, const char* directory - ): - m_useColor(useColor), m_logToConsole(logToConsole), m_logToFile(logToFile), - m_directory(directory) {} - - explicit constexpr LOG_PROPERTIES() = default; - }; - - struct logger { - log_level level; - - void log_internal(const std::string& str) const; - // evil hack, todo: better way -#ifdef BLT_DISABLE_LOGGING - void log(const std::string& str) const { - - } -#else - - void log(const std::string& str) const { - log_internal(str); - } - -#endif - - void flush() const; - - static void flush_all(); - }; - - static logger std_out{log_level::NONE}; - - static logger trace{log_level::TRACE}; - static logger debug{log_level::DEBUG}; - static logger info{log_level::INFO}; - static logger warn{log_level::WARN}; - static logger error{log_level::ERROR}; - static logger fatal{log_level::FATAL}; - - static inline logger& getLoggerFromLevel(log_level level) { - static logger loggerLevelDecode[11]{trace, trace, trace, trace, trace, debug, info, warn, error, fatal, std_out}; - return loggerLevelDecode[(int)level]; - } - - static inline logger& operator<<(logger& out, const std::string& str) { - out.log(str); - return out; - } - - template::value>::type* = nullptr> - static inline logger& operator<<(logger& out, T t) { - out.log(std::to_string(t)); - return out; - } - - void init(LOG_PROPERTIES properties); - - void log_internal( - const std::string& format, log_level level, const char* file, int currentLine, - int auto_line, ... - ); - - // template voodoo magic (SFINAE, "Substitution Failure Is Not An Error") - // https://stackoverflow.com/questions/44848011/c-limit-template-type-to-numbers - // std::enable_if has a member called type if the condition is true. - // What I am doing is saying that if the condition is true then the template has a non type - // template parameter of type type* (which is void* since the default type for enable_if is void) and it's value is nullptr. - // if the condition is false, the substitution fails, and the entire template is silently (no compiler error) discarded from the overload set. - /** - * Logs an is_arithmetic type to the console. - * @tparam T type to log - * @param t the value to log - * @param level logger level to log at - * @param auto_line put a new line at the end if none exists if true - */ - template::value>::type* = nullptr> - inline void log_internal( - T t, log_level level, const char* file, int currentLine, int auto_line - ) { - log_internal(std::to_string(t), level, file, currentLine, auto_line); - } - - /** - * Will flush all buffers! This might cause issues with threads! - */ - void flush(); - - void testLogging(); -} - -#ifndef BLT_ENABLE_LOGGING - #define BLT_TRACE(format, ...) - #define BLT_DEBUG(format, ...) - #define BLT_INFO(format, ...) - #define BLT_WARN(format, ...) - #define BLT_ERROR(format, ...) - #define BLT_FATAL(format, ...) -#else - #ifndef BLT_DISABLE_LOGGING - #define BLT_TRACE(format, ...) log_internal(format, blt::logging::log_level::TRACE, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_DEBUG(format, ...) log_internal(format, blt::logging::log_level::DEBUG, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_INFO(format, ...) log_internal(format, blt::logging::log_level::INFO, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_WARN(format, ...) log_internal(format, blt::logging::log_level::WARN, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_ERROR(format, ...) log_internal(format, blt::logging::log_level::ERROR, __FILE__, __LINE__, true, ##__VA_ARGS__) - #define BLT_FATAL(format, ...) log_internal(format, blt::logging::log_level::FATAL, __FILE__, __LINE__, true, ##__VA_ARGS__) - #endif -#endif - -#endif //BLT_LOGGING_H diff --git a/include/blt/std/memory.h b/include/blt/std/memory.h index c82ef5e..9f8f974 100644 --- a/include/blt/std/memory.h +++ b/include/blt/std/memory.h @@ -136,12 +136,12 @@ namespace blt { V* _values; size_t _size = 0; public: - - enum_storage(std::initializer_list> init){ for (auto& i : init) - _size = std::max((size_t)i, _size); + _size = std::max((size_t)i.first, _size); _values = new V[_size]; + for (auto& v : init) + _values[(size_t)v.first] = v.second; } inline V& operator[](size_t index){ diff --git a/include/blt/std/string.h b/include/blt/std/string.h index a0d31bf..69412dc 100644 --- a/include/blt/std/string.h +++ b/include/blt/std/string.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace blt::string { diff --git a/src/blt/profiling/profiler.cpp b/src/blt/profiling/profiler.cpp index b70d558..5ea8687 100644 --- a/src/blt/profiling/profiler.cpp +++ b/src/blt/profiling/profiler.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,9 +31,11 @@ namespace blt::profiling { }; inline void println(const std::vector&& lines, logging::log_level level) { - auto& logger = logging::getLoggerFromLevel(level); for (const auto& line : lines) - logger << line << "\n"; + BLT_INFO_STREAM << line << "\n"; +// auto& logger = logging::getLoggerFromLevel(level); +// for (const auto& line : lines) +// logger << line << "\n"; } /** diff --git a/src/blt/std/format.cpp b/src/blt/std/format.cpp index 76ca0e4..f7e5082 100644 --- a/src/blt/std/format.cpp +++ b/src/blt/std/format.cpp @@ -5,7 +5,7 @@ */ #include #include -#include "blt/std/logging_old.h" +#include "blt/std/logging.h" std::string createPadding(int padAmount) { std::string padStr; diff --git a/src/blt/std/logging_old.cpp b/src/blt/std/logging_old.cpp deleted file mode 100644 index a06c2e1..0000000 --- a/src/blt/std/logging_old.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Created by Brett on 23/01/23. - * Licensed under GNU General Public License V3.0 - * See LICENSE file for license detail - */ -#include -#include -#include -#include -#include -#include "blt/std/string.h" -#include "blt/std/format.h" -#include -#include -#include -#include -#include -#include - -// https://en.cppreference.com/w/cpp/utility/variadic -// https://medium.com/swlh/variadic-functions-3419c287a0d2 -// https://publications.gbdirect.co.uk//c_book/chapter9/stdarg.html -// https://cplusplus.com/reference/cstdio/printf/ - -#include - - -namespace blt::logging { - - class LogFileWriter { - private: - std::string m_path; - std::fstream* output; - int currentLines = 0; - static constexpr int MAX_LINES = 100000; - public: - explicit LogFileWriter(const std::string& path): m_path(path){ - auto currentTime = system::getTimeStringFS(); - output = new std::fstream(path + currentTime + ".log", std::ios::out | std::ios::app); - if (!output->good()){ - throw std::runtime_error("Unable to open console filestream!\n"); - } - } - - void writeLine(const std::string& line){ - if (!output->good()){ - std::cerr << "There has been an error in the logging file stream!\n"; - output->clear(); - } - *output << line; - currentLines++; - if (currentLines > MAX_LINES){ - output->flush(); - output->close(); - currentLines = 0; - auto currentTime = system::getTimeStringFS(); - delete(output); - output = new std::fstream(m_path + currentTime + ".log"); - } - } - - ~LogFileWriter() { - delete(output); - } - }; - - void applyFormatting(const std::string& format, std::string& output, va_list& args){ - // args must be copied because they will be consumed by the first vsnprintf - va_list args_copy; - va_copy(args_copy, args); - - auto buffer_size = std::vsnprintf(nullptr, 0, format.c_str(), args_copy) + 1; - // some compilers don't even allow you to do stack dynamic arrays. So always allocate on the heap. - // originally if the buffer was small enough the buffer was allocated on the stack because it made no sense to make a heap object - // that will be deleted a couple lines later. - scoped_buffer buffer{static_cast(buffer_size)}; - vsnprintf(*buffer, buffer_size, format.c_str(), args); - output = std::string(*buffer); - - va_end(args_copy); - } - - const char* levelColors[6] = { - "\033[97m", - "\033[36m", - "\033[92m", - "\033[93m", - "\033[91m", - "\033[97;41m" - }; - - const char* levelNames[6] = { - "[BLT_TRACE]: ", - "[BLT_DEBUG]: ", - "[BLT_INFO]: ", - "[BLT_WARN]: ", - "[BLT_ERROR]: ", - "[BLT_FATAL]: ", - }; - - // by default everything is enabled - LOG_PROPERTIES BLT_LOGGING_PROPERTIES {}; - LogFileWriter* writer = new LogFileWriter{"./"}; - - void init(LOG_PROPERTIES properties) { - if (properties.m_logToFile && BLT_LOGGING_PROPERTIES.m_directory != properties.m_directory) { - delete(writer); - writer = new LogFileWriter{properties.m_directory}; - } - if (properties.m_logToFile) - std::filesystem::create_directory(properties.m_directory); - BLT_LOGGING_PROPERTIES = properties; - } - - inline std::string filename(const std::string& path){ - if (BLT_LOGGING_PROPERTIES.m_logFullPath) - return path; - auto paths = blt::string::split(path, "/"); - auto final = paths[paths.size()-1]; - if (final == "/") - return paths[paths.size()-2]; - return final; - } - - inline void log(const std::string& str, bool hasEndingLinefeed, log_level level, const char* file, int currentLine, int auto_line){ - if (level < BLT_LOGGING_PROPERTIES.minLevel) - return; - std::string outputString = system::getTimeStringLog(); - - if (BLT_LOGGING_PROPERTIES.m_logWithData && currentLine >= 0) { - outputString += '['; - outputString += filename(file); - outputString += ':'; - outputString += std::to_string(currentLine); - outputString += "] "; - } - - outputString += levelNames[(int)level]; - outputString += str; - - std::string fileString = outputString; - - if (BLT_LOGGING_PROPERTIES.m_useColor) { - outputString = levelColors[(int)level] + outputString; - outputString += "\033[0m"; - } - - if (hasEndingLinefeed || auto_line) { - outputString += "\n"; - fileString += "\n"; - } - - if (BLT_LOGGING_PROPERTIES.m_logToConsole) { - if (level > log_level::WARN) - std::cerr << outputString; - else - std::cout << outputString; - } - - if (BLT_LOGGING_PROPERTIES.m_logToFile) { - writer->writeLine(fileString); - } - } - - void log_internal(const std::string& format, log_level level, const char* file, int currentLine, int auto_line, ...) { - va_list args; - va_start(args, auto_line); - - std::string formattedString; - applyFormatting(format, formattedString, args); - - bool hasEndingLinefeed = false; - - if (formattedString.length() > 0) - hasEndingLinefeed = formattedString[formattedString.length() - 1] == '\n'; - - if (hasEndingLinefeed) - formattedString = formattedString.substr(0, formattedString.length()-1); - - log(formattedString, hasEndingLinefeed, level, file, currentLine, auto_line); - - va_end(args); - } - - // stores an association between thread -> log level -> current line buffer - std::unordered_map> thread_local_strings; - - void logger::log_internal(const std::string& str) const { - auto id = std::this_thread::get_id(); - auto th_str = thread_local_strings[id][level]; - th_str += str; - - if (blt::string::contains(str, "\n")){ - // make sure new lines are properly formatted to prevent danging lines. Ie "[trace]: .... [debug]: ...." - bool hasEndingLinefeed = str[str.length()-1] == '\n'; - if (level == log_level::NONE) { - std::cout << th_str; - } else - logging::log(th_str, false, level, "", -1, !hasEndingLinefeed); - thread_local_strings[id][level] = ""; - } else { - thread_local_strings[id][level] = th_str; - } - } - - void flushLogger_internal(std::thread::id id, log_level level){ - auto th_str = thread_local_strings[id][level]; - if (th_str.empty()) - return; - bool hasEndingLinefeed = th_str[th_str.length() - 1] == '\n'; - logging::log(th_str, false, level, "", -1, !hasEndingLinefeed); - thread_local_strings[id][level] = ""; - } - - void logger::flush() const { - for (const auto& id : thread_local_strings) { - flushLogger_internal(id.first, level); - } - } - - void logger::flush_all() { - for (const auto& id : thread_local_strings) { - for (const auto& level : thread_local_strings[id.first]){ - flushLogger_internal(id.first, level.first); - } - } - } - - void flush() { - logger::flush_all(); - std::cerr.flush(); - std::cout.flush(); - } - - void testLogging() { - trace << "Trace Test!\n"; - debug << "Debug Test!\n"; - info << "Info Test!\n"; - warn << "Warn Test!\n"; - error << "Error Test!\n"; - fatal << "Fatal Test!\n"; - } -} - - diff --git a/src/tests/logging.h b/src/tests/logging.h index 4136744..c38ea99 100644 --- a/src/tests/logging.h +++ b/src/tests/logging.h @@ -18,10 +18,10 @@ void run_logging() { BLT_ERROR("Hello World!\n"); BLT_FATAL("Hello World!\n"); - blt::logging::trace << "Hello! " << "Double stream insertion! " << 51 << 65 << " "; - blt::logging::trace << "Same Line! "; - blt::logging::trace << "Write the end!\n"; - blt::logging::trace << "Seeee\n Super\n"; +// blt::logging::trace << "Hello! " << "Double stream insertion! " << 51 << 65 << " "; +// blt::logging::trace << "Same Line! "; +// blt::logging::trace << "Write the end!\n"; +// blt::logging::trace << "Seeee\n Super\n"; std::string hello = "superSexyMax"; std::cout << "String starts with: " << blt::string::contains(hello, "superSexyMaxE") << "\n"; diff --git a/src/tests/main.cpp b/src/tests/main.cpp index da44e63..28e8d6d 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -19,10 +19,10 @@ int main() { nbt_tests(); - blt::logging::trace << "Test Output!\n"; - blt::logging::trace << 5; - blt::logging::trace << 5; - blt::logging::trace << 5; +// blt::logging::trace << "Test Output!\n"; +// blt::logging::trace << 5; +// blt::logging::trace << 5; +// blt::logging::trace << 5; blt::logging::flush(); diff --git a/src/tests/nbt_tests.h b/src/tests/nbt_tests.h index 45a9194..bb2580f 100644 --- a/src/tests/nbt_tests.h +++ b/src/tests/nbt_tests.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/src/tests/profiling_tests.h b/src/tests/profiling_tests.h index 2d49f28..dcd26e3 100644 --- a/src/tests/profiling_tests.h +++ b/src/tests/profiling_tests.h @@ -8,7 +8,7 @@ #define BLT_TESTS_PROFILING_TESTS_H #include "blt/profiling/profiler.h" -#include "blt/std/logging_old.h" +#include "blt/std/logging.h" #include "blt/std/time.h" #include "blt/std/format.h" diff --git a/src/tests/queue_tests.h b/src/tests/queue_tests.h index b251438..052b670 100644 --- a/src/tests/queue_tests.h +++ b/src/tests/queue_tests.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include