1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
#pragma once
#ifndef LOG_H_SPSC31OG
#define LOG_H_SPSC31OG
#ifdef RPCLIB_ENABLE_LOGGING
#include "format.h"
#include <chrono>
#include <cstdlib>
#include <iomanip>
#include <mutex>
#include <sstream>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#ifdef _MSC_VER
#include <Windows.h>
#endif
namespace rpc {
namespace detail {
class logger {
public:
static logger &instance() {
static logger inst;
return inst;
}
template <typename... Args>
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 <typename... Args>
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 <typename... Args>
void warn(const char *channel, const char *msg, Args... args) {
basic_log("WARN", channel, RPCLIB_FMT::format(msg, args...));
}
template <typename... Args>
void error(const char *channel, const char *msg, Args... args) {
basic_log("ERROR", channel, RPCLIB_FMT::format(msg, args...));
}
template <typename... Args>
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<time_t *>(&now_t.tv_sec)),
"%F %T")
<< RPCLIB_FMT::format(
".{:03}", round(static_cast<double>(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<std::mutex> 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 */
|