You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 rivejä
6.2 KiB

  1. #pragma once
  2. #include <memory>
  3. #include <chrono>
  4. #include <thread>
  5. #include <sstream>
  6. #include "Exception.h"
  7. // () mandatory
  8. // [] optional
  9. // (logger), (LogLevel: Debug|Info|Warn|Error), [Sender], [Message, [Arguments]]
  10. #define logMessage(logger, level, ...) \
  11. if (logger.isEnabled(logging::Level::level)) \
  12. logger.makeLogHelper(logging::Level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = logging::LogMessage()
  13. // () mandatory
  14. // [] optional
  15. // (LogLevel: Debug|Info|Warn|Error), [Sender], [Message, [Arguments]]
  16. #define logGlobalMessage(level, ...) \
  17. if (logging::isEnabled(logging::Level::level)) \
  18. logging::makeLogHelper(logging::Level::level, __FILE__, __LINE__, ## __VA_ARGS__ ) = logging::LogMessage()
  19. namespace logging
  20. {
  21. enum class Level
  22. {
  23. Debug = 0,
  24. Info,
  25. Warn,
  26. Error,
  27. };
  28. struct Data
  29. {
  30. Level level;
  31. std::chrono::steady_clock::time_point time;
  32. void* sender;
  33. std::thread::id thread;
  34. const char* file;
  35. int line;
  36. std::string name;
  37. std::string message;
  38. };
  39. using DataPtrS = std::shared_ptr<Data>;
  40. struct Logger;
  41. struct LogMessage
  42. {
  43. private:
  44. std::ostringstream _msg;
  45. public:
  46. inline std::string str() const
  47. { return _msg.str(); }
  48. template <typename T>
  49. inline LogMessage& operator <<(const T& value)
  50. {
  51. _msg << value;
  52. return *this;
  53. }
  54. inline LogMessage& operator <<(std::ostream& (*callback)(std::ostream&))
  55. {
  56. callback(_msg);
  57. return *this;
  58. }
  59. LogMessage() :
  60. _msg()
  61. { }
  62. LogMessage(const std::string& msg) :
  63. _msg(msg)
  64. { }
  65. private:
  66. LogMessage(const LogMessage&) = delete;
  67. LogMessage(LogMessage&&) = delete;
  68. };
  69. struct LogHelper
  70. {
  71. private:
  72. Logger& _logger;
  73. DataPtrS _data;
  74. public:
  75. inline void operator=(const LogMessage& msg)
  76. { _data->message += msg.str(); }
  77. LogHelper(Logger& logger, DataPtrS data);
  78. ~LogHelper();
  79. };
  80. struct Logger
  81. {
  82. private:
  83. Logger(const Logger&) = delete;
  84. Logger(Logger&&) = delete;
  85. public:
  86. Logger() { }
  87. virtual const std::string& name() const;
  88. virtual bool isEnabled(Level level) const;
  89. virtual void log(DataPtrS data) const;
  90. template<class Sender>
  91. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message)
  92. { return makeLogHelper<void>(level, file, line, static_cast<void*>(sender), message); }
  93. template<class Sender>
  94. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender)
  95. { return makeLogHelper<void>(level, file, line, static_cast<void*>(sender), std::string()); }
  96. inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message)
  97. { return makeLogHelper(level, file, line, nullptr, message); }
  98. inline LogHelper makeLogHelper(Level level, const char* file, int line)
  99. { return makeLogHelper(level, file, line, nullptr, std::string()); }
  100. template<class Sender, class... Args>
  101. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message, Args... args)
  102. {
  103. std::unique_ptr<char, decltype(&free)> buff(static_cast<char*>(malloc(0x8000)), &free);
  104. auto len = snprintf(buff.get(), 10240, message.c_str(), args...);
  105. if (len < 0)
  106. throw utl::ErrorException(errno);
  107. return makeLogHelper<Sender>(level, file, line, sender, std::string(buff.get(), len));
  108. }
  109. template<class... Args>
  110. inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message, Args... args)
  111. { return makeLogHelper<void, Args...>(level, file, line, nullptr, message, args...); }
  112. };
  113. template<>
  114. inline LogHelper Logger::makeLogHelper<void>(Level level, const char* file, int line, void* sender, std::string message)
  115. {
  116. DataPtrS data(new Data());
  117. data->level = level;
  118. data->time = std::chrono::steady_clock::now();
  119. data->thread = std::this_thread::get_id();
  120. data->file = file;
  121. data->line = line;
  122. data->sender = sender;
  123. data->name = name();
  124. data->message = message;
  125. return LogHelper(*this, data);
  126. }
  127. Logger& getLogger(const std::string& name = "");
  128. inline bool isEnabled(Level level)
  129. { return getLogger().isEnabled(level); }
  130. template <class Sender>
  131. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message)
  132. { return getLogger().makeLogHelper<Sender>(level, file, line, sender, message); }
  133. template <class Sender>
  134. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender)
  135. { return getLogger().makeLogHelper<Sender>(level, file, line, sender, std::string()); }
  136. inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message)
  137. { return getLogger().makeLogHelper<void>(level, file, line, nullptr, message); }
  138. inline LogHelper makeLogHelper(Level level, const char* file, int line)
  139. { return getLogger().makeLogHelper<void>(level, file, line, nullptr, std::string()); }
  140. template <class Sender, class... Args>
  141. inline LogHelper makeLogHelper(Level level, const char* file, int line, Sender* sender, std::string message, Args... args)
  142. { return getLogger().makeLogHelper<Sender, Args...>(level, file, line, sender, message, args...); }
  143. template <class... Args>
  144. inline LogHelper makeLogHelper(Level level, const char* file, int line, std::string message, Args... args)
  145. { return getLogger().makeLogHelper<void, Args...>(level, file, line, nullptr, message, args...); }
  146. void resetLogging();
  147. }