trantor
Non-blocking I/O cross-platform TCP network library, using C++14
Loading...
Searching...
No Matches
Logger.h
Go to the documentation of this file.
1
14
15#pragma once
16
18#include <trantor/utils/Date.h>
20#include <trantor/exports.h>
21#include <cstring>
22#include <functional>
23#include <iostream>
24#include <vector>
25namespace spdlog
26{
27class logger;
28}
29#include <memory>
30
31#define TRANTOR_IF_(cond) for (int _r = 0; _r == 0 && (cond); _r = 1)
32
33namespace trantor
34{
39class TRANTOR_EXPORT Logger : public NonCopyable
40{
41 public:
42 enum LogLevel
43 {
44 kTrace = 0,
45 kDebug,
46 kInfo,
47 kWarn,
48 kError,
49 kFatal,
50 kNumberOfLogLevels
51 };
52
57 class SourceFile
58 {
59 public:
60 template <int N>
61 inline SourceFile(const char (&arr)[N]) : data_(arr), size_(N - 1)
62 {
63 // std::cout<<data_<<std::endl;
64#ifndef _MSC_VER
65 const char *slash = strrchr(data_, '/'); // builtin function
66#else
67 const char *slash = strrchr(data_, '\\');
68#endif
69 if (slash)
70 {
71 data_ = slash + 1;
72 size_ -= static_cast<int>(data_ - arr);
73 }
74 }
75
76 explicit SourceFile(const char *filename = nullptr) : data_(filename)
77 {
78 if (!filename)
79 {
80 size_ = 0;
81 return;
82 }
83#ifndef _MSC_VER
84 const char *slash = strrchr(filename, '/');
85#else
86 const char *slash = strrchr(filename, '\\');
87#endif
88 if (slash)
89 {
90 data_ = slash + 1;
91 }
92 size_ = static_cast<int>(strlen(data_));
93 }
94
95 const char *data_;
96 int size_;
97 };
98 Logger(SourceFile file, int line);
99 Logger(SourceFile file, int line, LogLevel level);
100 Logger(SourceFile file, int line, bool isSysErr);
101 Logger(SourceFile file, int line, LogLevel level, const char *func);
102
103 // LOG_COMPACT only <time><ThreadID><Level>
104 Logger();
105 Logger(LogLevel level);
106 Logger(bool isSysErr);
107
108 ~Logger();
109 Logger &setIndex(int index)
110 {
111 index_ = index;
112 return *this;
113 }
114 LogStream &stream();
115
124 static void setOutputFunction(
125 std::function<void(const char *msg, const uint64_t len)> outputFunc,
126 std::function<void()> flushFunc,
127 int index = -1)
128 {
129 if (index < 0)
130 {
131 outputFunc_() = outputFunc;
132 flushFunc_() = flushFunc;
133 }
134 else
135 {
136 outputFunc_(index) = outputFunc;
137 flushFunc_(index) = flushFunc;
138 }
139 }
140
146 static void setLogLevel(LogLevel level)
147 {
148 logLevel_() = level;
149 }
150
156 static LogLevel logLevel()
157 {
158 return logLevel_();
159 }
160
164 static bool displayLocalTime()
165 {
166 return displayLocalTime_();
167 }
168
172 static void setDisplayLocalTime(bool showLocalTime)
173 {
174 displayLocalTime_() = showLocalTime;
175 }
176
183 static bool hasSpdLogSupport();
192 static void enableSpdLog(int index,
193 std::shared_ptr<spdlog::logger> logger = {});
201 inline static void enableSpdLog(std::shared_ptr<spdlog::logger> logger = {})
202 {
203 enableSpdLog(-1, logger);
204 }
205
213 static void disableSpdLog(int index);
220 static void disableSpdLog()
221 {
222 disableSpdLog(-1);
223 }
224
229 static std::shared_ptr<spdlog::logger> getSpdLogger(int index = -1);
264 static std::shared_ptr<spdlog::logger> getDefaultSpdLogger(int index);
265
266 protected:
267 static void defaultOutputFunction(const char *msg, const uint64_t len)
268 {
269 fwrite(msg, 1, static_cast<size_t>(len), stdout);
270 }
271 static void defaultFlushFunction()
272 {
273 fflush(stdout);
274 }
275 void formatTime();
276 static bool &displayLocalTime_()
277 {
278 static bool showLocalTime = false;
279 return showLocalTime;
280 }
281
282 static LogLevel &logLevel_()
283 {
284#ifdef RELEASE
285 static LogLevel logLevel = LogLevel::kInfo;
286#else
287 static LogLevel logLevel = LogLevel::kDebug;
288#endif
289 return logLevel;
290 }
291 static std::function<void(const char *msg, const uint64_t len)> &
292 outputFunc_()
293 {
294 static std::function<void(const char *msg, const uint64_t len)>
295 outputFunc = Logger::defaultOutputFunction;
296 return outputFunc;
297 }
298 static std::function<void()> &flushFunc_()
299 {
300 static std::function<void()> flushFunc = Logger::defaultFlushFunction;
301 return flushFunc;
302 }
303 static std::function<void(const char *msg, const uint64_t len)> &
304 outputFunc_(size_t index)
305 {
306 static std::vector<
307 std::function<void(const char *msg, const uint64_t len)>>
308 outputFuncs;
309 if (index < outputFuncs.size())
310 {
311 return outputFuncs[index];
312 }
313 while (index >= outputFuncs.size())
314 {
315 outputFuncs.emplace_back(outputFunc_());
316 }
317 return outputFuncs[index];
318 }
319 static std::function<void()> &flushFunc_(size_t index)
320 {
321 static std::vector<std::function<void()>> flushFuncs;
322 if (index < flushFuncs.size())
323 {
324 return flushFuncs[index];
325 }
326 while (index >= flushFuncs.size())
327 {
328 flushFuncs.emplace_back(flushFunc_());
329 }
330 return flushFuncs[index];
331 }
332 friend class RawLogger;
333 LogStream logStream_;
334 Date date_{Date::now()};
335 SourceFile sourceFile_;
336 int fileLine_;
337 LogLevel level_;
338 int index_{-1};
339 const char *func_{nullptr};
340 std::size_t spdLogMessageOffset_{0};
341};
342class TRANTOR_EXPORT RawLogger : public NonCopyable
343{
344 public:
345 ~RawLogger();
346 RawLogger &setIndex(int index)
347 {
348 index_ = index;
349 return *this;
350 }
351 LogStream &stream()
352 {
353 return logStream_;
354 }
355
356 private:
357 LogStream logStream_;
358 int index_{-1};
359};
360#ifdef NDEBUG
361#define LOG_TRACE \
362 TRANTOR_IF_(0) \
363 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
364 .stream()
365#else
366#define LOG_TRACE \
367 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
368 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
369 .stream()
370#define LOG_TRACE_TO(index) \
371 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
372 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
373 .setIndex(index) \
374 .stream()
375
376#endif
377
378#define LOG_DEBUG \
379 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
380 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
381 .stream()
382#define LOG_DEBUG_TO(index) \
383 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
384 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
385 .setIndex(index) \
386 .stream()
387#define LOG_INFO \
388 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
389 trantor::Logger(__FILE__, __LINE__).stream()
390#define LOG_INFO_TO(index) \
391 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
392 trantor::Logger(__FILE__, __LINE__).setIndex(index).stream()
393#define LOG_WARN \
394 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
395#define LOG_WARN_TO(index) \
396 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn) \
397 .setIndex(index) \
398 .stream()
399#define LOG_ERROR \
400 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
401#define LOG_ERROR_TO(index) \
402 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError) \
403 .setIndex(index) \
404 .stream()
405#define LOG_FATAL \
406 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
407#define LOG_FATAL_TO(index) \
408 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal) \
409 .setIndex(index) \
410 .stream()
411#define LOG_SYSERR trantor::Logger(__FILE__, __LINE__, true).stream()
412#define LOG_SYSERR_TO(index) \
413 trantor::Logger(__FILE__, __LINE__, true).setIndex(index).stream()
414
415// LOG_COMPACT_... begin block
416#define LOG_COMPACT_DEBUG \
417 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
418 trantor::Logger(trantor::Logger::kDebug).stream()
419#define LOG_COMPACT_DEBUG_TO(index) \
420 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
421 trantor::Logger(trantor::Logger::kDebug).setIndex(index).stream()
422#define LOG_COMPACT_INFO \
423 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
424 trantor::Logger().stream()
425#define LOG_COMPACT_INFO_TO(index) \
426 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
427 trantor::Logger().setIndex(index).stream()
428#define LOG_COMPACT_WARN trantor::Logger(trantor::Logger::kWarn).stream()
429#define LOG_COMPACT_WARN_TO(index) \
430 trantor::Logger(trantor::Logger::kWarn).setIndex(index).stream()
431#define LOG_COMPACT_ERROR trantor::Logger(trantor::Logger::kError).stream()
432#define LOG_COMPACT_ERROR_TO(index) \
433 trantor::Logger(trantor::Logger::kError).setIndex(index).stream()
434#define LOG_COMPACT_FATAL trantor::Logger(trantor::Logger::kFatal).stream()
435#define LOG_COMPACT_FATAL_TO(index) \
436 trantor::Logger(trantor::Logger::kFatal).setIndex(index).stream()
437#define LOG_COMPACT_SYSERR trantor::Logger(true).stream()
438#define LOG_COMPACT_SYSERR_TO(index) \
439 trantor::Logger(true).setIndex(index).stream()
440// LOG_COMPACT_... end block
441
442#define LOG_RAW trantor::RawLogger().stream()
443#define LOG_RAW_TO(index) trantor::RawLogger().setIndex(index).stream()
444
445#define LOG_TRACE_IF(cond) \
446 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && \
447 (cond)) \
448 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
449 .stream()
450#define LOG_DEBUG_IF(cond) \
451 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kDebug) && \
452 (cond)) \
453 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
454 .stream()
455#define LOG_INFO_IF(cond) \
456 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kInfo) && \
457 (cond)) \
458 trantor::Logger(__FILE__, __LINE__).stream()
459#define LOG_WARN_IF(cond) \
460 TRANTOR_IF_(cond) \
461 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
462#define LOG_ERROR_IF(cond) \
463 TRANTOR_IF_(cond) \
464 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
465#define LOG_FATAL_IF(cond) \
466 TRANTOR_IF_(cond) \
467 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
468
469#ifdef NDEBUG
470#define DLOG_TRACE \
471 TRANTOR_IF_(0) \
472 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
473 .stream()
474#define DLOG_DEBUG \
475 TRANTOR_IF_(0) \
476 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
477 .stream()
478#define DLOG_INFO \
479 TRANTOR_IF_(0) \
480 trantor::Logger(__FILE__, __LINE__).stream()
481#define DLOG_WARN \
482 TRANTOR_IF_(0) \
483 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
484#define DLOG_ERROR \
485 TRANTOR_IF_(0) \
486 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
487#define DLOG_FATAL \
488 TRANTOR_IF_(0) \
489 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
490
491#define DLOG_TRACE_IF(cond) \
492 TRANTOR_IF_(0) \
493 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
494 .stream()
495#define DLOG_DEBUG_IF(cond) \
496 TRANTOR_IF_(0) \
497 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
498 .stream()
499#define DLOG_INFO_IF(cond) \
500 TRANTOR_IF_(0) \
501 trantor::Logger(__FILE__, __LINE__).stream()
502#define DLOG_WARN_IF(cond) \
503 TRANTOR_IF_(0) \
504 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
505#define DLOG_ERROR_IF(cond) \
506 TRANTOR_IF_(0) \
507 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
508#define DLOG_FATAL_IF(cond) \
509 TRANTOR_IF_(0) \
510 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
511#else
512#define DLOG_TRACE \
513 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
514 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
515 .stream()
516#define DLOG_DEBUG \
517 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
518 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
519 .stream()
520#define DLOG_INFO \
521 TRANTOR_IF_(trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
522 trantor::Logger(__FILE__, __LINE__).stream()
523#define DLOG_WARN \
524 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
525#define DLOG_ERROR \
526 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
527#define DLOG_FATAL \
528 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
529
530#define DLOG_TRACE_IF(cond) \
531 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && \
532 (cond)) \
533 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
534 .stream()
535#define DLOG_DEBUG_IF(cond) \
536 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kDebug) && \
537 (cond)) \
538 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
539 .stream()
540#define DLOG_INFO_IF(cond) \
541 TRANTOR_IF_((trantor::Logger::logLevel() <= trantor::Logger::kInfo) && \
542 (cond)) \
543 trantor::Logger(__FILE__, __LINE__).stream()
544#define DLOG_WARN_IF(cond) \
545 TRANTOR_IF_(cond) \
546 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
547#define DLOG_ERROR_IF(cond) \
548 TRANTOR_IF_(cond) \
549 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
550#define DLOG_FATAL_IF(cond) \
551 TRANTOR_IF_(cond) \
552 trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
553#endif
554
555const char *strerror_tl(int savedErrno);
556} // namespace trantor
Definition LogStream.h:120
Calculate of basename of source files in compile time.
Definition Logger.h:58
static void setOutputFunction(std::function< void(const char *msg, const uint64_t len)> outputFunc, std::function< void()> flushFunc, int index=-1)
Set the output function.
Definition Logger.h:124
static void enableSpdLog(int index, std::shared_ptr< spdlog::logger > logger={})
Enable logging with spdlog for the specified channel.
static bool hasSpdLogSupport()
Check whether trantor was build with spdlog support.
static void setLogLevel(LogLevel level)
Set the log level. Logs below the level are not printed.
Definition Logger.h:146
static void disableSpdLog()
Disable logging with spdlog for the default channel.
Definition Logger.h:220
static bool displayLocalTime()
Check whether it shows local time or UTC time.
Definition Logger.h:164
static std::shared_ptr< spdlog::logger > getDefaultSpdLogger(int index)
Get a default spdlog::logger for the specified channel.
static void setDisplayLocalTime(bool showLocalTime)
Set whether it shows local time or UTC time. the default is UTC.
Definition Logger.h:172
static std::shared_ptr< spdlog::logger > getSpdLogger(int index=-1)
Get the spdlog::logger set on the specified channel.
static LogLevel logLevel()
Get the current log level.
Definition Logger.h:156
static void enableSpdLog(std::shared_ptr< spdlog::logger > logger={})
Enable logging with spdlog for the default channel.
Definition Logger.h:201
static void disableSpdLog(int index)
Disable logging with spdlog for the specified channel.
Definition Logger.h:343
Definition EventLoop.h:34