Made some changes to logger and picked a new direction to chase smart text concept
This commit is contained in:
parent
d2102e320a
commit
6134a66c71
@ -8,13 +8,21 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#ifndef THROW_WITH_INFO
|
||||||
|
#ifdef CODE_ERROR_LOCATIONS
|
||||||
|
#define THROW_WITH_INFO(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__)
|
||||||
|
#else
|
||||||
|
#define THROW_WITH_INFO(type, ...) throw type(__VA_ARGS__)
|
||||||
|
#endif // CODE_ERROR_LOCATIONS
|
||||||
|
#endif // THROW_WITH_INFO
|
||||||
|
|
||||||
#ifndef THROW
|
#ifndef THROW
|
||||||
#ifdef CODE_ERROR_LOCATIONS
|
#ifdef LOGGING
|
||||||
#define THROW(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__)
|
#define THROW_WTIH_INFO(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__)
|
||||||
#else
|
#else
|
||||||
#define THROW(type, ...) throw type(__VA_ARGS__)
|
#define THROW(...) THROW_WITH_INFO(__VA_ARGS__)
|
||||||
#endif
|
#endif // LOGGING
|
||||||
#endif
|
#endif // THROW
|
||||||
|
|
||||||
namespace nb {
|
namespace nb {
|
||||||
|
|
||||||
@ -73,7 +81,7 @@ protected:
|
|||||||
);
|
);
|
||||||
|
|
||||||
_msg += std::string(ErrorType::type);
|
_msg += std::string(ErrorType::type);
|
||||||
_msg += "." + std::to_string(_code);
|
_msg += "[" + std::to_string(_code) + "]";
|
||||||
if (line && filename.size()) {
|
if (line && filename.size()) {
|
||||||
_msg += " in \'" + filename + "\':" + std::to_string(line);
|
_msg += " in \'" + filename + "\':" + std::to_string(line);
|
||||||
}
|
}
|
||||||
@ -91,7 +99,7 @@ protected:
|
|||||||
while((newline_pos=what_msg.find("\n", newline_pos+1))!= std::string::npos) {
|
while((newline_pos=what_msg.find("\n", newline_pos+1))!= std::string::npos) {
|
||||||
what_msg.replace(newline_pos, 1, "\n ");
|
what_msg.replace(newline_pos, 1, "\n ");
|
||||||
}
|
}
|
||||||
_msg += "\n Trace: " + what_msg;
|
_msg += "\n Trace - " + what_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int _code;
|
unsigned int _code;
|
||||||
@ -105,9 +113,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
using ErrorBase<Error>::ErrorBase;
|
using ErrorBase<Error>::ErrorBase;
|
||||||
//Error(unsigned int code) : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code)) {}
|
|
||||||
//Error(unsigned int code, const std::exception& trace, unsigned int line=0, const std::string& filename="")
|
|
||||||
// : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code), trace, line, filename) {}
|
|
||||||
|
|
||||||
friend ErrorBase<Error>;
|
friend ErrorBase<Error>;
|
||||||
|
|
||||||
@ -117,18 +122,6 @@ protected:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
template<class ErrorType>
|
|
||||||
ErrorBase<ErrorType>::ErrorBase(
|
|
||||||
unsigned int code,
|
|
||||||
std::string msg,
|
|
||||||
const std::exception& trace,
|
|
||||||
unsigned int line,
|
|
||||||
std::string filename
|
|
||||||
) noexcept
|
|
||||||
: ErrorBase<ErrorType>(code, msg, std::make_shared<Error>(trace), line, filename) {}
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<class ErrorType>
|
template<class ErrorType>
|
||||||
std::string ErrorBase<ErrorType>::lookup(unsigned int code) {
|
std::string ErrorBase<ErrorType>::lookup(unsigned int code) {
|
||||||
for (auto kv : ErrorType::ErrorMessages) {
|
for (auto kv : ErrorType::ErrorMessages) {
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
#ifndef _NB_LOGGER
|
#ifndef _NB_LOGGER
|
||||||
#define _NB_LOGGER
|
#define _NB_LOGGER
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "SmartStreams.hpp"
|
|
||||||
#include "ThreadSafeQueue.hpp"
|
#include "ThreadSafeQueue.hpp"
|
||||||
|
|
||||||
namespace nb {
|
namespace nb {
|
||||||
@ -23,42 +23,111 @@ struct LogEvent{
|
|||||||
const std::string msg;
|
const std::string msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Logger {
|
|
||||||
typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&);
|
typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&);
|
||||||
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
|
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
|
||||||
|
|
||||||
|
template<typename StreamType>
|
||||||
|
class Logger {
|
||||||
public:
|
public:
|
||||||
Logger();
|
Logger(StreamType& stream) : _ostream(&stream) {}
|
||||||
|
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
unsigned int count() const;
|
unsigned int count() const;
|
||||||
|
|
||||||
bool run();
|
bool run();
|
||||||
bool stop();
|
bool stop();
|
||||||
LogEvent popProcess();
|
LogEvent pop();
|
||||||
LogEvent popDelete();
|
void flush() {
|
||||||
void flush();
|
while(_queue.size()) {
|
||||||
void deleteAll();
|
pop();
|
||||||
void msg(const std::string&, uint8_t lvl=0);
|
}
|
||||||
void warn(const std::string&, uint8_t lvl=1);
|
}
|
||||||
void warn(const std::exception&, uint8_t lvl=1);
|
void deleteAll() {
|
||||||
void error(const std::string&, uint8_t lvl=0xFF);
|
_queue.empty();
|
||||||
void error(const std::exception&, uint8_t lvl=0xFF);
|
}
|
||||||
|
void msg(const std::string& _msg, uint8_t lvl=0) {
|
||||||
|
_queue.push(LogEvent{std::chrono::system_clock::now(), lvl, _msg});
|
||||||
|
}
|
||||||
|
void warn(const std::string& _msg, uint8_t lvl=1) {
|
||||||
|
msg(_msg, lvl);
|
||||||
|
}
|
||||||
|
void warn(const std::exception& _err, uint8_t lvl=1) {
|
||||||
|
msg(_err.what(), lvl);
|
||||||
|
}
|
||||||
|
void error(const std::string& _msg, uint8_t lvl=0xFF) {
|
||||||
|
msg(_msg, lvl);
|
||||||
|
}
|
||||||
|
void error(const std::exception& _err, uint8_t lvl=0xFF) {
|
||||||
|
msg(_err.what(), lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void process(const LogEvent&);
|
virtual void process(const LogEvent& event) {
|
||||||
|
uint8_t lvl = event.lvl;
|
||||||
|
try {
|
||||||
|
*_ostream << _function_map.at(lvl)(event.time, event.msg).c_str();
|
||||||
|
} catch (std::out_of_range e) {
|
||||||
|
*_ostream << _function_map.at(0)(event.time, event.msg).c_str();
|
||||||
|
//*_ostream << event.msg;
|
||||||
|
}
|
||||||
|
*_ostream << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
const LogProcessFunctionMap _function_map;
|
static const LogProcessFunctionMap _function_map;
|
||||||
|
|
||||||
ThreadsafeQueue<LogEvent> _queue;
|
ThreadsafeQueue<LogEvent> _queue;
|
||||||
T* _ostream;
|
StreamType* const _ostream;
|
||||||
// std::condition_variable _cond;
|
std::atomic<bool> _running;
|
||||||
// mutable std::mutex _mutex;
|
|
||||||
mutable std::mutex _runningMutex;
|
|
||||||
bool _running;
|
|
||||||
std::shared_ptr<std::thread> _runningThread = nullptr;
|
std::shared_ptr<std::thread> _runningThread = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
const LogProcessFunctionMap Logger<ST>::_function_map = {
|
||||||
|
{0, [](const LoggerTimePoint& tp, const std::string& msg){
|
||||||
|
return msg;
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
bool Logger<ST>::isRunning() const {
|
||||||
|
return _running && bool(_runningThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
unsigned int Logger<ST>::count() const {
|
||||||
|
return _queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
bool Logger<ST>::run() {
|
||||||
|
if (!isRunning()) {
|
||||||
|
_runningThread = std::make_shared<std::thread>([&]{
|
||||||
|
while(this->isRunning()) {
|
||||||
|
this->flush();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
bool Logger<ST>::stop() {
|
||||||
|
if (isRunning()) {
|
||||||
|
_running = false;
|
||||||
|
_runningThread->join();
|
||||||
|
_runningThread = nullptr;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
return isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ST>
|
||||||
|
LogEvent Logger<ST>::pop() {
|
||||||
|
std::shared_ptr<LogEvent> event;
|
||||||
|
_queue.pop(event);
|
||||||
|
process(*event);
|
||||||
|
return *event;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nb
|
} // namespace nb
|
||||||
#endif // _NB_LOGGER
|
#endif // _NB_LOGGER
|
||||||
92
include/SmartStreams.hpp
Normal file
92
include/SmartStreams.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _NB_SMARTSTREAM
|
||||||
|
#define _NB_SMARTSTREAM
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace nb {
|
||||||
|
|
||||||
|
using RGB = std::array<unsigned char, 3>;
|
||||||
|
|
||||||
|
std::string toANSI(const RGB& color) {
|
||||||
|
return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+
|
||||||
|
";"+std::to_string(color[2])+"m";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toANSI(const unsigned int& color) {
|
||||||
|
return "\x1b[38;5;"+std::to_string(color)+"m";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename Derived=void>
|
||||||
|
struct SmartText {
|
||||||
|
SmartText(const U& val) : msg(val) {}
|
||||||
|
|
||||||
|
const U msg;
|
||||||
|
|
||||||
|
template<typename C, typename T>
|
||||||
|
void process(std::basic_ostream<C,T>& stream) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
struct SmartText<std::string, Derived> {
|
||||||
|
template <std::size_t N>
|
||||||
|
SmartText(char const(&val) [N]) : msg(val) {}
|
||||||
|
SmartText(const std::string& val) : msg(val) {}
|
||||||
|
SmartText(const char* val) : msg(val) {}
|
||||||
|
|
||||||
|
const std::string msg;
|
||||||
|
|
||||||
|
template<typename C, typename T>
|
||||||
|
void process(std::basic_ostream<C,T>& stream) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U, typename Derived>
|
||||||
|
template <typename C, typename T>
|
||||||
|
void SmartText<U,Derived>::process(std::basic_ostream<C,T>& stream) const {
|
||||||
|
if (std::is_void<Derived>::value) {
|
||||||
|
stream << msg;
|
||||||
|
} else {
|
||||||
|
static_cast<Derived*>(this)->process(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename C, typename T, typename U, typename D>
|
||||||
|
std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& stream, const SmartText<U,D>& smt) {
|
||||||
|
if (std::is_void<D>::value) {
|
||||||
|
stream << smt.msg;
|
||||||
|
} else {
|
||||||
|
static_cast<const D*>(&smt)->process(stream);
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct TerminalColor : public SmartText<U, TerminalColor<U>> {
|
||||||
|
typedef SmartText<U, TerminalColor<U>> Base;
|
||||||
|
using Base::msg;
|
||||||
|
|
||||||
|
explicit TerminalColor(unsigned int color, const U& val)
|
||||||
|
: Base(val), colorSequence(toANSI(color)) { }
|
||||||
|
explicit TerminalColor(const RGB& color, const U& val)
|
||||||
|
: Base(val), colorSequence(toANSI(color)) { }
|
||||||
|
|
||||||
|
const std::string colorSequence;
|
||||||
|
|
||||||
|
template <typename C, typename T>
|
||||||
|
void process(std::basic_ostream<C, T>& stream) const {
|
||||||
|
if (&stream == &std::cout) {
|
||||||
|
stream << colorSequence << msg << "\x1b[0m";
|
||||||
|
} else {
|
||||||
|
stream << msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _NB_SMARTSTREAM
|
||||||
@ -1,87 +0,0 @@
|
|||||||
#include "Logger.hpp"
|
|
||||||
|
|
||||||
namespace nb {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool Logger<>::isRunning() const {
|
|
||||||
std::lock_guard<std::mutex> lock(_runningMutex);
|
|
||||||
return _running;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Logger::count() const {
|
|
||||||
return _queue.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Logger::run() {
|
|
||||||
std::lock_guard<std::mutex> lock(_runningMutex);
|
|
||||||
if (!_running) {
|
|
||||||
_runningThread = std::make_shared<std::thread>([&]{
|
|
||||||
while(this->_running) {
|
|
||||||
this->flush();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return _running;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Logger::stop() {
|
|
||||||
std::lock_guard<std::mutex> lock(_runningMutex);
|
|
||||||
_running = false;
|
|
||||||
_runningThread->join();
|
|
||||||
return _running;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::process(const LogEvent& event) {
|
|
||||||
uint8_t lvl = event.lvl;
|
|
||||||
try {
|
|
||||||
_ostream << _function_map.at(lvl)(event.time, event.msg).c_str();
|
|
||||||
} catch (std::out_of_range e) {
|
|
||||||
_ostream << _function_map[0](event.time, event.msg).c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogEvent Logger::popProcess() {
|
|
||||||
std::shared_ptr<LogEvent> event;
|
|
||||||
_queue.pop(event);
|
|
||||||
process(*event);
|
|
||||||
return *event;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogEvent Logger::popDelete() {
|
|
||||||
std::shared_ptr<LogEvent> event;
|
|
||||||
_queue.pop(event);
|
|
||||||
process(*event);
|
|
||||||
return *event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::flush() {
|
|
||||||
while(_queue.size()) {
|
|
||||||
popProcess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::deleteAll() {
|
|
||||||
_queue.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::msg(const std::string& _msg, uint8_t lvl) {
|
|
||||||
_queue.push(LogEvent{std::chrono::system_clock::now(), lvl, _msg});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::warn(const std::string& _msg, uint8_t lvl) {
|
|
||||||
msg(_msg, lvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::warn(const std::exception& _err, uint8_t lvl) {
|
|
||||||
msg(_err.what(), lvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::error(const std::string& _msg, uint8_t lvl) {
|
|
||||||
msg(_msg, lvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::error(const std::exception& _err, uint8_t lvl) {
|
|
||||||
msg(_err.what(), lvl);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Errors.hpp"
|
#include "Errors.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "Logger.hpp"
|
||||||
|
|
||||||
using namespace nb;
|
using namespace nb;
|
||||||
|
|
||||||
@ -40,7 +41,13 @@ int main() {
|
|||||||
THROW(TestError, TestError::ErrorCodes::A, e);
|
THROW(TestError, TestError::ErrorCodes::A, e);
|
||||||
}
|
}
|
||||||
} catch(const std::exception& e) {
|
} catch(const std::exception& e) {
|
||||||
THROW(Error, Error::ErrorCodes::UNDEFINED, e);
|
// THROW(Error, Error::ErrorCodes::UNDEFINED, e);
|
||||||
|
Logger log(std::cout);
|
||||||
|
std::cout << "Logger is starting: " << log.run() << std::endl;
|
||||||
|
std::cout << "Logger is running: " << log.isRunning() << std::endl;
|
||||||
|
log.error(e);
|
||||||
|
log.stop();
|
||||||
|
std::cout << "Logger is running: " << log.isRunning() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
5
tests/SmartStreamTest/CMakeLists.txt
Normal file
5
tests/SmartStreamTest/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.26.0)
|
||||||
|
project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX)
|
||||||
|
|
||||||
|
add_executable(SmartStreamTest main.cpp)
|
||||||
|
target_link_libraries(SmartStreamTest NBCore)
|
||||||
25
tests/SmartStreamTest/main.cpp
Normal file
25
tests/SmartStreamTest/main.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
#include "SmartStreams.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
auto test = nb::TerminalColor(9, 2030);
|
||||||
|
|
||||||
|
std::cout << test;
|
||||||
|
|
||||||
|
std::ofstream file;
|
||||||
|
file.open("test.txt");
|
||||||
|
if (file.is_open()) {
|
||||||
|
file << test;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user