setup_log.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright Takatoshi Kondo 2020
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(MQTT_SETUP_LOG_HPP)
  7. #define MQTT_SETUP_LOG_HPP
  8. // This is an example implementation for logging setup.
  9. // If your code doesn't use Boost.Log then you can use the setup_log() directly.
  10. // setup_log() provides a typical console logging setup.
  11. // If you want to use existing Boost.Log related code with mqtt_cpp,
  12. // then you can write your own logging setup code.
  13. // setup_log() could be a good reference for your own logging setup code.
  14. #include <mqtt/namespace.hpp>
  15. #include <mqtt/log.hpp>
  16. #if defined(MQTT_USE_LOG)
  17. #include <mqtt/move.hpp>
  18. #include <boost/filesystem.hpp>
  19. #include <boost/date_time/posix_time/posix_time_io.hpp>
  20. #endif // defined(MQTT_USE_LOG)
  21. namespace MQTT_NS {
  22. #if defined(MQTT_USE_LOG)
  23. static constexpr char const* log_color_table[] {
  24. "\033[0m", // trace
  25. "\033[36m", // debug
  26. "\033[32m", // info
  27. "\033[33m", // warning
  28. "\033[35m", // error
  29. "\033[31m", // fatal
  30. };
  31. /**
  32. * @brief Setup logging
  33. * @param threshold
  34. * Set threshold severity_level by channel
  35. * If the log severity_level >= threshold then log message outputs.
  36. */
  37. inline
  38. void setup_log(std::map<std::string, severity_level> threshold) {
  39. // https://www.boost.org/doc/libs/1_73_0/libs/log/doc/html/log/tutorial/advanced_filtering.html
  40. auto fmt =
  41. [](boost::log::record_view const& rec, boost::log::formatting_ostream& strm) {
  42. // Timestamp custom formatting example
  43. if (auto v = boost::log::extract<boost::posix_time::ptime>("TimeStamp", rec)) {
  44. strm.imbue(
  45. std::locale(
  46. strm.getloc(),
  47. // https://www.boost.org/doc/html/date_time/date_time_io.html#date_time.format_flags
  48. new boost::posix_time::time_facet("%H:%M:%s") // ownership is moved here
  49. )
  50. );
  51. strm << v.get() << " ";
  52. }
  53. // ThreadID example
  54. if (auto v = boost::log::extract<boost::log::thread_id>("ThreadID", rec)) {
  55. strm << "T:" << v.get() << " ";
  56. }
  57. // Adjust severity length example
  58. if (auto v = boost::log::extract<severity_level>("Severity", rec)) {
  59. strm << log_color_table[static_cast<std::size_t>(v.get())];
  60. strm << "S:" << std::setw(7) << std::left << v.get() << " ";
  61. }
  62. if (auto v = boost::log::extract<channel>("Channel", rec)) {
  63. strm << "C:" << std::setw(5) << std::left << v.get() << " ";
  64. }
  65. // Shorten file path example
  66. if (auto v = boost::log::extract<std::string>("MqttFile", rec)) {
  67. strm << boost::filesystem::path(v.get()).filename().string() << ":";
  68. }
  69. if (auto v = boost::log::extract<unsigned int>("MqttLine", rec)) {
  70. strm << v.get() << " ";
  71. }
  72. if (auto v = boost::log::extract<void const*>("MqttAddress", rec)) {
  73. strm << "A:" << v.get() << " ";
  74. }
  75. #if 0 // function is ofthen noisy
  76. if (auto v = boost::log::extract<std::string>("MqttFunction", rec)) {
  77. strm << v << ":";
  78. }
  79. #endif
  80. strm << rec[boost::log::expressions::smessage];
  81. strm << "\033[0m";
  82. };
  83. // https://www.boost.org/doc/libs/1_73_0/libs/log/doc/html/log/tutorial/sinks.html
  84. boost::shared_ptr<std::ostream> stream(&std::clog, boost::null_deleter());
  85. using text_sink = boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>;
  86. auto sink = boost::make_shared<text_sink>();
  87. sink->locked_backend()->add_stream(stream);
  88. sink->set_formatter(fmt);
  89. auto fil =
  90. [threshold = force_move(threshold)]
  91. (boost::log::attribute_value_set const& avs) {
  92. {
  93. // For mqtt
  94. auto chan = boost::log::extract<channel>("Channel", avs);
  95. auto sev = boost::log::extract<severity_level>("Severity", avs);
  96. if (chan && sev) {
  97. auto it = threshold.find(chan.get());
  98. if (it == threshold.end()) return false;
  99. return sev.get() >= it->second;
  100. }
  101. }
  102. return true;
  103. };
  104. boost::log::core::get()->set_filter(fil);
  105. boost::log::core::get()->add_sink(sink);
  106. boost::log::add_common_attributes();
  107. }
  108. /**
  109. * @brief Setup logging
  110. * @param threshold
  111. * Set threshold severity_level for all channels
  112. * If the log severity_level >= threshold then log message outputs.
  113. */
  114. inline
  115. void setup_log(severity_level threshold = severity_level::warning) {
  116. setup_log(
  117. {
  118. { "mqtt_api", threshold },
  119. { "mqtt_cb", threshold },
  120. { "mqtt_impl", threshold },
  121. { "mqtt_broker", threshold },
  122. { "mqtt_test", threshold },
  123. }
  124. );
  125. }
  126. #else // defined(MQTT_USE_LOG)
  127. template <typename... Params>
  128. void setup_log(Params&&...) {}
  129. #endif // defined(MQTT_USE_LOG)
  130. } // namespace MQTT_NS
  131. #endif // MQTT_SETUP_LOG_HPP