C++11 library providing functionality common to all adapters.
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.

232 lines
12 KiB

  1. // This file is under GNU General Public License 3.0
  2. // see LICENSE.txt
  3. #ifndef LIBPEPADAPTER_PEPLOG_HH
  4. #define LIBPEPADAPTER_PEPLOG_HH
  5. // getpid
  6. // Linux - unistd.h
  7. // macOS - unistd.h
  8. // Android - unistd.h
  9. // Win - process.h
  10. #ifdef WIN32
  11. #include <process.h>
  12. #else
  13. #include <unistd.h>
  14. #endif
  15. #include <sstream>
  16. #include <thread>
  17. #include "std_utils.hh"
  18. // pEpLog
  19. // ======
  20. // a "to be kept ultra small and simple" logging unit.
  21. // featuring:
  22. // * Logging macros that completely eliminate any logging calls in release-builds (NDEBUG)
  23. // * thread safe (no interleave when logging from diff threads) TODO: pEpLogger: REALLY?
  24. // * OS dependent backend switches:
  25. // * android: __android_log_print
  26. // * all other OS: cerr
  27. // * Logging without any class/object (pEpLog / pEpLogRaw macros)
  28. // * runtime switchable (on/off) only on a global level
  29. // * Class backed Logging macros (pEpLogClass / pEpLogClassRaw)
  30. // * * runtime switchable (on/off) on a class and object level
  31. //
  32. // There are already too many features and you might want even more and more.
  33. // But the feature-policy of this logging unit is very restrictive, and there is a
  34. // primary design goal to keep it very simple, maintainable and portable.
  35. //
  36. // pEpLog - logformat "thread - __FILE__::__FUNTION__ - <message>"
  37. // To be used in a non-class/object context
  38. #ifdef NDEBUG
  39. #define pEpLog(msg) \
  40. do { \
  41. } while (0)
  42. #else
  43. #define pEpLog(msg) \
  44. do { \
  45. if (pEp::Adapter::pEpLog::get_enabled()) { \
  46. std::stringstream msg_; \
  47. msg_ << "[" << _getpid() << " " << std::this_thread::get_id() << "]"; \
  48. msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \
  49. msg_ << " - " << msg; \
  50. pEp::Adapter::pEpLog::log(msg_.str()); \
  51. } \
  52. } while (0)
  53. #endif // NDEBUG
  54. // pEpLogH1 - logformat "Thread - __FILE__::__FUNTION__ - <=============== message ==============>"
  55. #ifdef NDEBUG
  56. #define pEpLogH1(msg) \
  57. do { \
  58. } while (0)
  59. #else
  60. #define pEpLogH1(msg) \
  61. do { \
  62. if (pEp::Adapter::pEpLog::get_enabled()) { \
  63. std::stringstream msg_; \
  64. msg_ << "[" << _getpid() << " " << std::this_thread::get_id() << "]"; \
  65. msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \
  66. msg_ << " - " << pEp::Adapter::pEpLog::decorateH1(msg); \
  67. pEp::Adapter::pEpLog::log(msg_.str()); \
  68. } \
  69. } while (0)
  70. #endif // NDEBUG
  71. // pEpLogH1 - logformat "Thread - __FILE__::__FUNTION__ - <--------------- message -------------->"
  72. #ifdef NDEBUG
  73. #define pEpLogH2(msg) \
  74. do { \
  75. } while (0)
  76. #else
  77. #define pEpLogH2(msg) \
  78. do { \
  79. if (pEp::Adapter::pEpLog::get_enabled()) { \
  80. std::stringstream msg_; \
  81. msg_ << "[" << _getpid() << " " << std::this_thread::get_id() << "]"; \
  82. msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \
  83. msg_ << " - " << pEp::Adapter::pEpLog::decorateH2(msg); \
  84. pEp::Adapter::pEpLog::log(msg_.str()); \
  85. } \
  86. } while (0)
  87. #endif // NDEBUG
  88. // RAW == without prefix of thread, file, function
  89. // pEpLogRaw - logformat "<message>"
  90. #ifdef NDEBUG
  91. #define pEpLogRaw(msg) \
  92. do { \
  93. } while (0)
  94. #else
  95. #define pEpLogRaw(msg) \
  96. do { \
  97. if (pEp::Adapter::pEpLog::get_enabled()) { \
  98. pEp::Adapter::pEpLog::log(msg_.str()); \
  99. } \
  100. } while (0)
  101. #endif // NDEBUG
  102. // pEpLogRawH1 - logformat "<--------------- message -------------->"
  103. #ifdef NDEBUG
  104. #define pEpLogRawH1(msg) \
  105. do { \
  106. } while (0)
  107. #else
  108. #define pEpLogRawH1(msg) \
  109. do { \
  110. if (pEp::Adapter::pEpLog::get_enabled()) { \
  111. pEp::Adapter::pEpLog::logH1(msg_.str()); \
  112. } \
  113. } while (0)
  114. #endif // NDEBUG
  115. // pEpLogRawH2 - logformat <=============== message ==============>"
  116. #ifdef NDEBUG
  117. #define pEpLogRawH2(msg) \
  118. do { \
  119. } while (0)
  120. #else
  121. #define pEpLogRawH2(msg) \
  122. do { \
  123. if (pEp::Adapter::pEpLog::get_enabled()) { \
  124. pEp::Adapter::pEpLog::logH2(msg_.str()); \
  125. } \
  126. } while (0)
  127. #endif // NDEBUG
  128. namespace pEp {
  129. namespace Adapter {
  130. namespace pEpLog {
  131. // Logging functions to control pEpLog() macro
  132. void set_enabled(const bool& is_enabled);
  133. bool get_enabled();
  134. void log(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
  135. void logH1(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
  136. void logH2(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
  137. void logH3(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
  138. std::string decorate_three_lines(const std::string& msg, char decoration = '-');
  139. std::string decorate_centered(const std::string& msg, char decoration = '-');
  140. } // namespace pEpLog
  141. } // namespace Adapter
  142. } // namespace pEp
  143. // --------------------------------------------------------------------------------------------------
  144. // pEpLogClass is to be used in a class
  145. // pEpLogger can only print the "thread - file::class::function - <message>" format using this macro
  146. // WARNING: Some magic is needed
  147. // Usage:
  148. // create your logger obj in your class as a public member (usually)
  149. // Adapter::pEpLog::pEpLogger logger{"<CLASSNAME>", enabled: true|false};
  150. // then, create an alias for your logger called "m4gic_logger_n4me" as a private member
  151. // Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
  152. // Thats all.
  153. // Now in your implementation, to log a message you just write:
  154. // pEpLogClass("my great logging message");
  155. #ifdef NDEBUG
  156. #define pEpLogClass(msg) \
  157. do { \
  158. } while (0)
  159. #else
  160. #define pEpLogClass(msg) \
  161. do { \
  162. std::stringstream msg_; \
  163. msg_ << "[" << _getpid() << " " << std::this_thread::get_id() << "]"; \
  164. msg_ << " - " << this->m4gic_logger_n4me.get_classname(); \
  165. msg_ << "[" << this->m4gic_logger_n4me.get_instancename() << "]"; \
  166. msg_ << "::" << __FUNCTION__; \
  167. msg_ << " - " << (msg); \
  168. this->m4gic_logger_n4me.logRaw(msg_.str()); \
  169. } while (0)
  170. #endif // NDEBUG
  171. // pEpLogClassRaw is the same as pEpLogClass, but does not print anything except the supplied msg
  172. // This can also be achieved without this macro, just use the log method of pEpLogger
  173. // You also need to set up the logger in your class as for pEpLogClass
  174. // The only advantage of this macro is that is compiled away to nothing with NDEBUG
  175. #ifdef NDEBUG
  176. #define pEpLogClassRaw(msg) \
  177. do { \
  178. } while (0)
  179. #else
  180. #define pEpLogClassRaw(msg) \
  181. do { \
  182. this->m4gic_logger_n4me.logRaw(msg); \
  183. } while (0)
  184. #endif // NDEBUG
  185. namespace pEp {
  186. namespace Adapter {
  187. namespace pEpLog {
  188. class pEpLogger {
  189. public:
  190. pEpLogger() = delete;
  191. pEpLogger(const std::string& classname, const bool& enabled);
  192. // Print a logging message in the format "thread - classname[instancename] - <msg>"
  193. void log(const std::string& msg, Utils::Color col = Utils::Color::WHITE) const;
  194. // Prints just "<msg>"
  195. void logRaw(const std::string& msg, Utils::Color col = Utils::Color::WHITE) const;
  196. void set_enabled(const bool& enabled);
  197. bool get_enabled() const;
  198. std::string get_classname() const;
  199. // If never set, the default instancename is a unique number
  200. void set_instancename(const std::string& name);
  201. std::string get_instancename() const;
  202. private:
  203. static int auto_instance_nr;
  204. bool is_enabled;
  205. std::string classname;
  206. std::string instancename;
  207. };
  208. } // namespace pEpLog
  209. } // namespace Adapter
  210. } // namespace pEp
  211. #endif // LIBPEPADAPTER_PEPLOG_HH