44inline constexpr std::array<std::string_view, 8>
kLevelNames = {
45 "trace",
"dev",
"debug",
"info",
"warn",
"error",
"critical",
"off"};
82 constexpr LogCategory(std::string_view name, std::string_view description) noexcept
83 : name_(name), description_(description) {}
85 constexpr std::string_view GetName()
const {
return name_; }
87 constexpr std::string_view GetDescription()
const {
return description_; }
97 friend class DetailAccess;
99 std::string_view name_;
100 std::string_view description_;
106 std::string description;
122 std::format_args args)
noexcept;
125template <
typename... Args>
126void WriteFormatted(
const LogCategory& category,
Level level, std::format_string<Args...> fmt,
127 Args&&... args)
noexcept {
128 WriteArgs(category, level, fmt.get(), std::make_format_args(args...));
137REX_API void WriteStub(
const LogCategory& category, std::atomic_flag& seen, std::string_view name,
138 std::string_view detail);
141template <
typename... Categories>
142constexpr std::array<
const LogCategory*,
sizeof...(Categories)> BuildTable(
143 const Categories&... categories)
noexcept {
144 return {
static_cast<const LogCategory*
>(&categories)...};
162#define REXLOG_CATEGORY(name, description) \
163 namespace rex::log { \
164 inline constinit ::rex::log::LogCategory name{#name, description}; \
179#define REXLOG_TABLE(table, ...) \
180 namespace rex::log { \
181 inline constexpr auto table = ::rex::log::detail::BuildTable(__VA_ARGS__); \
187template <
size_t Count>
199 const u64 bit = u64{1} << (key % 64);
200 return (words_[key / 64].fetch_or(bit, std::memory_order_relaxed) & bit) == 0;
204 std::array<std::atomic<u64>, (Count + 63) / 64> words_{};
216template <
typename Fn>
219 std::forward<Fn>(fn)();
220 }
catch (
const std::exception& error) {
221 detail::WriteFormatted(category,
Level::kError,
"teardown step failed, {}", error.what());
223 detail::WriteFormatted(category,
Level::kError,
"teardown step failed, unknown exception");
241#define REXLOG_DETAIL_WRITE(cat, level, fmt, ...) \
243 if ((cat).IsEnabled(level)) { \
244 ::rex::log::detail::WriteFormatted((cat), level, fmt __VA_OPT__(, ) __VA_ARGS__); \
262#define REXLOG_CAT_ONCE(cat, level, once, key, fmt, ...) \
264 if ((cat).IsEnabled(level) && (once).IsFirst(key)) { \
265 ::rex::log::detail::WriteFormatted((cat), level, fmt __VA_OPT__(, ) __VA_ARGS__); \
280#define REXLOG_CAT_TRACE(cat, fmt, ...) \
281 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kTrace, fmt __VA_OPT__(, ) __VA_ARGS__)
294#define REXLOG_CAT_DEV(cat, fmt, ...) \
295 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kDev, fmt __VA_OPT__(, ) __VA_ARGS__)
308#define REXLOG_CAT_DEBUG(cat, fmt, ...) \
309 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kDebug, fmt __VA_OPT__(, ) __VA_ARGS__)
322#define REXLOG_CAT_INFO(cat, fmt, ...) \
323 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kInfo, fmt __VA_OPT__(, ) __VA_ARGS__)
336#define REXLOG_CAT_WARN(cat, fmt, ...) \
337 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kWarn, fmt __VA_OPT__(, ) __VA_ARGS__)
350#define REXLOG_CAT_ERROR(cat, fmt, ...) \
351 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kError, fmt __VA_OPT__(, ) __VA_ARGS__)
364#define REXLOG_CAT_CRITICAL(cat, fmt, ...) \
365 REXLOG_DETAIL_WRITE(cat, ::rex::log::Level::kCritical, fmt __VA_OPT__(, ) __VA_ARGS__)
379#define REX_CAT_FAIL(cat, value, fmt, ...) \
381 REXLOG_CAT_ERROR(cat, fmt __VA_OPT__(, ) __VA_ARGS__); \
396#define REX_CAT_FATAL(cat, fmt, ...) \
398 REXLOG_CAT_CRITICAL(cat, fmt __VA_OPT__(, ) __VA_ARGS__); \
399 ::rex::log::Flush(); \
415#define REX_CAT_CHECK(cat, cond, fmt, ...) \
418 REX_CAT_FATAL(cat, "check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
422REXLOG_CATEGORY(core,
"Core library, provider loading, settings and the app lifecycle")
424 "Kernel objects, guest threads, guest memory and modules, and the host threads and "
426REXLOG_CATEGORY(apu,
"APU emulation, XMA decoding and the audio output modules")
428REXLOG_CATEGORY(gpu,
"Xenos emulation, shader translation and the host graphics paths")
449#define REXLOG_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
450#define REXLOG_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
451#define REXLOG_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
452#define REXLOG_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
453#define REXLOG_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
454#define REXLOG_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
455#define REXLOG_CRITICAL(fmt, ...) \
456 REXLOG_CAT_CRITICAL(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
457#define REXLOG_WARN_ONCE(once, key, fmt, ...) \
458 REXLOG_CAT_ONCE(::rex::log::core, ::rex::log::Level::kWarn, once, key, \
459 fmt __VA_OPT__(, ) __VA_ARGS__)
460#define REX_FAIL(value, fmt, ...) \
461 REX_CAT_FAIL(::rex::log::core, value, fmt __VA_OPT__(, ) __VA_ARGS__)
462#define REX_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::core, fmt __VA_OPT__(, ) __VA_ARGS__)
463#define REX_CHECK(cond, fmt, ...) \
466 REX_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
470#define REXSYS_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
471#define REXSYS_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
472#define REXSYS_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
473#define REXSYS_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
474#define REXSYS_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
475#define REXSYS_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
476#define REXSYS_CRITICAL(fmt, ...) \
477 REXLOG_CAT_CRITICAL(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
478#define REXSYS_WARN_ONCE(once, key, fmt, ...) \
479 REXLOG_CAT_ONCE(::rex::log::system, ::rex::log::Level::kWarn, once, key, \
480 fmt __VA_OPT__(, ) __VA_ARGS__)
481#define REXSYS_FAIL(value, fmt, ...) \
482 REX_CAT_FAIL(::rex::log::system, value, fmt __VA_OPT__(, ) __VA_ARGS__)
483#define REXSYS_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::system, fmt __VA_OPT__(, ) __VA_ARGS__)
484#define REXSYS_CHECK(cond, fmt, ...) \
487 REXSYS_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
491#define REXAPU_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
492#define REXAPU_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
493#define REXAPU_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
494#define REXAPU_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
495#define REXAPU_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
496#define REXAPU_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
497#define REXAPU_CRITICAL(fmt, ...) \
498 REXLOG_CAT_CRITICAL(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
499#define REXAPU_WARN_ONCE(once, key, fmt, ...) \
500 REXLOG_CAT_ONCE(::rex::log::apu, ::rex::log::Level::kWarn, once, key, \
501 fmt __VA_OPT__(, ) __VA_ARGS__)
502#define REXAPU_FAIL(value, fmt, ...) \
503 REX_CAT_FAIL(::rex::log::apu, value, fmt __VA_OPT__(, ) __VA_ARGS__)
504#define REXAPU_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::apu, fmt __VA_OPT__(, ) __VA_ARGS__)
505#define REXAPU_CHECK(cond, fmt, ...) \
508 REXAPU_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
512#define REXFS_TRACE(fmt, ...) \
513 REXLOG_CAT_TRACE(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
514#define REXFS_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
515#define REXFS_DEBUG(fmt, ...) \
516 REXLOG_CAT_DEBUG(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
517#define REXFS_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
518#define REXFS_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
519#define REXFS_ERROR(fmt, ...) \
520 REXLOG_CAT_ERROR(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
521#define REXFS_CRITICAL(fmt, ...) \
522 REXLOG_CAT_CRITICAL(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
523#define REXFS_WARN_ONCE(once, key, fmt, ...) \
524 REXLOG_CAT_ONCE(::rex::log::filesystem, ::rex::log::Level::kWarn, once, key, \
525 fmt __VA_OPT__(, ) __VA_ARGS__)
526#define REXFS_FAIL(value, fmt, ...) \
527 REX_CAT_FAIL(::rex::log::filesystem, value, fmt __VA_OPT__(, ) __VA_ARGS__)
528#define REXFS_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::filesystem, fmt __VA_OPT__(, ) __VA_ARGS__)
529#define REXFS_CHECK(cond, fmt, ...) \
532 REXFS_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
536#define REXGPU_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
537#define REXGPU_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
538#define REXGPU_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
539#define REXGPU_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
540#define REXGPU_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
541#define REXGPU_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
542#define REXGPU_CRITICAL(fmt, ...) \
543 REXLOG_CAT_CRITICAL(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
544#define REXGPU_WARN_ONCE(once, key, fmt, ...) \
545 REXLOG_CAT_ONCE(::rex::log::gpu, ::rex::log::Level::kWarn, once, key, \
546 fmt __VA_OPT__(, ) __VA_ARGS__)
547#define REXGPU_FAIL(value, fmt, ...) \
548 REX_CAT_FAIL(::rex::log::gpu, value, fmt __VA_OPT__(, ) __VA_ARGS__)
549#define REXGPU_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::gpu, fmt __VA_OPT__(, ) __VA_ARGS__)
550#define REXGPU_CHECK(cond, fmt, ...) \
553 REXGPU_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
557#define REXHID_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
558#define REXHID_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
559#define REXHID_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
560#define REXHID_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
561#define REXHID_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
562#define REXHID_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
563#define REXHID_CRITICAL(fmt, ...) \
564 REXLOG_CAT_CRITICAL(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
565#define REXHID_WARN_ONCE(once, key, fmt, ...) \
566 REXLOG_CAT_ONCE(::rex::log::hid, ::rex::log::Level::kWarn, once, key, \
567 fmt __VA_OPT__(, ) __VA_ARGS__)
568#define REXHID_FAIL(value, fmt, ...) \
569 REX_CAT_FAIL(::rex::log::hid, value, fmt __VA_OPT__(, ) __VA_ARGS__)
570#define REXHID_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::hid, fmt __VA_OPT__(, ) __VA_ARGS__)
571#define REXHID_CHECK(cond, fmt, ...) \
574 REXHID_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
578#define REXCPU_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
579#define REXCPU_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
580#define REXCPU_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
581#define REXCPU_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
582#define REXCPU_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
583#define REXCPU_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
584#define REXCPU_CRITICAL(fmt, ...) \
585 REXLOG_CAT_CRITICAL(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
586#define REXCPU_WARN_ONCE(once, key, fmt, ...) \
587 REXLOG_CAT_ONCE(::rex::log::cpu, ::rex::log::Level::kWarn, once, key, \
588 fmt __VA_OPT__(, ) __VA_ARGS__)
589#define REXCPU_FAIL(value, fmt, ...) \
590 REX_CAT_FAIL(::rex::log::cpu, value, fmt __VA_OPT__(, ) __VA_ARGS__)
591#define REXCPU_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::cpu, fmt __VA_OPT__(, ) __VA_ARGS__)
592#define REXCPU_CHECK(cond, fmt, ...) \
595 REXCPU_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
599#define REXUI_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
600#define REXUI_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
601#define REXUI_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
602#define REXUI_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
603#define REXUI_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
604#define REXUI_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
605#define REXUI_CRITICAL(fmt, ...) REXLOG_CAT_CRITICAL(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
606#define REXUI_WARN_ONCE(once, key, fmt, ...) \
607 REXLOG_CAT_ONCE(::rex::log::ui, ::rex::log::Level::kWarn, once, key, \
608 fmt __VA_OPT__(, ) __VA_ARGS__)
609#define REXUI_FAIL(value, fmt, ...) \
610 REX_CAT_FAIL(::rex::log::ui, value, fmt __VA_OPT__(, ) __VA_ARGS__)
611#define REXUI_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::ui, fmt __VA_OPT__(, ) __VA_ARGS__)
612#define REXUI_CHECK(cond, fmt, ...) \
615 REXUI_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
619#define REXCON_TRACE(fmt, ...) REXLOG_CAT_TRACE(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
620#define REXCON_DEV(fmt, ...) REXLOG_CAT_DEV(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
621#define REXCON_DEBUG(fmt, ...) REXLOG_CAT_DEBUG(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
622#define REXCON_INFO(fmt, ...) REXLOG_CAT_INFO(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
623#define REXCON_WARN(fmt, ...) REXLOG_CAT_WARN(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
624#define REXCON_ERROR(fmt, ...) REXLOG_CAT_ERROR(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
625#define REXCON_CRITICAL(fmt, ...) \
626 REXLOG_CAT_CRITICAL(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
627#define REXCON_WARN_ONCE(once, key, fmt, ...) \
628 REXLOG_CAT_ONCE(::rex::log::console, ::rex::log::Level::kWarn, once, key, \
629 fmt __VA_OPT__(, ) __VA_ARGS__)
630#define REXCON_FAIL(value, fmt, ...) \
631 REX_CAT_FAIL(::rex::log::console, value, fmt __VA_OPT__(, ) __VA_ARGS__)
632#define REXCON_FATAL(fmt, ...) REX_CAT_FATAL(::rex::log::console, fmt __VA_OPT__(, ) __VA_ARGS__)
633#define REXCON_CHECK(cond, fmt, ...) \
636 REXCON_FATAL("check failed: " #cond ". " fmt __VA_OPT__(, ) __VA_ARGS__); \
Definition log_category.h:71
static constexpr u16 kUnresolved
Definition log_category.h:74
bool IsEnabled(Level level) const
constexpr LogCategory(std::string_view name, std::string_view description) noexcept
Definition log_category.h:82
Definition log_category.h:188
bool IsFirst(size_t key) noexcept
Definition log_category.h:195
#define REXLOG_CATEGORY(name, description)
Definition log_category.h:162
Definition log_category.h:29
Result< Level > ParseLevel(std::string_view text)
void NoThrow(const LogCategory &category, Fn &&fn) noexcept
Definition log_category.h:217
constexpr size_t kMessageLevelCount
Definition log_category.h:48
Level
Definition log_category.h:32
@ kInfo
Definition log_category.h:36
@ kCritical
Definition log_category.h:39
@ kWarn
Definition log_category.h:37
@ kDev
Definition log_category.h:34
@ kOff
Definition log_category.h:40
@ kError
Definition log_category.h:38
@ kTrace
Definition log_category.h:33
constexpr std::array< std::string_view, 8 > kLevelNames
Definition log_category.h:44
std::string_view LevelName(Level level)
std::expected< T, Error > Result
Definition result.h:98
Definition log_category.h:104
Level level
Definition log_category.h:107
std::optional< Level > explicit_level
Definition log_category.h:109
bool registered
Definition log_category.h:110
Integer types, byte order wrappers and size literals.
Move only function, const propagating pointer and scope guard.