working on logging 2.0. Format defined, custom tags added.
parent
7033474455
commit
58ba957b1d
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
project(BLT VERSION 0.5.2)
|
project(BLT VERSION 0.6.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
@ -7,7 +7,13 @@ option(BUILD_STD "Build the BLT standard utilities." ON)
|
||||||
option(BUILD_PROFILING "Build the BLT profiler extension" ON)
|
option(BUILD_PROFILING "Build the BLT profiler extension" ON)
|
||||||
option(BUILD_NBT "Build the BLT NBT + eNBT extension" ON)
|
option(BUILD_NBT "Build the BLT NBT + eNBT extension" ON)
|
||||||
option(BUILD_TESTS "Build the BLT test set" OFF)
|
option(BUILD_TESTS "Build the BLT test set" OFF)
|
||||||
option(BLT_ENABLE_LOGGING "Enable blt::logging" ON)
|
option(BLT_ENABLE_LOGGING "Enable blt::logging (all macros and will safely disable logging function!)" ON)
|
||||||
|
option(BLT_ENABLE_TRACE "Enable blt::logging BLT_TRACE macro" ON)
|
||||||
|
option(BLT_ENABLE_DEBUG "Enable blt::logging BLT_DEBUG macro" ON)
|
||||||
|
option(BLT_ENABLE_INFO "Enable blt::logging BLT_INFO macro" ON)
|
||||||
|
option(BLT_ENABLE_WARN "Enable blt::logging BLT_WARN macro" ON)
|
||||||
|
option(BLT_ENABLE_ERROR "Enable blt::logging BLT_ERROR macro" ON)
|
||||||
|
option(BLT_ENABLE_FATAL "Enable blt::logging BLT_FATAL macro" ON)
|
||||||
|
|
||||||
if(${BUILD_STD} OR ${BUILD_PROFILING})
|
if(${BUILD_STD} OR ${BUILD_PROFILING})
|
||||||
file(GLOB_RECURSE STD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/std/*.cpp")
|
file(GLOB_RECURSE STD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/blt/std/*.cpp")
|
||||||
|
|
|
@ -3,5 +3,11 @@
|
||||||
|
|
||||||
#cmakedefine ZLIB_FOUND
|
#cmakedefine ZLIB_FOUND
|
||||||
#cmakedefine BLT_ENABLE_LOGGING
|
#cmakedefine BLT_ENABLE_LOGGING
|
||||||
|
#cmakedefine BLT_ENABLE_TRACE
|
||||||
|
#cmakedefine BLT_ENABLE_DEBUG
|
||||||
|
#cmakedefine BLT_ENABLE_INFO
|
||||||
|
#cmakedefine BLT_ENABLE_WARN
|
||||||
|
#cmakedefine BLT_ENABLE_ERROR
|
||||||
|
#cmakedefine BLT_ENABLE_FATAL
|
||||||
|
|
||||||
#endif // BLT_CONFIG_H
|
#endif // BLT_CONFIG_H
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <blt/math/vectors.h>
|
#include <blt/math/vectors.h>
|
||||||
#include <blt/math/matrix.h>
|
#include <blt/math/matrix.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
|
|
||||||
namespace blt {
|
namespace blt {
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <blt/std/queue.h>
|
#include <blt/std/queue.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ namespace blt::profiling {
|
||||||
profile getProfile(const std::string& profileName);
|
profile getProfile(const std::string& profileName);
|
||||||
|
|
||||||
void printProfile(
|
void printProfile(
|
||||||
const std::string& profileName, logging::LogLevel loggingLevel = logging::LogLevel::NONE,
|
const std::string& profileName, logging::log_level loggingLevel = logging::log_level::NONE,
|
||||||
bool averageHistory = false
|
bool averageHistory = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <blt/std/string.h>
|
#include <blt/std/string.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
|
|
||||||
namespace blt::fs {
|
namespace blt::fs {
|
||||||
std::vector<std::string> getLinesFromFile(const std::string& path);
|
std::vector<std::string> getLinesFromFile(const std::string& path);
|
||||||
|
|
|
@ -1,138 +1,99 @@
|
||||||
/*
|
/*
|
||||||
* Created by Brett on 23/01/23.
|
* Created by Brett on 20/07/23.
|
||||||
* Licensed under GNU General Public License V3.0
|
* Licensed under GNU General Public License V3.0
|
||||||
* See LICENSE file for license detail
|
* See LICENSE file for license detail
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BLT_LOGGING_H
|
#ifndef BLT_TESTS_LOGGING2_H
|
||||||
#define BLT_LOGGING_H
|
#define BLT_TESTS_LOGGING2_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <functional>
|
||||||
#include <blt/config.h>
|
#include <blt/config.h>
|
||||||
|
|
||||||
namespace blt::logging {
|
namespace blt::logging {
|
||||||
|
|
||||||
enum class LogLevel {
|
enum class log_level {
|
||||||
// low level
|
// low level
|
||||||
TRACE0, TRACE1, TRACE2, TRACE3,
|
TRACE0, TRACE1, TRACE2, TRACE3,
|
||||||
// normal
|
// normal
|
||||||
TRACE, DEBUG, INFO,
|
TRACE, DEBUG, INFO,
|
||||||
WARN,
|
|
||||||
// errors
|
// errors
|
||||||
ERROR, FATAL,
|
WARN, ERROR, FATAL,
|
||||||
// default
|
// default
|
||||||
NONE
|
NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
class ILogHandler {
|
struct log_tag {
|
||||||
public:
|
// tag without the ${{ or }}
|
||||||
virtual void log(std::string message, LogLevel level) = 0;
|
std::string tag;
|
||||||
|
// function to run, log level and raw user input string are provided
|
||||||
|
std::function<std::string(blt::logging::log_level, std::string)> func;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LOG_PROPERTIES {
|
struct log_format {
|
||||||
bool m_useColor = true;
|
/**
|
||||||
bool m_logToConsole = true;
|
* the log output format is the string which will be used to create the log output string
|
||||||
bool m_logToFile = true;
|
*
|
||||||
// include file + line data?
|
* Available tags:
|
||||||
bool m_logWithData = true;
|
* - ${{YEAR}} // current year
|
||||||
// print the whole path or just the file name?
|
* - ${{MONTH}} // current month
|
||||||
bool m_logFullPath = false;
|
* - ${{DAY}} // current day
|
||||||
const char* m_directory = "./";
|
* - ${{HOUR}} // current hour
|
||||||
LogLevel minLevel = LogLevel::TRACE;
|
* - ${{MINUTE}} // current minute
|
||||||
|
* - ${{SECOND}} // current second
|
||||||
explicit constexpr LOG_PROPERTIES(
|
* - ${{MS}} // current millisecond
|
||||||
bool useColor, bool logToConsole, bool logToFile, const char* directory
|
* - ${{LF}} // log level color (ASCII color code)
|
||||||
):
|
* - ${{R}} // ASCII color reset
|
||||||
m_useColor(useColor), m_logToConsole(logToConsole), m_logToFile(logToFile),
|
* - ${{LOG_LEVEL}} // current log level
|
||||||
m_directory(directory) {}
|
* - ${{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
|
||||||
explicit constexpr LOG_PROPERTIES() = default;
|
* - ${{LINE}} // line in the from which the macro is invoked
|
||||||
|
* - ${{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}}";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logger {
|
void log(log_level level, const std::string& format, const char* file, int line, ...);
|
||||||
LogLevel 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{LogLevel::NONE};
|
|
||||||
|
|
||||||
static logger trace{LogLevel::TRACE};
|
|
||||||
static logger debug{LogLevel::DEBUG};
|
|
||||||
static logger info{LogLevel::INFO};
|
|
||||||
static logger warn{LogLevel::WARN};
|
|
||||||
static logger error{LogLevel::ERROR};
|
|
||||||
static logger fatal{LogLevel::FATAL};
|
|
||||||
|
|
||||||
static inline logger& getLoggerFromLevel(LogLevel 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<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||||
static inline logger& operator<<(logger& out, T t) {
|
inline void log(T t, log_level level, const char* file, int line) {
|
||||||
out.log(std::to_string(t));
|
log(std::to_string(t), level, file, line);
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(LOG_PROPERTIES properties);
|
|
||||||
|
|
||||||
void log_internal(
|
|
||||||
const std::string& format, LogLevel 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<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
|
||||||
inline void log_internal(
|
|
||||||
T t, LogLevel 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 flush();
|
||||||
|
|
||||||
void testLogging();
|
void setThreadName(const std::string& name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BLT_ENABLE_LOGGING
|
#ifdef BLT_LOGGING_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace blt::logging {
|
||||||
|
|
||||||
|
void log(const std::string& format, log_level level, const char* file, int line, ...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setThreadName(const std::string& name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
std::cerr.flush();
|
||||||
|
std::cout.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BLT_ENABLE_LOGGING) || defined(BLT_DISABLE_LOGGING)
|
||||||
|
#define BLT_LOG(format, level, ...)
|
||||||
#define BLT_TRACE(format, ...)
|
#define BLT_TRACE(format, ...)
|
||||||
#define BLT_DEBUG(format, ...)
|
#define BLT_DEBUG(format, ...)
|
||||||
#define BLT_INFO(format, ...)
|
#define BLT_INFO(format, ...)
|
||||||
|
@ -140,14 +101,42 @@ namespace blt::logging {
|
||||||
#define BLT_ERROR(format, ...)
|
#define BLT_ERROR(format, ...)
|
||||||
#define BLT_FATAL(format, ...)
|
#define BLT_FATAL(format, ...)
|
||||||
#else
|
#else
|
||||||
#ifndef BLT_DISABLE_LOGGING
|
#define BLT_LOG(format, level, ...) log(format, level, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
#define BLT_TRACE(format, ...) log_internal(format, blt::logging::LogLevel::TRACE, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
#ifndef BLT_ENABLE_TRACE
|
||||||
#define BLT_DEBUG(format, ...) log_internal(format, blt::logging::LogLevel::DEBUG, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
#define BLT_TRACE(format, ...)
|
||||||
#define BLT_INFO(format, ...) log_internal(format, blt::logging::LogLevel::INFO, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
#else
|
||||||
#define BLT_WARN(format, ...) log_internal(format, blt::logging::LogLevel::WARN, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
#define BLT_TRACE(format, ...) BLT_LOG(format, blt::logging::log_level::TRACE, ##__VA_ARGS__)
|
||||||
#define BLT_ERROR(format, ...) log_internal(format, blt::logging::LogLevel::ERROR, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
#endif
|
||||||
#define BLT_FATAL(format, ...) log_internal(format, blt::logging::LogLevel::FATAL, __FILE__, __LINE__, true, ##__VA_ARGS__)
|
|
||||||
|
#ifndef BLT_ENABLE_DEBUG
|
||||||
|
#define BLT_DEBUG(format, ...)
|
||||||
|
#else
|
||||||
|
#define BLT_DEBUG(format, ...) BLT_LOG(format, blt::logging::log_level::DEBUG, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLT_ENABLE_INFO
|
||||||
|
#define BLT_INFO(format, ...)
|
||||||
|
#else
|
||||||
|
#define BLT_INFO(format, ...) BLT_LOG(format, blt::logging::log_level::INFO, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLT_ENABLE_WARN
|
||||||
|
#define BLT_WARN(format, ...)
|
||||||
|
#else
|
||||||
|
#define BLT_WARN(format, ...) BLT_LOG(format, blt::logging::log_level::WARN, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLT_ENABLE_ERROR
|
||||||
|
#define BLT_ERROR(format, ...)
|
||||||
|
#else
|
||||||
|
#define BLT_ERROR(format, ...) BLT_LOG(format, blt::logging::log_level::ERROR, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLT_ENABLE_FATAL
|
||||||
|
#define BLT_FATAL(format, ...)
|
||||||
|
#else
|
||||||
|
#define BLT_FATAL(format, ...) BLT_LOG(format, blt::logging::log_level::FATAL, ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //BLT_LOGGING_H
|
#endif //BLT_TESTS_LOGGING2_H
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* 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 <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <blt/config.h>
|
||||||
|
|
||||||
|
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<typename T, typename std::enable_if<std::is_arithmetic<T>::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<typename T, typename std::enable_if<std::is_arithmetic<T>::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
|
|
@ -12,7 +12,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
|
|
||||||
namespace blt::string {
|
namespace blt::string {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <blt/std/time.h>
|
#include <blt/std/time.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <blt/std/format.h>
|
#include <blt/std/format.h>
|
||||||
|
@ -30,7 +30,7 @@ namespace blt::profiling {
|
||||||
difference(difference), name(std::move(name)), total(total) {}
|
difference(difference), name(std::move(name)), total(total) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void println(const std::vector<std::string>&& lines, logging::LogLevel level) {
|
inline void println(const std::vector<std::string>&& lines, logging::log_level level) {
|
||||||
auto& logger = logging::getLoggerFromLevel(level);
|
auto& logger = logging::getLoggerFromLevel(level);
|
||||||
for (const auto& line : lines)
|
for (const auto& line : lines)
|
||||||
logger << line << "\n";
|
logger << line << "\n";
|
||||||
|
@ -104,7 +104,7 @@ namespace blt::profiling {
|
||||||
}
|
}
|
||||||
|
|
||||||
void printProfile(
|
void printProfile(
|
||||||
const std::string& profileName, logging::LogLevel loggingLevel, bool averageHistory
|
const std::string& profileName, logging::log_level loggingLevel, bool averageHistory
|
||||||
) {
|
) {
|
||||||
auto& profile = profiles[profileName];
|
auto& profile = profiles[profileName];
|
||||||
const auto& intervals = profile.intervals;
|
const auto& intervals = profile.intervals;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
#include <blt/std/format.h>
|
#include <blt/std/format.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "blt/std/logging.h"
|
#include "blt/std/logging_old.h"
|
||||||
|
|
||||||
std::string createPadding(int padAmount) {
|
std::string createPadding(int padAmount) {
|
||||||
std::string padStr;
|
std::string padStr;
|
||||||
|
|
|
@ -1,245 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Created by Brett on 23/01/23.
|
* Created by Brett on 20/07/23.
|
||||||
* Licensed under GNU General Public License V3.0
|
* Licensed under GNU General Public License V3.0
|
||||||
* See LICENSE file for license detail
|
* See LICENSE file for license detail
|
||||||
*/
|
*/
|
||||||
|
#define BLT_LOGGING_IMPLEMENTATION
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <blt/std/time.h>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include "blt/std/string.h"
|
|
||||||
#include "blt/std/format.h"
|
|
||||||
#include <fstream>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <ios>
|
|
||||||
#include <thread>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <blt/std/memory.h>
|
|
||||||
|
|
||||||
// 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 <blt/std/memory.h>
|
|
||||||
|
|
||||||
|
|
||||||
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<char> buffer{static_cast<unsigned long>(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, LogLevel 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 > LogLevel::WARN)
|
|
||||||
std::cerr << outputString;
|
|
||||||
else
|
|
||||||
std::cout << outputString;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BLT_LOGGING_PROPERTIES.m_logToFile) {
|
|
||||||
writer->writeLine(fileString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_internal(const std::string& format, LogLevel 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<std::thread::id, std::unordered_map<LogLevel, std::string>> 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 == LogLevel::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, LogLevel 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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* Created by Brett on 23/01/23.
|
||||||
|
* Licensed under GNU General Public License V3.0
|
||||||
|
* See LICENSE file for license detail
|
||||||
|
*/
|
||||||
|
#include <blt/std/logging_old.h>
|
||||||
|
#include <blt/std/time.h>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include "blt/std/string.h"
|
||||||
|
#include "blt/std/format.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <ios>
|
||||||
|
#include <thread>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <blt/std/memory.h>
|
||||||
|
|
||||||
|
// 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 <blt/std/memory.h>
|
||||||
|
|
||||||
|
|
||||||
|
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<char> buffer{static_cast<unsigned long>(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<std::thread::id, std::unordered_map<log_level, std::string>> 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <blt/nbt/nbt.h>
|
#include <blt/nbt/nbt.h>
|
||||||
#include <blt/profiling/profiler.h>
|
#include <blt/profiling/profiler.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
#include <blt/std/format.h>
|
#include <blt/std/format.h>
|
||||||
#include <blt/std/filesystem.h>
|
#include <blt/std/filesystem.h>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define BLT_TESTS_PROFILING_TESTS_H
|
#define BLT_TESTS_PROFILING_TESTS_H
|
||||||
|
|
||||||
#include "blt/profiling/profiler.h"
|
#include "blt/profiling/profiler.h"
|
||||||
#include "blt/std/logging.h"
|
#include "blt/std/logging_old.h"
|
||||||
#include "blt/std/time.h"
|
#include "blt/std/time.h"
|
||||||
#include "blt/std/format.h"
|
#include "blt/std/format.h"
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ static void runProfilingAndTableTests() {
|
||||||
BLT_END_INTERVAL("Help", "UnderSet" + std::to_string(i));
|
BLT_END_INTERVAL("Help", "UnderSet" + std::to_string(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
BLT_PRINT_PROFILE("Help", blt::logging::LogLevel::TRACE);
|
BLT_PRINT_PROFILE("Help", blt::logging::log_level::TRACE);
|
||||||
BLT_TRACE("");
|
BLT_TRACE("");
|
||||||
|
|
||||||
blt::string::TableFormatter formatter;
|
blt::string::TableFormatter formatter;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <blt/std/queue.h>
|
#include <blt/std/queue.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging_old.h>
|
||||||
#include <blt/profiling/profiler.h>
|
#include <blt/profiling/profiler.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <blt/std/random.h>
|
#include <blt/std/random.h>
|
||||||
|
@ -140,9 +140,9 @@ static inline void test_queues() {
|
||||||
fill_queues();
|
fill_queues();
|
||||||
random_access();
|
random_access();
|
||||||
|
|
||||||
BLT_PRINT_PROFILE("Insert", blt::logging::LogLevel::INFO, true);
|
BLT_PRINT_PROFILE("Insert", blt::logging::log_level::INFO, true);
|
||||||
BLT_PRINT_PROFILE("Access", blt::logging::LogLevel::INFO, true);
|
BLT_PRINT_PROFILE("Access", blt::logging::log_level::INFO, true);
|
||||||
BLT_PRINT_PROFILE("Random", blt::logging::LogLevel::INFO, true);
|
BLT_PRINT_PROFILE("Random", blt::logging::log_level::INFO, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLT_TESTS_QUEUE_TESTS_H
|
#endif //BLT_TESTS_QUEUE_TESTS_H
|
||||||
|
|
Loading…
Reference in New Issue