Back to C++20 standard!

Logging is worked (AdcOstreamLogger and AdcSPDLOGLogger classes)
This commit is contained in:
2024-11-14 18:33:07 +03:00
parent 05e0055193
commit 78a9e53d18
9 changed files with 334 additions and 196 deletions

View File

@@ -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&) {};
};