Kylin/Universal/BoostLog.h
2024-09-04 12:28:49 +08:00

229 lines
7.8 KiB
C++

#ifndef BOOSTLOG_H
#define BOOSTLOG_H
#include <boost/log/common.hpp>
#include <boost/log/core.hpp>
#include <boost/log/detail/light_rw_mutex.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/thread.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
/* what i expected.
[2020-09-08 17:12:35.229152] [0x00007fa07fc94800] [info] Hello world!
[2020-09-08 17:12:35.229204] [0x00007fa07fc94800] [info] server ip: 127.0.0.1,port: 8080
[2020-09-08 17:12:35.229211] [0x00007fa07fc94800] [warning] server ip: 127.0.0.1,port: 8080
[2020-09-08 17:12:35.230961] [0x00007fa07fc94800] [info] server start successful .
*/
// clang-format off
#define LOG_IF(lvl,predic) \
if(predic) LOG(lvl)
#define LOG_IF_EVERY_N(lvl,predic,n) \
if(predic) for(static NumberPredicator pred(n);(!!pred);) \
LOG(lvl)
#define LOG_EVERY_N(lvl,n) \
LOG_IF_EVERY_N(lvl,true,n)
#define LOG_IF_FIRST_N(lvl,predic,n) \
if(predic) for(static CountPredicator pred(n);(!!pred);) \
LOG(lvl)
#define LOG_FIRST_N(lvl,n) \
LOG_IF_FIRST_N(lvl,true,n)
#define LOG_IF_EVERY_T(lvl,predic,n) \
if(predic) for(static TimePredicator pred(n);(!!pred);) \
LOG(lvl)
#define LOG_EVERY_T(lvl,n) \
LOG_IF_EVERY_T(lvl,true,n)
// clang-format on
#ifndef LOG_FILTER_LEVEL
#define LOG_FILTER_LEVEL (boost::log::trivial::info)
#endif
namespace boost {
namespace log {
/**
* @brief
*
* @param filename log file path
* @param target path for rotated log files
* @param filter
*/
void initialize(const std::string &filename = "logs/app", const std::string &target = "logs",
trivial::severity_level filter = static_cast<trivial::severity_level>(LOG_FILTER_LEVEL));
void defaultFormatter(boost::log::record_view const &record, boost::log::formatting_ostream &ostream);
void removeConsoleLog();
} // namespace log
} // namespace boost
namespace AmassKeywords {
BOOST_PARAMETER_KEYWORD(FilenameNS, FilenameTag)
BOOST_PARAMETER_KEYWORD(FunctionNS, FunctionTag)
BOOST_PARAMETER_KEYWORD(LineNS, LineTag)
BOOST_PARAMETER_KEYWORD(CategoryNS, CategoryTag)
BOOST_LOG_ATTRIBUTE_KEYWORD(filename, "Filename", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(function, "Function", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(line, "Line", size_t)
BOOST_LOG_ATTRIBUTE_KEYWORD(category, "Category", std::string)
constexpr const char *pathEnd(const char *path) {
return *path ? pathEnd(path + 1) : path;
}
constexpr bool hasSlant(const char *path) {
return (*path == '\\' || *path == '/') ? true : (*path ? hasSlant(path + 1) : false);
}
constexpr const char *rightSlant(const char *path) {
return (*path == '\\' || *path == '/') ? (path + 1) : rightSlant(path - 1);
}
constexpr const char *fileName(const char *path) {
return hasSlant(path) ? rightSlant(pathEnd(path)) : path;
}
} // namespace AmassKeywords
template <typename BaseT>
class CategoryTaggerFeature : public BaseT {
public:
typedef typename BaseT::char_type char_type;
typedef typename BaseT::threading_model threading_model;
CategoryTaggerFeature() = default;
CategoryTaggerFeature(const CategoryTaggerFeature &obj);
template <typename ArgsT>
CategoryTaggerFeature(const ArgsT &args);
typedef typename boost::log::strictest_lock<boost::lock_guard<threading_model>, typename BaseT::open_record_lock,
typename BaseT::add_attribute_lock,
typename BaseT::remove_attribute_lock>::type open_record_lock;
protected:
template <typename ArgsT>
boost::log::record open_record_unlocked(const ArgsT &args);
};
struct CategoryTagger : public boost::mpl::quote1<CategoryTaggerFeature> {};
template <typename BaseT>
class FilenameTaggerFeature : public BaseT {
public:
typedef typename BaseT::char_type char_type;
typedef typename BaseT::threading_model threading_model;
FilenameTaggerFeature() = default;
FilenameTaggerFeature(const FilenameTaggerFeature &obj);
template <typename ArgsT>
FilenameTaggerFeature(const ArgsT &args);
typedef typename boost::log::strictest_lock<boost::lock_guard<threading_model>, typename BaseT::open_record_lock,
typename BaseT::add_attribute_lock,
typename BaseT::remove_attribute_lock>::type open_record_lock;
protected:
template <typename ArgsT>
boost::log::record open_record_unlocked(const ArgsT &args);
};
struct FilenameTagger : public boost::mpl::quote1<FilenameTaggerFeature> {};
template <typename BaseT>
class FunctionTaggerFeature : public BaseT {
public:
typedef typename BaseT::char_type char_type;
typedef typename BaseT::threading_model threading_model;
FunctionTaggerFeature() = default;
FunctionTaggerFeature(const FunctionTaggerFeature &obj);
template <typename ArgsT>
FunctionTaggerFeature(const ArgsT &args);
typedef typename boost::log::strictest_lock<boost::lock_guard<threading_model>, typename BaseT::open_record_lock,
typename BaseT::add_attribute_lock,
typename BaseT::remove_attribute_lock>::type open_record_lock;
protected:
template <typename ArgsT>
boost::log::record open_record_unlocked(const ArgsT &args);
};
struct FunctionTagger : public boost::mpl::quote1<FunctionTaggerFeature> {};
template <typename BaseT>
class LineTaggerFeature : public BaseT {
public:
typedef typename BaseT::char_type char_type;
typedef typename BaseT::threading_model threading_model;
LineTaggerFeature() = default;
LineTaggerFeature(const LineTaggerFeature &obj);
template <typename ArgsT>
LineTaggerFeature(const ArgsT &args);
typedef typename boost::log::strictest_lock<boost::lock_guard<threading_model>, typename BaseT::open_record_lock,
typename BaseT::add_attribute_lock,
typename BaseT::remove_attribute_lock>::type open_record_lock;
protected:
template <typename ArgsT>
boost::log::record open_record_unlocked(const ArgsT &args);
};
struct LineTagger : public boost::mpl::quote1<LineTaggerFeature> {};
template <typename LevelT = int>
class LocationLogger
: public boost::log::sources::basic_composite_logger<
char, LocationLogger<LevelT>, boost::log::sources::multi_thread_model<boost::log::aux::light_rw_mutex>,
boost::log::sources::features<boost::log::sources::severity<LevelT>, FilenameTagger, FunctionTagger,
LineTagger, CategoryTagger>> {
typedef typename LocationLogger::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(LocationLogger)
};
BOOST_LOG_GLOBAL_LOGGER(location_logger, LocationLogger<boost::log::trivial::severity_level>)
// clang-format off
#define LOG( lvl) \
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
(AmassKeywords::FunctionTag = __func__) \
(AmassKeywords::LineTag = __LINE__))
#define LOG_CAT( lvl, cat) \
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
(AmassKeywords::FunctionTag = __func__) \
(AmassKeywords::LineTag = __LINE__) \
(AmassKeywords::CategoryTag = #cat))
#define LOG_FORMAT(lvl,...)\
auto xxx_size = snprintf(nullptr,0,__VA_ARGS__);\
std::string xxx_buffer(xxx_size,'\0');\
snprintf(xxx_buffer.data(),xxx_buffer.size(),__VA_ARGS__);\
LOG(lvl)<<std::move(xxx_buffer);
// clang-format on
#include "BoostLog.inl"
#endif // BOOSTLOG_H