2022-11-18 21:50:49 +05:00
|
|
|
#pragma once
|
|
|
|
|
2023-01-11 14:46:49 +05:00
|
|
|
#include "../containers/array.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
|
|
|
#include <sstream>
|
|
|
|
#include <vector>
|
2022-11-18 21:50:49 +05:00
|
|
|
|
|
|
|
namespace hpr
|
|
|
|
{
|
2023-01-11 14:46:49 +05:00
|
|
|
|
|
|
|
|
|
|
|
namespace logging
|
|
|
|
{
|
|
|
|
enum Severity
|
|
|
|
{
|
|
|
|
Emergency,
|
|
|
|
Alert,
|
|
|
|
Critical,
|
|
|
|
Error,
|
|
|
|
Warning,
|
|
|
|
Notice,
|
|
|
|
Info,
|
|
|
|
Debug
|
|
|
|
};
|
|
|
|
|
|
|
|
class Sink
|
|
|
|
{
|
|
|
|
//friend class Logger;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
Severity p_severity;
|
|
|
|
std::string_view p_message;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Sink() :
|
|
|
|
p_severity {Emergency},
|
|
|
|
p_message {}
|
|
|
|
{}
|
|
|
|
|
|
|
|
Sink(Severity severity) :
|
|
|
|
p_severity {severity},
|
|
|
|
p_message {}
|
|
|
|
{}
|
|
|
|
|
|
|
|
void addMessage(const std::string_view& message)
|
|
|
|
{
|
|
|
|
p_message = message;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual
|
|
|
|
void flush() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual
|
|
|
|
~Sink() = default;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class StandardOutput : public Sink
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
StandardOutput() :
|
|
|
|
Sink()
|
|
|
|
{}
|
|
|
|
|
|
|
|
explicit
|
|
|
|
StandardOutput(Severity severity) :
|
|
|
|
Sink(severity)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void flush() override
|
|
|
|
{
|
|
|
|
if (p_severity < Error)
|
|
|
|
std::cerr << p_message << "\n";
|
|
|
|
if (p_severity < Debug)
|
|
|
|
std::cout << p_message << "\n";
|
|
|
|
std::cout.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~StandardOutput() override = default;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class LoggerState
|
|
|
|
{
|
|
|
|
Endline,
|
|
|
|
Flush,
|
|
|
|
Exception,
|
|
|
|
Exit
|
|
|
|
};
|
|
|
|
|
2022-11-18 21:50:49 +05:00
|
|
|
class Logger
|
|
|
|
{
|
2023-01-11 14:46:49 +05:00
|
|
|
static Logger g_instance;
|
|
|
|
static darray<Sink*> g_sinks;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
Severity p_severity;
|
|
|
|
std::ostringstream p_stream;
|
|
|
|
int p_exitcode;
|
|
|
|
sarray<std::string, 8> p_levelNames;
|
|
|
|
darray<std::string> p_buffer;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
Logger() :
|
|
|
|
p_severity {Emergency},
|
|
|
|
p_stream {},
|
|
|
|
p_exitcode {-1},
|
|
|
|
p_levelNames { "Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug"}
|
|
|
|
{}
|
|
|
|
|
|
|
|
static Logger& instance()
|
|
|
|
{
|
|
|
|
return g_instance;
|
|
|
|
}
|
|
|
|
|
2022-11-18 21:50:49 +05:00
|
|
|
public:
|
2023-01-11 14:46:49 +05:00
|
|
|
|
|
|
|
static void destroy()
|
2022-11-18 21:50:49 +05:00
|
|
|
{
|
2023-01-11 14:46:49 +05:00
|
|
|
for (Sink* sink : g_sinks)
|
|
|
|
delete sink;
|
|
|
|
g_sinks.clear();
|
|
|
|
}
|
2022-11-18 21:50:49 +05:00
|
|
|
|
2023-01-11 14:46:49 +05:00
|
|
|
static darray<Sink*>& sinks()
|
2022-11-18 21:50:49 +05:00
|
|
|
{
|
2023-01-11 14:46:49 +05:00
|
|
|
return g_sinks;
|
|
|
|
}
|
2022-11-18 21:50:49 +05:00
|
|
|
|
2023-01-11 14:46:49 +05:00
|
|
|
static void addSink(Sink* sink)
|
|
|
|
{
|
|
|
|
if (sink != nullptr)
|
|
|
|
g_sinks.push(sink);
|
2022-11-18 21:50:49 +05:00
|
|
|
}
|
2023-01-11 14:46:49 +05:00
|
|
|
|
|
|
|
static Severity severity()
|
|
|
|
{
|
|
|
|
return g_instance.p_severity;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void severity(Severity severity)
|
|
|
|
{
|
|
|
|
g_instance.p_severity = severity;
|
|
|
|
}
|
|
|
|
|
|
|
|
// begin functions
|
|
|
|
friend
|
|
|
|
std::ostringstream&& log(Severity severity);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// end functions
|
|
|
|
friend
|
|
|
|
LoggerState endl();
|
|
|
|
|
|
|
|
friend
|
|
|
|
LoggerState flush();
|
|
|
|
|
|
|
|
friend
|
|
|
|
LoggerState exception();
|
|
|
|
|
|
|
|
friend
|
|
|
|
LoggerState exit(int code);
|
|
|
|
|
|
|
|
//
|
|
|
|
friend
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const LoggerState& state);
|
2022-11-18 21:50:49 +05:00
|
|
|
};
|
2023-01-11 14:46:49 +05:00
|
|
|
|
|
|
|
//
|
|
|
|
Logger Logger::g_instance;
|
|
|
|
darray<Sink*> Logger::g_sinks;
|
|
|
|
|
|
|
|
//
|
|
|
|
std::ostringstream&& log(Severity severity)
|
|
|
|
{
|
|
|
|
Logger& instance = Logger::instance();
|
|
|
|
instance.p_severity = severity;
|
|
|
|
//std::ostringstream oss;
|
|
|
|
//return instance.p_stream;
|
|
|
|
return std::move(std::ostringstream());// oss;//std::forward(oss);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostringstream&& error()
|
|
|
|
{
|
|
|
|
return log(Error);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
LoggerState endl()
|
|
|
|
{
|
|
|
|
return LoggerState::Endline;
|
|
|
|
}
|
|
|
|
|
|
|
|
LoggerState flush()
|
|
|
|
{
|
|
|
|
return LoggerState::Flush;
|
|
|
|
}
|
|
|
|
|
|
|
|
LoggerState exception()
|
|
|
|
{
|
|
|
|
return LoggerState::Exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
LoggerState exit(int code)
|
|
|
|
{
|
|
|
|
Logger& instance = Logger::instance();
|
|
|
|
instance.p_exitcode = code;
|
|
|
|
return LoggerState::Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& stream, const LoggerState& state)
|
|
|
|
{
|
|
|
|
stream << std::endl;
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << stream.rdbuf();
|
|
|
|
std::string test = oss.str();
|
|
|
|
std::cout << test << std::endl;
|
|
|
|
//static std::mutex mtx;
|
|
|
|
//std::lock_guard<std::mutex> lock(mtx);
|
|
|
|
Logger& instance = Logger::instance();
|
|
|
|
|
|
|
|
if (state >= LoggerState::Endline)
|
|
|
|
{
|
|
|
|
stream << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
//instance.p_stream << stream.rdbuf();
|
|
|
|
|
|
|
|
|
|
|
|
if (state >= LoggerState::Flush)
|
|
|
|
{
|
|
|
|
// default sink
|
|
|
|
if (Logger::sinks().is_empty())
|
|
|
|
{
|
|
|
|
std::unique_ptr<Sink> sink = std::make_unique<StandardOutput>(Logger::severity());
|
|
|
|
sink->addMessage(oss.str());
|
|
|
|
sink->flush();
|
|
|
|
//delete sink;
|
|
|
|
}
|
|
|
|
|
|
|
|
// global sinks
|
|
|
|
for (Sink* sink : Logger::sinks())
|
|
|
|
{
|
|
|
|
sink->addMessage(oss.str());
|
|
|
|
sink->flush();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == LoggerState::Exception)
|
|
|
|
{
|
|
|
|
throw std::runtime_error(oss.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == LoggerState::Exit)
|
|
|
|
{
|
|
|
|
std::exit(instance.p_exitcode);
|
|
|
|
}
|
|
|
|
|
|
|
|
//instance.p_stream.flush();
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
}
|
2022-11-18 21:50:49 +05:00
|
|
|
}
|