log.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef __ASIO2_LOG_HPP__
  11. #define __ASIO2_LOG_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <asio2/base/detail/push_options.hpp>
  16. #include <cassert>
  17. #include <string>
  18. #include <asio2/external/predef.h>
  19. #include <asio2/external/assert.hpp>
  20. #include <asio2/base/detail/filesystem.hpp>
  21. #if defined(ASIO2_ENABLE_LOG)
  22. #if __has_include(<spdlog/spdlog.h>)
  23. #if ASIO2_OS_LINUX || ASIO2_OS_UNIX
  24. #if __has_include(<unistd.h>)
  25. #include <unistd.h>
  26. #endif
  27. #if __has_include(<dirent.h>)
  28. #include <dirent.h>
  29. #endif
  30. #elif ASIO2_OS_WINDOWS
  31. #ifndef WIN32_LEAN_AND_MEAN
  32. #define WIN32_LEAN_AND_MEAN
  33. #endif
  34. #if __has_include(<Windows.h>)
  35. #include <Windows.h>
  36. #endif
  37. #elif ASIO2_OS_MACOS
  38. #if __has_include(<mach-o/dyld.h>)
  39. #include <mach-o/dyld.h>
  40. #endif
  41. #endif
  42. #include <spdlog/spdlog.h>
  43. #include <spdlog/sinks/basic_file_sink.h>
  44. #include <spdlog/fmt/bundled/chrono.h>
  45. #else
  46. #undef ASIO2_ENABLE_LOG
  47. #endif
  48. #endif
  49. namespace asio2::detail
  50. {
  51. #if defined(ASIO2_ENABLE_LOG)
  52. static std::shared_ptr<spdlog::logger>& get_logger()
  53. {
  54. static std::shared_ptr<spdlog::logger> logger;
  55. static std::mutex mtx;
  56. if (!logger)
  57. {
  58. std::lock_guard guard(mtx);
  59. if (!logger)
  60. {
  61. std::string filepath;
  62. std::shared_ptr<spdlog::logger> loger;
  63. try
  64. {
  65. #if ASIO2_OS_LINUX || ASIO2_OS_UNIX
  66. filepath.resize(PATH_MAX);
  67. auto r = readlink("/proc/self/exe", (char *)filepath.data(), PATH_MAX);
  68. std::ignore = r; // gcc 7 warning: ignoring return value of ... [-Wunused-result]
  69. #elif ASIO2_OS_WINDOWS
  70. filepath.resize(MAX_PATH);
  71. filepath.resize(::GetModuleFileNameA(NULL, (LPSTR)filepath.data(), MAX_PATH));
  72. #elif ASIO2_OS_MACOS
  73. filepath.resize(PATH_MAX);
  74. std::uint32_t bufsize = std::uint32_t(PATH_MAX);
  75. _NSGetExecutablePath(filepath.data(), std::addressof(bufsize));
  76. #endif
  77. if (std::string::size_type pos = filepath.find('\0'); pos != std::string::npos)
  78. filepath.resize(pos);
  79. ASIO2_ASSERT(!filepath.empty());
  80. std::filesystem::path path{ filepath };
  81. std::string name = path.filename().string();
  82. std::string ext = path.extension().string();
  83. name.resize(name.size() - ext.size());
  84. filepath = path.parent_path().append(name).string() + ".asio2.log";
  85. auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filepath, true);
  86. file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
  87. loger = std::make_shared<spdlog::logger>("ASIO2_LOG", std::move(file_sink));
  88. loger->set_level(spdlog::level::debug);
  89. loger->flush_on(spdlog::level::err);
  90. }
  91. catch (const std::exception&)
  92. {
  93. loger.reset();
  94. }
  95. logger = std::move(loger);
  96. }
  97. }
  98. return logger;
  99. }
  100. template<typename... Args>
  101. inline void log(spdlog::level::level_enum lvl, fmt::format_string<Args...> fmtstr, Args&&...args)
  102. {
  103. std::shared_ptr<spdlog::logger>& loger = get_logger();
  104. if (loger)
  105. {
  106. loger->log(lvl, fmtstr, std::forward<Args>(args)...);
  107. }
  108. }
  109. #else
  110. template <typename... Ts>
  111. inline constexpr void log(Ts const& ...) noexcept {}
  112. #endif
  113. class [[maybe_unused]] external_linkaged_log
  114. {
  115. public:
  116. [[maybe_unused]] static bool& has_unexpected_behavior() noexcept
  117. {
  118. static bool flag = false;
  119. return flag;
  120. }
  121. };
  122. namespace internal_linkaged_log
  123. {
  124. [[maybe_unused]] static bool& has_unexpected_behavior() noexcept
  125. {
  126. static bool flag = false;
  127. return flag;
  128. }
  129. }
  130. // just for : debug, find bug ...
  131. [[maybe_unused]] static bool& has_unexpected_behavior() noexcept
  132. {
  133. return external_linkaged_log::has_unexpected_behavior();
  134. }
  135. }
  136. #ifdef ASIO2_LOG
  137. static_assert(false, "Unknown ASIO2_LOG definition will affect the relevant functions of this program.");
  138. #endif
  139. #if defined(ASIO2_ENABLE_LOG)
  140. #define ASIO2_LOG(...) asio2::detail::log(__VA_ARGS__)
  141. #define ASIO2_LOG_TRACE(...) asio2::detail::log(spdlog::level::trace , __VA_ARGS__)
  142. #define ASIO2_LOG_DEBUG(...) asio2::detail::log(spdlog::level::debug , __VA_ARGS__)
  143. #define ASIO2_LOG_INFOR(...) asio2::detail::log(spdlog::level::info , __VA_ARGS__)
  144. #define ASIO2_LOG_WARNS(...) asio2::detail::log(spdlog::level::warn , __VA_ARGS__)
  145. #define ASIO2_LOG_ERROR(...) asio2::detail::log(spdlog::level::err , __VA_ARGS__)
  146. #define ASIO2_LOG_FATAL(...) asio2::detail::log(spdlog::level::critical, __VA_ARGS__)
  147. #else
  148. #define ASIO2_LOG(...) ((void)0)
  149. #define ASIO2_LOG_TRACE(...) ((void)0)
  150. #define ASIO2_LOG_DEBUG(...) ((void)0)
  151. #define ASIO2_LOG_INFOR(...) ((void)0)
  152. #define ASIO2_LOG_WARNS(...) ((void)0)
  153. #define ASIO2_LOG_ERROR(...) ((void)0)
  154. #define ASIO2_LOG_FATAL(...) ((void)0)
  155. #endif
  156. #include <asio2/base/detail/pop_options.hpp>
  157. #endif // !__ASIO2_LOG_HPP__