Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

257 linhas
6.7 KiB

  1. #include <list>
  2. #include <iomanip>
  3. #include "cpputils/LoggerImpl.h"
  4. using namespace logging;
  5. struct StreamFormatSaver
  6. {
  7. std::ios state;
  8. std::ostream& stream;
  9. StreamFormatSaver(std::ostream& s) :
  10. state (nullptr),
  11. stream (s)
  12. { state.copyfmt(stream); }
  13. ~StreamFormatSaver()
  14. { stream.copyfmt(state); }
  15. };
  16. struct Manager
  17. {
  18. private:
  19. using LoggerImplPtrU = std::unique_ptr<LoggerImpl>;
  20. LoggerImpl _defaultLogger;
  21. std::map<std::string, LoggerImplPtrU> _logger;
  22. std::list<Rule> _rules;
  23. std::set<Consumer*> _consumer;
  24. LoggerImpl& initLogger(LoggerImpl& logger)
  25. {
  26. for (auto& rule : _rules)
  27. {
  28. if (rule.loggerMatcher->match(logger))
  29. logger.registerRule(rule);
  30. }
  31. return logger;
  32. }
  33. public:
  34. inline Logger& getLogger(const std::string& name)
  35. {
  36. if (name.empty())
  37. return _defaultLogger;
  38. auto it = _logger.find(name);
  39. return (it != _logger.end()
  40. ? *it->second
  41. : initLogger(*_logger.emplace(name, LoggerImplPtrU(new LoggerImpl(name))).first->second));
  42. }
  43. void registerConsumer(Consumer& consumer)
  44. {
  45. _consumer.insert(&consumer);
  46. for (auto& rule : _rules)
  47. {
  48. if (rule.consumerMatcher->match(consumer))
  49. rule.registerConsumer(consumer);
  50. }
  51. }
  52. void unregisterConsumer(Consumer& consumer)
  53. {
  54. for (auto& rule : _rules)
  55. rule.unregisterConsumer(consumer);
  56. }
  57. RuleHandle defineRule(MatcherPtrU loggerMatcher, MatcherPtrU consumerMatcher, Level minLevel, Level maxLevel)
  58. {
  59. _rules.emplace_back(std::move(loggerMatcher), std::move(consumerMatcher), minLevel, maxLevel);
  60. auto& rule = _rules.back();
  61. for (auto& c : _consumer)
  62. {
  63. if (rule.consumerMatcher->match(*c))
  64. rule.registerConsumer(*c);
  65. }
  66. if (rule.loggerMatcher->match(_defaultLogger))
  67. _defaultLogger.registerRule(rule);
  68. for (auto& l : _logger)
  69. {
  70. if (rule.loggerMatcher->match(*l.second))
  71. l.second->registerRule(rule);
  72. }
  73. return &rule;
  74. }
  75. void undefineRule(RuleHandle rule)
  76. {
  77. auto r = static_cast<Rule*>(rule);
  78. auto it = _rules.begin();
  79. while (&*it != r && it != _rules.end())
  80. ++it;
  81. if (it == _rules.end())
  82. return;
  83. _defaultLogger.unregisterRule(*it);
  84. for (auto& l : _logger)
  85. l.second->unregisterRule(*it);
  86. _rules.erase(it);
  87. }
  88. inline void reset()
  89. {
  90. _logger.clear();
  91. _rules.clear();
  92. _consumer.clear();
  93. }
  94. Manager() :
  95. _defaultLogger(std::string())
  96. { }
  97. };
  98. Manager& manager()
  99. {
  100. static Manager value;
  101. return value;
  102. }
  103. std::string EmptyString;
  104. Consumer::Consumer(const std::string& n, bool autoRegister) :
  105. _name(n)
  106. {
  107. if (autoRegister)
  108. registerConsumer(*this);
  109. }
  110. Consumer::~Consumer()
  111. { unregisterConsumer(*this); }
  112. void StreamConsumer::log(DataPtrS data)
  113. {
  114. std::lock_guard<std::mutex> lk(_mutex);
  115. using namespace std;
  116. if (!data)
  117. return;
  118. auto& d = *data;
  119. auto t = std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(d.time.time_since_epoch()).count();
  120. auto f = d.file;
  121. if (f)
  122. {
  123. auto tmp = strrchr(f, '/');
  124. if (tmp)
  125. f = tmp + 1;
  126. }
  127. else
  128. f = "unknown";
  129. StreamFormatSaver formatSaver(*_stream);
  130. if (t >= 0) *_stream << "[" << fixed << setfill(' ') << setw(17) << setprecision(6) << t << "] ";
  131. switch(d.level)
  132. {
  133. case Level::Debug: *_stream << "DEBUG "; break;
  134. case Level::Info: *_stream << "INFO "; break;
  135. case Level::Warn: *_stream << "WARN "; break;
  136. case Level::Error: *_stream << "ERROR "; break;
  137. }
  138. if (d.sender) *_stream << "0x" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.sender;
  139. else *_stream << " ";
  140. if (d.thread != std::thread::id()) *_stream << "@" << hex << setw(2 * sizeof(void*)) << setfill('0') << d.thread;
  141. else *_stream << " ";
  142. if (!d.name.empty()) *_stream << " '" << d.name << "'";
  143. if (d.line) *_stream << " - " << setw(25) << setfill(' ') << f << ":" << setw(5) << setfill(' ') << dec << d.line;
  144. if (!d.message.empty())
  145. {
  146. *_stream << ": " << d.message;
  147. if (d.message.back() != '\n')
  148. *_stream << std::endl;
  149. }
  150. else
  151. *_stream << std::endl;
  152. }
  153. bool AllMatcher::match(const Logger& logger) const
  154. { return true; }
  155. bool AllMatcher::match(const Consumer& consumer) const
  156. { return true; }
  157. bool RegexMatcher::match(const Logger& logger) const
  158. { return !logger.name().empty() && std::regex_match(logger.name(), _regex) != _invert; }
  159. bool RegexMatcher::match(const Consumer& consumer) const
  160. { return !consumer.name().empty() && std::regex_match(consumer.name(), _regex) != _invert; }
  161. bool DefaultLoggerMatcher::match(const Logger& logger) const
  162. { return &_defaultLogger == &logger; }
  163. LogHelper::LogHelper(Logger& logger, DataPtrS data) :
  164. _logger (logger),
  165. _data (data)
  166. { }
  167. LogHelper::~LogHelper()
  168. { _logger.log(_data); }
  169. const std::string& Logger::name() const
  170. { return EmptyString; }
  171. bool Logger::isEnabled(Level level) const
  172. { return false; }
  173. void Logger::log(DataPtrS data) const
  174. { /* no op */ }
  175. const std::string& LoggerImpl::name() const
  176. { return _name; }
  177. bool LoggerImpl::isEnabled(Level level) const
  178. {
  179. for (auto& rule : _rules)
  180. {
  181. if (rule->isEnabled(level))
  182. return true;
  183. }
  184. return false;
  185. }
  186. void LoggerImpl::log(DataPtrS data) const
  187. {
  188. std::lock_guard<std::mutex> lk(_mutex);
  189. for (auto& r : _rules)
  190. r->log(data);
  191. }
  192. namespace logging
  193. {
  194. Logger& getLogger(const std::string& name)
  195. { return manager().getLogger(name); }
  196. void registerConsumer(Consumer& consumer)
  197. { return manager().registerConsumer(consumer); }
  198. void unregisterConsumer(Consumer& consumer)
  199. { return manager().unregisterConsumer(consumer); }
  200. RuleHandle defineRule(MatcherPtrU loggerMatcher, MatcherPtrU consumerMatcher, Level minLevel, Level maxLevel)
  201. { return manager().defineRule(std::move(loggerMatcher), std::move(consumerMatcher), minLevel, maxLevel); }
  202. void undefineRule(RuleHandle rule)
  203. { return manager().undefineRule(rule); }
  204. void resetLogging()
  205. { manager().reset(); }
  206. }