1 #pragma once 2 3 #ifndef LOG_H_SPSC31OG 4 #define LOG_H_SPSC31OG 5 6 #ifdef RPCLIB_ENABLE_LOGGING 7 8 #include "format.h" 9 #include <chrono> 10 #include <cstdlib> 11 #include <iomanip> 12 #include <mutex> 13 #include <sstream> 14 15 #include <inttypes.h> 16 #include <math.h> 17 #include <stdio.h> 18 #include <time.h> 19 20 #ifdef _MSC_VER 21 #include <Windows.h> 22 #endif 23 24 namespace rpc { 25 namespace detail { 26 class logger { 27 public: instance()28 static logger &instance() { 29 static logger inst; 30 return inst; 31 } 32 33 template <typename... Args> trace(const char * channel,const char * file,const char * func,std::size_t line,const char * msg,Args...args)34 void trace(const char *channel, const char *file, const char *func, 35 std::size_t line, const char *msg, Args... args) { 36 (void)func; 37 basic_log("TRACE", channel, 38 RPCLIB_FMT::format("{} ({}:{})", 39 RPCLIB_FMT::format(msg, args...), file, 40 line)); 41 } 42 43 template <typename... Args> debug(const char * channel,const char * file,const char * func,std::size_t line,const char * msg,Args...args)44 void debug(const char *channel, const char *file, const char *func, 45 std::size_t line, const char *msg, Args... args) { 46 (void)func; 47 basic_log("DEBUG", channel, 48 RPCLIB_FMT::format("{} ({}:{})", 49 RPCLIB_FMT::format(msg, args...), file, 50 line)); 51 } 52 53 template <typename... Args> warn(const char * channel,const char * msg,Args...args)54 void warn(const char *channel, const char *msg, Args... args) { 55 basic_log("WARN", channel, RPCLIB_FMT::format(msg, args...)); 56 } 57 58 template <typename... Args> error(const char * channel,const char * msg,Args...args)59 void error(const char *channel, const char *msg, Args... args) { 60 basic_log("ERROR", channel, RPCLIB_FMT::format(msg, args...)); 61 } 62 63 template <typename... Args> info(const char * channel,const char * msg,Args...args)64 void info(const char *channel, const char *msg, Args... args) { 65 basic_log("INFO", channel, RPCLIB_FMT::format(msg, args...)); 66 } 67 68 private: logger()69 logger() {} 70 71 #ifdef _MSC_VER now()72 static std::string now() { 73 std::stringstream ss; 74 SYSTEMTIME t; 75 GetSystemTime(&t); 76 ss << RPCLIB_FMT::format("{}-{}-{} {}:{}:{}.{:03}", t.wYear, t.wMonth, 77 t.wDay, t.wHour, t.wMinute, t.wSecond, 78 t.wMilliseconds); 79 return ss.str(); 80 } 81 #else now()82 static std::string now() { 83 std::stringstream ss; 84 timespec now_t = {}; 85 clock_gettime(CLOCK_REALTIME, &now_t); 86 ss << std::put_time( 87 std::localtime(reinterpret_cast<time_t *>(&now_t.tv_sec)), 88 "%F %T") 89 << RPCLIB_FMT::format( 90 ".{:03}", round(static_cast<double>(now_t.tv_nsec) / 1.0e6)); 91 return ss.str(); 92 } 93 #endif 94 basic_log(const char * severity,const char * channel,std::string const & msg)95 void basic_log(const char *severity, const char *channel, 96 std::string const &msg) { 97 using RPCLIB_FMT::arg; 98 std::lock_guard<std::mutex> lock(mut_print_); 99 RPCLIB_FMT::print("{time:16} {severity:6} {channel:12} {msg:40}\n", 100 arg("severity", severity), arg("channel", channel), 101 arg("time", now()), arg("msg", msg)); 102 } 103 104 private: 105 std::mutex mut_print_; 106 }; 107 } /* detail */ 108 } /* rpc */ 109 110 #ifdef _MSC_VER 111 #define RPCLIB_CREATE_LOG_CHANNEL(Name) \ 112 static constexpr const char *rpc_channel_name = #Name; 113 #elif defined(__GNUC__) 114 #define RPCLIB_CREATE_LOG_CHANNEL(Name) \ 115 _Pragma("GCC diagnostic push") \ 116 _Pragma("GCC diagnostic ignored \"-Wunused-variable\"") \ 117 static constexpr const char *rpc_channel_name = #Name; \ 118 _Pragma("GCC diagnostic pop") 119 #elif defined(__clang__) 120 _Pragma("clang diagnostic push") \ 121 _Pragma("clang diagnostic ignored \"-Wunused-variable\"") \ 122 static constexpr const char *rpc_channel_name = #Name; \ 123 _Pragma("clang diagnostic pop") 124 #endif 125 126 RPCLIB_CREATE_LOG_CHANNEL(global) 127 128 #define LOG_INFO(...) \ 129 rpc::detail::logger::instance().info(rpc_channel_name, __VA_ARGS__) 130 131 #define LOG_WARN(...) \ 132 rpc::detail::logger::instance().warn(rpc_channel_name, __VA_ARGS__) 133 134 #define LOG_ERROR(...) \ 135 rpc::detail::logger::instance().error(rpc_channel_name, __VA_ARGS__) 136 137 #define LOG_DEBUG(...) \ 138 rpc::detail::logger::instance().debug(rpc_channel_name, __FILE__, \ 139 __func__, __LINE__, __VA_ARGS__) 140 141 #define LOG_TRACE(...) \ 142 rpc::detail::logger::instance().trace(rpc_channel_name, __FILE__, \ 143 __func__, __LINE__, __VA_ARGS__) 144 145 #define LOG_EXPR(Level, Expr) LOG_##Level("`" #Expr "` = {}", Expr) 146 147 #else 148 149 #define LOG_INFO(...) 150 #define LOG_WARN(...) 151 #define LOG_ERROR(...) 152 #define LOG_DEBUG(...) 153 #define LOG_TRACE(...) 154 #define LOG_EXPR(...) 155 #define RPCLIB_CREATE_LOG_CHANNEL(...) 156 157 #endif 158 159 #endif /* end of include guard: LOG_H_SPSC31OG */ 160