#ifndef BOOSTLOG_H #define BOOSTLOG_H #include #include #include #include #include #include #include #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(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 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 CategoryTaggerFeature(const ArgsT &args); typedef typename boost::log::strictest_lock, typename BaseT::open_record_lock, typename BaseT::add_attribute_lock, typename BaseT::remove_attribute_lock>::type open_record_lock; protected: template boost::log::record open_record_unlocked(const ArgsT &args); }; struct CategoryTagger : public boost::mpl::quote1 {}; template 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 FilenameTaggerFeature(const ArgsT &args); typedef typename boost::log::strictest_lock, typename BaseT::open_record_lock, typename BaseT::add_attribute_lock, typename BaseT::remove_attribute_lock>::type open_record_lock; protected: template boost::log::record open_record_unlocked(const ArgsT &args); }; struct FilenameTagger : public boost::mpl::quote1 {}; template 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 FunctionTaggerFeature(const ArgsT &args); typedef typename boost::log::strictest_lock, typename BaseT::open_record_lock, typename BaseT::add_attribute_lock, typename BaseT::remove_attribute_lock>::type open_record_lock; protected: template boost::log::record open_record_unlocked(const ArgsT &args); }; struct FunctionTagger : public boost::mpl::quote1 {}; template 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 LineTaggerFeature(const ArgsT &args); typedef typename boost::log::strictest_lock, typename BaseT::open_record_lock, typename BaseT::add_attribute_lock, typename BaseT::remove_attribute_lock>::type open_record_lock; protected: template boost::log::record open_record_unlocked(const ArgsT &args); }; struct LineTagger : public boost::mpl::quote1 {}; template class LocationLogger : public boost::log::sources::basic_composite_logger< char, LocationLogger, boost::log::sources::multi_thread_model, boost::log::sources::features, 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) // 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)<