Kylin/Universal/BoostLog.inl
2024-09-15 23:39:23 +08:00

200 lines
6.3 KiB
C++

#ifndef BOOSTLOG_INL
#define BOOSTLOG_INL
#include "BoostLog.h"
#include "StreamFormat.h"
#include "boost/log/sources/basic_logger.hpp"
#include "boost/log/trivial.hpp"
#include "boost/scope_exit.hpp"
#include <chrono>
#include <iomanip>
template <typename Derived>
class LogPredicator {
public:
operator bool() const {
bool ret = m_status;
m_status = !m_status;
if (ret) {
ret = doOnceInterface();
if (!ret) m_status = true;
}
return ret;
}
inline bool doOnceInterface() const {
return static_cast<const Derived *>(this)->doOnce();
}
protected:
mutable bool m_status = true;
};
class NumberPredicator : public LogPredicator<NumberPredicator> {
public:
NumberPredicator(int limit) : m_limit(limit) {
}
inline bool doOnce() const {
return (m_current++ % m_limit) == 0;
}
private:
int m_limit;
mutable int m_current{0};
};
class CountPredicator : public LogPredicator<CountPredicator> {
public:
CountPredicator(int limit) : m_limit(limit) {
}
inline bool doOnce() const {
return m_current++ < m_limit;
}
private:
int m_limit;
mutable int m_current{0};
};
class TimePredicator : public LogPredicator<TimePredicator> {
public:
TimePredicator(int milliseconds) : m_limit(std::chrono::milliseconds(milliseconds)) {
}
inline bool doOnce() const {
auto now = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_current);
bool ret = duration >= m_limit;
if (ret) m_current = now;
return ret;
}
private:
std::chrono::milliseconds m_limit;
mutable decltype(std::chrono::system_clock::now()) m_current{std::chrono::system_clock::now()};
};
template <typename BaseT>
CategoryTaggerFeature<BaseT>::CategoryTaggerFeature(const CategoryTaggerFeature &obj) : BaseT(static_cast<const BaseT &>(obj)) {
}
template <typename BaseT>
template <typename ArgsT>
CategoryTaggerFeature<BaseT>::CategoryTaggerFeature(const ArgsT &args) : BaseT(args) {
}
template <typename BaseT>
template <typename ArgsT>
boost::log::record CategoryTaggerFeature<BaseT>::open_record_unlocked(const ArgsT &args) {
std::string tag_value = args[AmassKeywords::CategoryTag | std::string()];
boost::log::attribute_set &attrs = BaseT::attributes();
boost::log::attribute_set::iterator tag = attrs.end();
if (!tag_value.empty()) {
// Add the tag as a new attribute
std::pair<boost::log::attribute_set::iterator, bool> res =
BaseT::add_attribute_unlocked("Category", boost::log::attributes::constant<std::string>(tag_value));
if (res.second) tag = res.first;
}
BOOST_SCOPE_EXIT_TPL((&tag)(&attrs)) {
if (tag != attrs.end()) attrs.erase(tag);
}
BOOST_SCOPE_EXIT_END
return BaseT::open_record_unlocked(args);
}
template <typename BaseT>
FilenameTaggerFeature<BaseT>::FilenameTaggerFeature(const FilenameTaggerFeature &obj) : BaseT(static_cast<const BaseT &>(obj)) {
}
template <typename BaseT>
template <typename ArgsT>
FilenameTaggerFeature<BaseT>::FilenameTaggerFeature(const ArgsT &args) : BaseT(args) {
}
template <typename BaseT>
template <typename ArgsT>
boost::log::record FilenameTaggerFeature<BaseT>::open_record_unlocked(const ArgsT &args) {
std::string tag_value = args[AmassKeywords::FilenameTag | std::string()];
boost::log::attribute_set &attrs = BaseT::attributes();
boost::log::attribute_set::iterator tag = attrs.end();
if (!tag_value.empty()) {
// Add the tag as a new attribute
std::pair<boost::log::attribute_set::iterator, bool> res =
BaseT::add_attribute_unlocked("Filename", boost::log::attributes::constant<std::string>(tag_value));
if (res.second) tag = res.first;
}
BOOST_SCOPE_EXIT_TPL((&tag)(&attrs)) {
if (tag != attrs.end()) attrs.erase(tag);
}
BOOST_SCOPE_EXIT_END
return BaseT::open_record_unlocked(args);
}
template <typename BaseT>
FunctionTaggerFeature<BaseT>::FunctionTaggerFeature(const FunctionTaggerFeature &obj) : BaseT(static_cast<const BaseT &>(obj)) {
}
template <typename BaseT>
template <typename ArgsT>
FunctionTaggerFeature<BaseT>::FunctionTaggerFeature(const ArgsT &args) : BaseT(args) {
}
template <typename BaseT>
template <typename ArgsT>
boost::log::record FunctionTaggerFeature<BaseT>::open_record_unlocked(const ArgsT &args) {
std::string tag_value = args[AmassKeywords::FunctionTag | std::string()];
boost::log::attribute_set &attrs = BaseT::attributes();
boost::log::attribute_set::iterator tag = attrs.end();
if (!tag_value.empty()) {
// Add the tag as a new attribute
std::pair<boost::log::attribute_set::iterator, bool> res =
BaseT::add_attribute_unlocked("Function", boost::log::attributes::constant<std::string>(tag_value));
if (res.second) tag = res.first;
}
BOOST_SCOPE_EXIT_TPL((&tag)(&attrs)) {
if (tag != attrs.end()) attrs.erase(tag);
}
BOOST_SCOPE_EXIT_END
return BaseT::open_record_unlocked(args);
}
template <typename BaseT>
template <typename ArgsT>
LineTaggerFeature<BaseT>::LineTaggerFeature(const ArgsT &args) : BaseT(args) {
}
template <typename BaseT>
LineTaggerFeature<BaseT>::LineTaggerFeature(const LineTaggerFeature &obj) : BaseT(static_cast<const BaseT &>(obj)) {
}
template <typename BaseT>
template <typename ArgsT>
boost::log::record LineTaggerFeature<BaseT>::open_record_unlocked(const ArgsT &args) {
size_t tag_value = args[AmassKeywords::LineTag | size_t()];
boost::log::attribute_set &attrs = BaseT::attributes();
boost::log::attribute_set::iterator tag = attrs.end();
// Add the tag as a new attribute
std::pair<boost::log::attribute_set::iterator, bool> res =
BaseT::add_attribute_unlocked("Line", boost::log::attributes::constant<size_t>(tag_value));
if (res.second) tag = res.first;
BOOST_SCOPE_EXIT_TPL((&tag)(&attrs)) {
if (tag != attrs.end()) attrs.erase(tag);
}
BOOST_SCOPE_EXIT_END
return BaseT::open_record_unlocked(args);
}
namespace std {
ostream &operator<<(ostream &os, const map<int, int> &m);
}
#endif // BOOSTLOG_INL