229 lines
7.8 KiB
C++
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
|