dncurrency/nano/lib/logger_mt.hpp
theohax 9bb89ab323
Improvements in const correctness and 'const' positioning (#3510)
* Improve const correctness and adhere to 'const' specifier positioning style

Co-authored-by: Mario Ortiz Manero <marioortizmanero@gmail.com>
2021-10-21 16:20:09 +03:00

139 lines
3.8 KiB
C++

#pragma once
#include <nano/lib/locks.hpp>
#include <nano/lib/utility.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/manipulators/to_log.hpp>
#include <array>
#include <chrono>
#include <mutex>
namespace nano
{
enum class severity_level
{
normal = 0,
error
};
}
// Attribute value tag type
struct severity_tag;
inline boost::log::formatting_ostream & operator<< (boost::log::formatting_ostream & strm, boost::log::to_log_manip<nano::severity_level, severity_tag> const & manip)
{
// Needs to match order in the severity_level enum
static std::array<char const *, 2> strings = {
"",
"Error: "
};
nano::severity_level level = manip.get ();
debug_assert (static_cast<int> (level) < strings.size ());
strm << strings[static_cast<int> (level)];
return strm;
}
namespace nano
{
// A wrapper around a boost logger object to allow minimum
// time spaced output to prevent logging happening too quickly.
class logger_mt
{
private:
void add_to_stream (boost::log::record_ostream & stream)
{
}
template <typename LogItem, typename... LogItems>
void add_to_stream (boost::log::record_ostream & stream, const LogItem & first_log_item, LogItems &&... remainder_log_items)
{
stream << first_log_item;
add_to_stream (stream, remainder_log_items...);
}
template <typename... LogItems>
void output (nano::severity_level severity_level, LogItems &&... log_items)
{
boost::log::record rec = boost_logger_mt.open_record (boost::log::keywords::severity = severity_level);
if (rec)
{
boost::log::record_ostream strm (rec);
add_to_stream (strm, std::forward<LogItems> (log_items)...);
strm.flush ();
boost_logger_mt.push_record (std::move (rec));
}
}
public:
logger_mt () = default;
/**
* @param min_log_delta_a The minimum time between successive output
*/
explicit logger_mt (std::chrono::milliseconds const & min_log_delta_a) :
min_log_delta (min_log_delta_a)
{
}
/*
* @param log_items A collection of objects with overloaded operator<< to be output to the log file
* @params severity_level The severity level that this log message should have.
*/
template <typename... LogItems>
void always_log (nano::severity_level severity_level, LogItems &&... log_items)
{
output (severity_level, std::forward<LogItems> (log_items)...);
}
/*
* @param log_items A collection of objects with overloaded operator<< to be output to the log file.
*/
template <typename... LogItems>
void always_log (LogItems &&... log_items)
{
always_log (nano::severity_level::normal, std::forward<LogItems> (log_items)...);
}
/*
* @param log_items Output to the log file if the last write was over min_log_delta time ago.
* @params severity_level The severity level that this log message should have.
* @return true if nothing was logged
*/
template <typename... LogItems>
bool try_log (nano::severity_level severity_level, LogItems &&... log_items)
{
auto error (true);
auto time_now = std::chrono::steady_clock::now ();
nano::unique_lock<nano::mutex> lk (last_log_time_mutex);
if (((time_now - last_log_time) > min_log_delta) || last_log_time == std::chrono::steady_clock::time_point{})
{
last_log_time = time_now;
lk.unlock ();
output (severity_level, std::forward<LogItems> (log_items)...);
error = false;
}
return error;
}
/*
* @param log_items Output to the log file if the last write was over min_log_delta time ago.
* @return true if nothing was logged
*/
template <typename... LogItems>
bool try_log (LogItems &&... log_items)
{
return try_log (nano::severity_level::normal, std::forward<LogItems> (log_items)...);
}
std::chrono::milliseconds min_log_delta{ 0 };
private:
nano::mutex last_log_time_mutex;
std::chrono::steady_clock::time_point last_log_time;
boost::log::sources::severity_logger_mt<severity_level> boost_logger_mt;
};
}