23 static constexpr const char* LevelNames[] = {
24 "trace",
"debug",
"info",
"fail",
"fatal"};
26 static constexpr const char* to_string(
LoggerLevel l)
28 return LevelNames[
static_cast<int>(l)];
31 static constexpr long int ns_per_s = 1'000'000'000;
33 static constexpr auto preamble_length = 45u;
35#ifdef CCF_RAFT_TRACING
36 static size_t logical_clock = 0;
49 std::ostringstream
ss;
54 std::string_view tag_,
55 std::string_view file_name_,
56 size_t line_number_) :
83 static std::string get_timestamp(
const std::tm& tm, const ::timespec& ts)
85#ifdef CCF_RAFT_TRACING
86 return std::to_string(logical_clock++);
89 constexpr size_t nano_per_micro = 1000;
91 "{:%Y-%m-%dT%H:%M:%S}.{:0>6}Z", tm, ts.tv_nsec / nano_per_micro);
101 virtual void emit(
const std::string& s)
103 std::cout.write(s.c_str(), s.size());
116 ::timespec host_ts{};
117 if (::timespec_get(&host_ts, TIME_UTC) == 0)
119 throw std::runtime_error(
"timespec_get failed");
122 ::gmtime_r(&host_ts.tv_sec, &host_tm);
124#ifdef CCF_RAFT_TRACING
125 auto escaped_msg = ll.
msg;
126 if (!nlohmann::json::accept(escaped_msg))
131 escaped_msg = nlohmann::json(ll.
msg).dump();
134 const auto escaped_msg = nlohmann::json(ll.
msg).dump();
139 "{{\"h_ts\":\"{}\",\"thread_id\":\"{}\",\"level\":\"{}\",\"tag\":\"{}"
140 "\",\"file\":\"{}\",\"number\":\"{}\",\"msg\":{}}}\n",
141 get_timestamp(host_tm, host_ts),
153 static std::string format_to_text(
const LogLine& ll)
156 ::timespec host_ts{};
157 if (::timespec_get(&host_ts, TIME_UTC) == 0)
159 throw std::runtime_error(
"timespec_get failed");
162 ::gmtime_r(&host_ts.tv_sec, &host_tm);
164 auto file_line = fmt::format(
"{}:{} ", ll.file_name, ll.line_number);
165 auto* file_line_data = file_line.data();
169 auto preamble = fmt::format(
171 to_string(ll.log_level),
172 (ll.tag.empty() ?
"" : fmt::format(
"[{}]", ll.tag)))
173 .substr(0, preamble_length);
174 const auto max_file_line_len = preamble_length - preamble.size();
176 const auto len = file_line.size();
177 if (len > max_file_line_len)
179 file_line_data += len - max_file_line_len;
182 preamble += file_line_data;
185 "{} {:<3} {:<45}| {}\n",
186 get_timestamp(host_tm, host_ts),
197 emit(format_to_text(ll));
204 static std::vector<std::unique_ptr<AbstractLogger>>&
loggers()
206 return get_loggers();
211 get_loggers().emplace_back(std::make_unique<TextConsoleLogger>());
216 get_loggers().emplace_back(std::make_unique<JsonConsoleLogger>());
221 get_loggers().clear();
238 static std::vector<std::unique_ptr<AbstractLogger>>& get_loggers()
240 static std::vector<std::unique_ptr<AbstractLogger>> the_loggers;
260#pragma clang diagnostic push
261#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
267#if defined(__clang__) && __clang_major__ >= 12
268# define CCF_FMT_STRING(s) (s)
270# define CCF_FMT_STRING(s) FMT_STRING(s)
280#define CCF_LOG_OUT(LVL, TAG) \
281 ccf::logger::config::ok(ccf::LoggerLevel::LVL) && \
282 ccf::logger::Out() == \
283 ccf::logger::LogLine(ccf::LoggerLevel::LVL, TAG, __FILE__, __LINE__)
288#define CCF_LOG_FMT_2(s, ...) fmt::format(CCF_FMT_STRING(s), ##__VA_ARGS__)
289#define CCF_LOG_FMT(LVL, TAG) CCF_LOG_OUT(LVL, TAG) << CCF_LOG_FMT_2
291#define CCF_APP_TRACE CCF_LOG_FMT(TRACE, "app")
292#define CCF_APP_DEBUG CCF_LOG_FMT(DEBUG, "app")
293#define CCF_APP_INFO CCF_LOG_FMT(INFO, "app")
294#define CCF_APP_FAIL CCF_LOG_FMT(FAIL, "app")
295#define CCF_APP_FATAL CCF_LOG_FMT(FATAL, "app")
297#pragma clang diagnostic pop
void write(const LogLine &ll) override
Definition logger.h:195