logger.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // logger.cpp
  3. // logger
  4. //
  5. // Created by Sam Jaffe on 9/3/16.
  6. //
  7. #include <sys/time.h>
  8. #include <cassert>
  9. #include <cmath>
  10. #include <ctime>
  11. #include <map>
  12. #include <stdexcept>
  13. #include "expect/expect.hpp"
  14. #include "logger.hpp"
  15. #include "properties.hpp"
  16. namespace logging {
  17. #define X(l) \
  18. case logging::L##l: \
  19. return #l;
  20. const char* level_header(log_level l) {
  21. assert(l != logging::LNONE);
  22. switch (l) {
  23. X(FATAL)
  24. X(CRITICAL)
  25. X(ERROR)
  26. X(WARNING)
  27. X(INFO)
  28. X(DEBUG)
  29. X(TRACE)
  30. X(NONE)
  31. }
  32. }
  33. #undef X
  34. }
  35. namespace {
  36. struct timeval now( ) {
  37. struct timeval tv;
  38. gettimeofday( &tv, nullptr );
  39. return tv;
  40. }
  41. }
  42. namespace logging {
  43. class multiple_bindings : public std::logic_error {
  44. using std::logic_error::logic_error;
  45. };
  46. // extern logger_impl& _logger_impl_shared_instance();
  47. extern _binding _default_logger_impl;
  48. static _binding _impl_binding = nullptr;
  49. bool bind_logger_impl(_binding impl) {
  50. expects(_impl_binding == nullptr, multiple_bindings,
  51. "Only one logger implementation may be bound");
  52. _impl_binding = impl;
  53. return true;
  54. }
  55. logger_impl& _i_get_shared_instance() {
  56. if (_impl_binding == nullptr) {
  57. return _default_logger_impl();
  58. } else {
  59. return _impl_binding();
  60. }
  61. }
  62. }
  63. namespace logging {
  64. logger& logger::instance() {
  65. static logger instance;
  66. return instance;
  67. }
  68. logger& logger::instance(std::string const & name) {
  69. using p_logger = std::unique_ptr<logger>;
  70. using store = std::map<std::string, p_logger>;
  71. static store instances;
  72. store::iterator it;
  73. if ((it = instances.find(name)) != instances.end()) {
  74. return *(it->second);
  75. }
  76. return *(instances.emplace(std::make_pair(name, p_logger(new logger(name)))).first->second);
  77. }
  78. logger::logger(std::string const & name)
  79. : min_level_(LDEBUG)
  80. , logger_name_(name)
  81. , impl_(_i_get_shared_instance())
  82. {
  83. }
  84. logger::~logger() {
  85. flush();
  86. }
  87. void logger::log(log_level ll, location_info info, std::string const & msg) {
  88. impl_.write({ now( ), ll, info, logger_name_.c_str(), msg });
  89. }
  90. bool logger::should_log( log_level ll ) const {
  91. return ll < min_level_ && impl_.should_log( ll );
  92. }
  93. void logger::flush() {
  94. impl_.flush();
  95. }
  96. }
  97. namespace logging {
  98. bool logger_impl::should_log( log_level ll ) const {
  99. return ll < min_log_level;
  100. }
  101. }
  102. void test() {
  103. logging::logger & LOG = logging::logger::instance( );
  104. LOG.log(logging::LERROR, "{}", 5);
  105. }