Back to C++20 standard!
Logging is worked (AdcOstreamLogger and AdcSPDLOGLogger classes)
This commit is contained in:
@@ -8,9 +8,9 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#if __has_include(<unistd.h>) // POSIX
|
||||
@@ -21,8 +21,10 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||
#endif
|
||||
|
||||
|
||||
#include "../common/adc_utils.h"
|
||||
#include "adc_net_concepts.h"
|
||||
|
||||
|
||||
namespace adc
|
||||
{
|
||||
|
||||
@@ -30,87 +32,6 @@ namespace adc
|
||||
/* SOME USEFULL PRIVITIVES */
|
||||
|
||||
|
||||
// A simple std::ostream logger
|
||||
class AdcTrivialLogger
|
||||
{
|
||||
public:
|
||||
virtual ~AdcTrivialLogger() = default;
|
||||
|
||||
// protected:
|
||||
static constexpr std::string_view errorLevelMark{"error"};
|
||||
static constexpr std::string_view warnLevelMark{"warning"};
|
||||
static constexpr std::string_view infoLevelMark{"info"};
|
||||
|
||||
std::basic_ostream<char>& _stream;
|
||||
|
||||
AdcTrivialLogger(std::basic_ostream<char>& stream = std::cout) : _stream(stream) {}
|
||||
|
||||
template <traits::formattable... ArgTs>
|
||||
std::string logMsgFormat(std::string_view level_mark, std::string_view fmt, ArgTs&&... args)
|
||||
{
|
||||
std::string s;
|
||||
std::format_to(std::back_inserter(s), fmt, std::forward<ArgTs>(args)...);
|
||||
|
||||
std::stringstream st;
|
||||
|
||||
const std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
|
||||
// format log-message in form:
|
||||
// [YYYY-MM-DD HH:MM:SS][level] log-message
|
||||
//
|
||||
st << std::put_time(std::localtime(&now), "[%F %T]") << "[" << level_mark << "] " << s;
|
||||
|
||||
return st.str();
|
||||
}
|
||||
|
||||
|
||||
// define default logging function of ERROR, WARNING and INFO levels
|
||||
template <traits::formattable... ArgTs>
|
||||
void logError(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
||||
{
|
||||
using obj_t = decltype(self);
|
||||
|
||||
if constexpr (std::same_as<std::remove_cvref_t<obj_t>, AdcTrivialLogger>) {
|
||||
std::forward<obj_t>(self)._stream
|
||||
<< std::forward<obj_t>(self).logMsgFormat(errorLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
||||
<< std::flush;
|
||||
} else {
|
||||
std::forward<obj_t>(self).logError(fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <traits::formattable... ArgTs>
|
||||
void logWarn(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
||||
{
|
||||
using obj_t = decltype(self);
|
||||
|
||||
if constexpr (std::same_as<obj_t, AdcTrivialLogger>) {
|
||||
std::forward<obj_t>(self)._stream
|
||||
<< std::forward<obj_t>(self).logMsgFormat(warnLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
||||
<< std::flush;
|
||||
} else {
|
||||
std::forward<obj_t>(self).logWarn(fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <traits::formattable... ArgTs>
|
||||
void logInfo(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
||||
{
|
||||
using obj_t = decltype(self);
|
||||
|
||||
if constexpr (std::same_as<obj_t, AdcTrivialLogger>) {
|
||||
std::forward<obj_t>(self)._stream
|
||||
<< std::forward<obj_t>(self).logMsgFormat(infoLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
||||
<< std::flush;
|
||||
} else {
|
||||
std::forward<obj_t>(self).logInfo(fmt, std::forward<ArgTs>(args)...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static_assert(interfaces::adc_logger_c<AdcTrivialLogger>, "!!!!!!!!!!!");
|
||||
|
||||
// A generic implementation of POSIX OS daemon
|
||||
class AdcPosixGenericDaemon
|
||||
{
|
||||
@@ -303,25 +224,39 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
static_assert(interfaces::adc_logger_c<utils::AdcOstreamLogger<>>, "!!!!!");
|
||||
|
||||
|
||||
|
||||
/* very generic network server */
|
||||
|
||||
template <typename IdentT = std::string>
|
||||
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager, public AdcTrivialLogger
|
||||
template <typename IdentT = std::string, interfaces::adc_logger_c LoggerT = utils::AdcOstreamLogger<char>>
|
||||
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager, public LoggerT
|
||||
{
|
||||
public:
|
||||
typedef IdentT server_ident_t;
|
||||
typedef LoggerT logger_t;
|
||||
|
||||
AdcGenericNetServer(const server_ident_t& id, std::basic_ostream<char>& log_stream = std::cout)
|
||||
: AdcTrivialLogger(log_stream), _serverIdent(id)
|
||||
template <typename... LoggerCtorArgTs>
|
||||
AdcGenericNetServer(const server_ident_t& id, LoggerCtorArgTs&&... ctor_args)
|
||||
: _serverIdent(id), LoggerT(std::forward<LoggerCtorArgTs>(ctor_args)...)
|
||||
{
|
||||
if constexpr (traits::formattable<IdentT>) {
|
||||
logInfo("Create ADC generic network server with ID: {} (addr = {}, thread = {})", id, (void*)this,
|
||||
utils::AdcThisThreadId());
|
||||
} else {
|
||||
logInfo("Create ADC generic network server (addr = {}, thread = {})", (void*)this,
|
||||
utils::AdcThisThreadId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AdcGenericNetServer(const AdcGenericNetServer&) = delete;
|
||||
AdcGenericNetServer(AdcGenericNetServer&& other)
|
||||
: AdcPosixGenericDaemon(std::move(other)), AdcNetSessionManager(std::move(other))
|
||||
: AdcPosixGenericDaemon(std::move(other)), AdcNetSessionManager(std::move(other)), LoggerT(std::move(other))
|
||||
{
|
||||
logDebug("Move ADC server class: this = {}, target = {}", (void*)this, (void*)&other);
|
||||
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
@@ -336,11 +271,22 @@ public:
|
||||
_moveCtorFunc = std::move(other._moveCtorFunc);
|
||||
}
|
||||
|
||||
virtual ~AdcGenericNetServer() = default;
|
||||
virtual ~AdcGenericNetServer()
|
||||
{
|
||||
if constexpr (traits::formattable<IdentT>) {
|
||||
logInfo("Delete ADC generic network server with ID: {} (addr = {}, thread = {})", _serverIdent, (void*)this,
|
||||
utils::AdcThisThreadId());
|
||||
} else {
|
||||
logInfo("Delete ADC generic network server (addr = {}, thread = {})", (void*)this,
|
||||
utils::AdcThisThreadId());
|
||||
}
|
||||
};
|
||||
|
||||
AdcGenericNetServer& operator=(const AdcGenericNetServer&) = delete;
|
||||
AdcGenericNetServer& operator=(AdcGenericNetServer&& other)
|
||||
{
|
||||
logDebug("Assign-move ADC server class: this = {}, target = {}", (void*)this, (void*)&other);
|
||||
|
||||
if (this != &other) {
|
||||
AdcPosixGenericDaemon::operator=(std::move(other));
|
||||
AdcNetSessionManager::operator=(std::move(other));
|
||||
@@ -369,6 +315,8 @@ public:
|
||||
void start(SessionT::netsession_ident_t id, SessionT::netsession_ctx_t sess_ctx, AcceptorCtorArgTs&&... ctor_args)
|
||||
requires traits::adc_hashable_c<typename SessionT::netsession_ident_t>
|
||||
{
|
||||
logDebug("Call {}", __PRETTY_FUNCTION__);
|
||||
|
||||
if (!_isListening<SessionT>[this][id]) {
|
||||
auto acceptor = std::make_shared<typename SessionT::netservice_t::acceptor_t>(
|
||||
std::forward<AcceptorCtorArgTs>(ctor_args)...);
|
||||
@@ -380,6 +328,16 @@ public:
|
||||
_isListening<SessionT>[inst][id] = false;
|
||||
});
|
||||
|
||||
if constexpr (traits::formattable<typename SessionT::netsession_ident_t>) {
|
||||
logInfo(
|
||||
"Start listening for client connections at <{}> endpoint (session ID: {}, server addr = {}, thread "
|
||||
"= {})",
|
||||
acceptor->localEndpoint(), id, (void*)this, utils::AdcThisThreadId());
|
||||
} else {
|
||||
logInfo("Start listening for client connections at <{}> endpoint (server addr = {}, thread = {})",
|
||||
acceptor->localEndpoint(), (void*)this, utils::AdcThisThreadId());
|
||||
}
|
||||
|
||||
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||
}
|
||||
|
||||
@@ -413,6 +371,30 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// helper methods for logging
|
||||
template <traits::formattable... Ts>
|
||||
void logMessage(LoggerT::loglevel_t level, std::format_string<Ts...> fmt, Ts&&... args)
|
||||
{
|
||||
LoggerT::logMessage(level, std::format(fmt, std::forward<Ts>(args)...));
|
||||
}
|
||||
|
||||
template <traits::formattable... Ts>
|
||||
void logInfo(std::format_string<Ts...> fmt, Ts&&... args)
|
||||
{
|
||||
LoggerT::logInfo(std::format(fmt, std::forward<Ts>(args)...));
|
||||
}
|
||||
|
||||
template <traits::formattable... Ts>
|
||||
void logDebug(std::format_string<Ts...> fmt, Ts&&... args)
|
||||
{
|
||||
LoggerT::logDebug(std::format(fmt, std::forward<Ts>(args)...));
|
||||
}
|
||||
|
||||
template <traits::formattable... Ts>
|
||||
void logError(std::format_string<Ts...> fmt, Ts&&... args)
|
||||
{
|
||||
LoggerT::logError(std::format(fmt, std::forward<Ts>(args)...));
|
||||
}
|
||||
|
||||
protected:
|
||||
// template <interfaces::adc_netsession_c SessionT>
|
||||
@@ -433,24 +415,22 @@ protected:
|
||||
acceptor->asyncAccept([acceptor, id = std::move(id), sess_ctx = std::move(sess_ctx), this](
|
||||
auto ec, typename SessionT::netservice_t srv) mutable {
|
||||
if (!ec) {
|
||||
logInfo(
|
||||
"Client connection is succesfully accepted! Client endpoint: {} (server addr = {}, thread = {})",
|
||||
srv.remoteEndpoint(), (void*)this, utils::AdcThisThreadId());
|
||||
|
||||
auto sess = std::make_shared<SessionT>(id, std::move(srv), sess_ctx);
|
||||
startSession(sess);
|
||||
|
||||
_isListening<SessionT>[this][id] = true;
|
||||
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||
} else {
|
||||
// std::string str{"Cannot start accepting connection: "};
|
||||
// SessionT::netservice_t::formatError(ec, str);
|
||||
// errorMessage(str);
|
||||
|
||||
this->logError("Cannot start accepting connection: {}", SessionT::netservice_t::formattableError(ec));
|
||||
|
||||
_isListening<SessionT>[this][id] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// virtual void errorMessage(const std::string&) {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user