47template<global_state_type Level, fixed_string SourcePath,
int SourceLine, fixed_string Fmt,
typename... Values>
50 static_assert(std::popcount(to_underlying(Level)) == 1);
53 static constexpr char const *log_level_name =
54 Level == global_state_type::log_fatal ?
"fatal" :
55 Level == global_state_type::log_error ?
"error" :
56 Level == global_state_type::log_warning ?
"warning" :
57 Level == global_state_type::log_info ?
"info" :
58 Level == global_state_type::log_debug ?
"debug" :
59 Level == global_state_type::log_trace ?
"trace" :
60 Level == global_state_type::log_audit ?
"audit" :
61 Level == global_state_type::log_statistics ?
"stats" :
62 "<unknown log level>";
68 template<
typename... Args>
69 hi_force_inline
log_message(Args&&...args) noexcept :
70 _time_stamp(time_stamp_count::inplace_with_thread_id{}), _what(std::forward<Args>(args)...)
76 hilet utc_time_point = time_stamp_utc::make(_time_stamp);
77 hilet sys_time_point = std::chrono::clock_cast<std::chrono::system_clock>(utc_time_point);
78 hilet local_time_point = zone->to_local(sys_time_point);
80 hilet cpu_id = _time_stamp.cpu_id();
81 hilet thread_id = _time_stamp.thread_id();
82 hilet thread_name = get_thread_name(thread_id);
84 if constexpr (to_bool(Level & global_state_type::log_statistics)) {
85 return std::format(
"{} {}({}) {:5} {}\n", local_time_point, thread_name, cpu_id, log_level_name, _what());
87 auto source_filename = std::filesystem::path{
static_cast<std::string_view
>(SourcePath)}.filename().generic_string();
89 "{} {}({}) {:5} {} ({}:{})\n",
102 return std::make_unique<log_message>(*
this);
106 time_stamp_count _time_stamp;
107 delayed_format<Fmt, Values...> _what;
121 template<global_state_type Level, fixed_string SourcePath,
int SourceLine, fixed_string Fmt,
typename... Args>
122 hi_force_inline
void add(Args&&...args)
noexcept
124 static_assert(std::popcount(to_underlying(Level)) == 1);
126 hilet state = global_state.load(std::memory_order::relaxed);
127 if (not to_bool(state & Level)) {
139 std::forward<Args>(args)...);
141 if (to_bool(Level & global_state_type::log_fatal) or not to_bool(state & global_state_type::log_is_running)) {
144 [[unlikely]]
flush();
161 static
bool start_subsystem(global_state_type log_level = global_state_type::log_level_default)
163 set_log_level(log_level);
164 return hi::start_subsystem(global_state_type::log_is_running, log::subsystem_init, log::subsystem_deinit);
172 return hi::stop_subsystem(log::subsystem_deinit);
178 wfree_fifo<detail::log_message_base, 64> _fifo;
179 mutable unfair_mutex _mutex;
189 static inline std::jthread _log_thread;
193 static void log_thread_main(std::stop_token stop_token)
noexcept;
197 static void subsystem_deinit() noexcept;
204 static
bool subsystem_init() noexcept;