logger_impl.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //local
  2. #include "logger_impl.h"
  3. //stl
  4. #include <fstream>
  5. #include <random>
  6. #include <fmt/format.h>
  7. //boost
  8. #include <boost/algorithm/string.hpp>
  9. namespace robotics::v3 {
  10. logger_impl::~logger_impl() {
  11. thread_pool_.join();
  12. }
  13. void logger_impl::write(int color, std::string const& type, std::string const& time, std::string const& file, std::string const& func, int line, std::thread::id thread_id, std::string const& text) {
  14. if (!thread_pool_.executor().running_in_this_thread()) {
  15. asio::post(thread_pool_, std::bind(&logger_impl::write, this, color, type, time, file, func, line, thread_id, text));
  16. return;
  17. }
  18. static time_t g_remove_ergodic = 0;
  19. union __thread_id__ {
  20. __thread_id__(std::thread::id d) :
  21. id(d) {
  22. }
  23. std::thread::id id;
  24. unsigned int iid;
  25. };
  26. __thread_id__ th_id = thread_id;
  27. if (save_.find(type) == save_.end()) {
  28. std::cout << fmt::format("\033[{}m{} [{}] [{}#{}#{}#{}] ==>>\033[0m{}", color, time, type, file, func, line, th_id.iid, text) << std::endl;
  29. }
  30. else {
  31. if (!std::filesystem::is_directory("log")) {
  32. std::filesystem::create_directory("log");
  33. }
  34. std::string log_text = fmt::format("{} [{}] [{}#{}#{}#{}] ==>>{}", time, type, file, func, line, th_id.iid, text);
  35. std::string log_filename = fmt::format("log/{}_{}.log", type, datetime::current_datetime().to_string("yyyy-MM-dd"));
  36. std::fstream fs(log_filename, std::ios::out | std::ios::app);
  37. if (fs.is_open()) {
  38. fs << log_text;
  39. fs << std::endl;
  40. fs.close();
  41. backup(log_filename);
  42. time_t current_time = datetime::current_time_stamp();
  43. if (g_remove_ergodic == 0 || g_remove_ergodic + 43200000 < current_time) {
  44. g_remove_ergodic = current_time;
  45. remove();
  46. }
  47. }
  48. }
  49. }
  50. logger_impl& logger_impl::instance() {
  51. static logger_impl g_instance;
  52. return g_instance;
  53. }
  54. void logger_impl::install(std::string const& filename) {
  55. instance().max_time_ = config::read<int>("LOGGER", "TIME", 30);
  56. instance().max_size_ = config::read<int>("LOGGER", "SIZE", 10);
  57. auto type = config::read<std::string>("LOGGER", "TYPE", "info,debug,warn,error");
  58. std::vector<std::string> types;
  59. boost::split(types, type, boost::is_any_of(","));
  60. for (auto& it : types) {
  61. if (it.empty())
  62. continue;
  63. instance().save_.insert(it);
  64. }
  65. }
  66. logger_impl::logger_impl() :
  67. thread_pool_(1) {
  68. }
  69. void logger_impl::backup(std::string const& filename) {
  70. if (!std::filesystem::exists(filename) || std::filesystem::file_size(filename) <= max_size_ * 1024 * 1024)
  71. return;
  72. for (int i = 0; i < 10; i++) {
  73. std::string backup_filename = filename;
  74. std::random_device r;
  75. std::default_random_engine e1(r());
  76. std::uniform_int_distribution<int> uniform_dist(10000, 99999);
  77. std::string mean = "__" + std::to_string(uniform_dist(e1));
  78. backup_filename.insert(backup_filename.begin() + backup_filename.size() - 4, mean.begin(), mean.end());
  79. if (std::filesystem::exists(backup_filename))
  80. continue;
  81. std::filesystem::copy(filename, backup_filename);
  82. std::fstream fout(filename, std::ios::out | std::ios::trunc);
  83. fout.close();
  84. break;
  85. }
  86. }
  87. void logger_impl::remove() {
  88. datetime remove_time = datetime::current_datetime();
  89. remove_time.add_day(-this->max_time_);
  90. const std::filesystem::path path_to_directory = "log";
  91. try {
  92. if (std::filesystem::exists(path_to_directory) && std::filesystem::is_directory(path_to_directory)) {
  93. for (const auto& entry : std::filesystem::recursive_directory_iterator(path_to_directory)) {
  94. const auto& path = entry.path();
  95. if (std::filesystem::is_regular_file(path)) {
  96. auto create_time = std::filesystem::last_write_time(path);
  97. time_t elapse = std::chrono::duration_cast<std::chrono::milliseconds>(std::filesystem::file_time_type::clock::now().time_since_epoch() - std::chrono::system_clock::now().time_since_epoch()).count();
  98. std::chrono::milliseconds secs = std::chrono::duration_cast<std::chrono::milliseconds>(create_time.time_since_epoch());
  99. v3::datetime time = (secs.count() - elapse);
  100. if (remove_time > time) {
  101. std::filesystem::remove(path);
  102. }
  103. }
  104. }
  105. }
  106. }
  107. catch (...) {}
  108. }
  109. logger_stream::logger_stream(
  110. int color,
  111. std::string const& type,
  112. std::string const& time,
  113. std::string const& file,
  114. std::string const& func,
  115. int line,
  116. std::thread::id thread_id) :
  117. color_(color),
  118. type_(type),
  119. time_(time),
  120. file_(file),
  121. func_(func),
  122. line_(line),
  123. thread_id_(thread_id) {
  124. }
  125. logger_stream::~logger_stream() {
  126. std::string text = stream.str();
  127. if (!text.empty())
  128. logger_impl::instance().write(color_, type_, time_, file_, func_, line_, thread_id_, text);
  129. }
  130. }