#pragma once #ifndef LOG_H_SPSC31OG #define LOG_H_SPSC31OG #ifdef RPCLIB_ENABLE_LOGGING #include "format.h" #include #include #include #include #include #include #include #include #include #ifdef _MSC_VER #include #endif namespace rpc { namespace detail { class logger { public: static logger &instance() { static logger inst; return inst; } template void trace(const char *channel, const char *file, const char *func, std::size_t line, const char *msg, Args... args) { (void)func; basic_log("TRACE", channel, RPCLIB_FMT::format("{} ({}:{})", RPCLIB_FMT::format(msg, args...), file, line)); } template void debug(const char *channel, const char *file, const char *func, std::size_t line, const char *msg, Args... args) { (void)func; basic_log("DEBUG", channel, RPCLIB_FMT::format("{} ({}:{})", RPCLIB_FMT::format(msg, args...), file, line)); } template void warn(const char *channel, const char *msg, Args... args) { basic_log("WARN", channel, RPCLIB_FMT::format(msg, args...)); } template void error(const char *channel, const char *msg, Args... args) { basic_log("ERROR", channel, RPCLIB_FMT::format(msg, args...)); } template void info(const char *channel, const char *msg, Args... args) { basic_log("INFO", channel, RPCLIB_FMT::format(msg, args...)); } private: logger() {} #ifdef _MSC_VER static std::string now() { std::stringstream ss; SYSTEMTIME t; GetSystemTime(&t); ss << RPCLIB_FMT::format("{}-{}-{} {}:{}:{}.{:03}", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); return ss.str(); } #else static std::string now() { std::stringstream ss; timespec now_t = {}; clock_gettime(CLOCK_REALTIME, &now_t); ss << std::put_time( std::localtime(reinterpret_cast(&now_t.tv_sec)), "%F %T") << RPCLIB_FMT::format( ".{:03}", round(static_cast(now_t.tv_nsec) / 1.0e6)); return ss.str(); } #endif void basic_log(const char *severity, const char *channel, std::string const &msg) { using RPCLIB_FMT::arg; std::lock_guard lock(mut_print_); RPCLIB_FMT::print("{time:16} {severity:6} {channel:12} {msg:40}\n", arg("severity", severity), arg("channel", channel), arg("time", now()), arg("msg", msg)); } private: std::mutex mut_print_; }; } /* detail */ } /* rpc */ #ifdef _MSC_VER #define RPCLIB_CREATE_LOG_CHANNEL(Name) \ static constexpr const char *rpc_channel_name = #Name; #elif defined(__GNUC__) #define RPCLIB_CREATE_LOG_CHANNEL(Name) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wunused-variable\"") \ static constexpr const char *rpc_channel_name = #Name; \ _Pragma("GCC diagnostic pop") #elif defined(__clang__) _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wunused-variable\"") \ static constexpr const char *rpc_channel_name = #Name; \ _Pragma("clang diagnostic pop") #endif RPCLIB_CREATE_LOG_CHANNEL(global) #define LOG_INFO(...) \ rpc::detail::logger::instance().info(rpc_channel_name, __VA_ARGS__) #define LOG_WARN(...) \ rpc::detail::logger::instance().warn(rpc_channel_name, __VA_ARGS__) #define LOG_ERROR(...) \ rpc::detail::logger::instance().error(rpc_channel_name, __VA_ARGS__) #define LOG_DEBUG(...) \ rpc::detail::logger::instance().debug(rpc_channel_name, __FILE__, \ __func__, __LINE__, __VA_ARGS__) #define LOG_TRACE(...) \ rpc::detail::logger::instance().trace(rpc_channel_name, __FILE__, \ __func__, __LINE__, __VA_ARGS__) #define LOG_EXPR(Level, Expr) LOG_##Level("`" #Expr "` = {}", Expr) #else #define LOG_INFO(...) #define LOG_WARN(...) #define LOG_ERROR(...) #define LOG_DEBUG(...) #define LOG_TRACE(...) #define LOG_EXPR(...) #define RPCLIB_CREATE_LOG_CHANNEL(...) #endif #endif /* end of include guard: LOG_H_SPSC31OG */