2014-06-17 15:44:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
2016-02-01 21:55:43 +00:00
|
|
|
#include "types.h"
|
2016-08-03 20:51:05 +00:00
|
|
|
#include "StrFmt.h"
|
2020-02-01 07:30:03 +00:00
|
|
|
#include "util/atomic.hpp"
|
|
|
|
#include <atomic>
|
2014-06-17 15:44:03 +00:00
|
|
|
|
2016-05-13 14:01:48 +00:00
|
|
|
namespace logs
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2016-01-12 21:57:16 +00:00
|
|
|
enum class level : uint
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2017-05-13 18:30:37 +00:00
|
|
|
always, // Highest log severity (unused, cannot be disabled)
|
2016-01-12 21:57:16 +00:00
|
|
|
fatal,
|
|
|
|
error,
|
|
|
|
todo,
|
|
|
|
success,
|
|
|
|
warning,
|
|
|
|
notice,
|
2017-05-13 18:30:37 +00:00
|
|
|
trace, // Lowest severity (usually disabled)
|
2014-06-17 15:44:03 +00:00
|
|
|
};
|
|
|
|
|
2016-07-20 22:00:31 +00:00
|
|
|
struct channel;
|
|
|
|
|
2018-09-15 21:36:20 +00:00
|
|
|
// Message information
|
2016-07-20 22:00:31 +00:00
|
|
|
struct message
|
|
|
|
{
|
2017-05-13 18:30:37 +00:00
|
|
|
channel* ch;
|
2016-07-20 22:00:31 +00:00
|
|
|
level sev;
|
|
|
|
|
2018-09-15 21:36:20 +00:00
|
|
|
private:
|
2016-08-05 16:49:45 +00:00
|
|
|
// Send log message to global logger instance
|
2018-09-19 11:14:04 +00:00
|
|
|
void broadcast(const char*, const fmt_type_info*, ...) const;
|
2018-09-15 21:36:20 +00:00
|
|
|
|
|
|
|
friend struct channel;
|
2016-07-20 22:00:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class listener
|
|
|
|
{
|
|
|
|
// Next listener (linked list)
|
|
|
|
atomic_t<listener*> m_next{};
|
|
|
|
|
2016-08-05 16:49:45 +00:00
|
|
|
friend struct message;
|
2016-07-20 22:00:31 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
constexpr listener() = default;
|
|
|
|
|
2017-01-24 23:22:19 +00:00
|
|
|
virtual ~listener();
|
2016-07-20 22:00:31 +00:00
|
|
|
|
|
|
|
// Process log message
|
2017-02-22 09:52:03 +00:00
|
|
|
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) = 0;
|
2016-07-20 22:00:31 +00:00
|
|
|
|
|
|
|
// Add new listener
|
|
|
|
static void add(listener*);
|
|
|
|
};
|
|
|
|
|
2016-01-12 21:57:16 +00:00
|
|
|
struct channel
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2016-02-01 21:55:43 +00:00
|
|
|
// Channel prefix (added to every log message)
|
|
|
|
const char* const name;
|
2016-01-12 21:57:16 +00:00
|
|
|
|
|
|
|
// The lowest logging level enabled for this channel (used for early filtering)
|
2020-02-01 07:30:03 +00:00
|
|
|
std::atomic<level> enabled;
|
2016-01-12 21:57:16 +00:00
|
|
|
|
2020-02-02 11:09:20 +00:00
|
|
|
// Initialize channel
|
|
|
|
constexpr channel(const char* name) noexcept
|
|
|
|
: name(name)
|
|
|
|
, enabled(level::notice)
|
|
|
|
{
|
|
|
|
}
|
2016-01-12 21:57:16 +00:00
|
|
|
|
|
|
|
#define GEN_LOG_METHOD(_sev)\
|
2018-09-15 21:36:20 +00:00
|
|
|
const message msg_##_sev{this, level::_sev};\
|
2019-10-08 23:14:52 +00:00
|
|
|
template <std::size_t N, typename... Args>\
|
|
|
|
void _sev(const char(&fmt)[N], const Args&... args)\
|
2016-01-12 21:57:16 +00:00
|
|
|
{\
|
2020-02-01 07:30:03 +00:00
|
|
|
if (UNLIKELY(level::_sev <= enabled.load(std::memory_order_relaxed)))\
|
2018-09-15 21:36:20 +00:00
|
|
|
{\
|
|
|
|
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};\
|
2018-09-19 11:14:04 +00:00
|
|
|
msg_##_sev.broadcast(fmt, type_list, u64{fmt_unveil<Args>::get(args)}...);\
|
2018-09-15 21:36:20 +00:00
|
|
|
}\
|
2016-01-12 21:57:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GEN_LOG_METHOD(fatal)
|
|
|
|
GEN_LOG_METHOD(error)
|
|
|
|
GEN_LOG_METHOD(todo)
|
|
|
|
GEN_LOG_METHOD(success)
|
|
|
|
GEN_LOG_METHOD(warning)
|
|
|
|
GEN_LOG_METHOD(notice)
|
|
|
|
GEN_LOG_METHOD(trace)
|
|
|
|
|
|
|
|
#undef GEN_LOG_METHOD
|
2014-06-17 15:44:03 +00:00
|
|
|
};
|
|
|
|
|
2020-02-02 11:09:20 +00:00
|
|
|
struct registerer
|
|
|
|
{
|
|
|
|
registerer(channel& _ch);
|
|
|
|
};
|
|
|
|
|
2017-05-13 18:30:37 +00:00
|
|
|
// Log level control: set all channels to level::notice
|
|
|
|
void reset();
|
|
|
|
|
2020-01-31 12:18:25 +00:00
|
|
|
// Log level control: set all channels to level::always
|
|
|
|
void silence();
|
|
|
|
|
2017-05-13 18:30:37 +00:00
|
|
|
// Log level control: register channel if necessary, set channel level
|
|
|
|
void set_level(const std::string&, level);
|
2020-01-31 09:09:34 +00:00
|
|
|
|
|
|
|
// Log level control: get channel level
|
|
|
|
level get_level(const std::string&);
|
2020-01-31 12:04:40 +00:00
|
|
|
|
|
|
|
// Get all registered log channels
|
|
|
|
std::vector<std::string> get_channels();
|
2020-02-01 07:43:43 +00:00
|
|
|
|
|
|
|
// Helper: no additional name specified
|
|
|
|
constexpr const char* make_channel_name(const char* name)
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper: special channel name specified
|
|
|
|
constexpr const char* make_channel_name(const char*, const char* name, ...)
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
2014-06-27 13:26:46 +00:00
|
|
|
}
|
2016-01-12 21:57:16 +00:00
|
|
|
|
2020-02-02 11:09:20 +00:00
|
|
|
#if __cpp_constinit >= 201907
|
|
|
|
#define LOG_CONSTINIT constinit
|
|
|
|
#else
|
|
|
|
#define LOG_CONSTINIT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define LOG_CHANNEL(ch, ...) LOG_CONSTINIT inline ::logs::channel ch(::logs::make_channel_name(#ch, ##__VA_ARGS__)); \
|
|
|
|
namespace logs { inline ::logs::registerer reg_##ch{ch}; }
|
2018-08-25 12:39:00 +00:00
|
|
|
|
2020-02-01 08:07:25 +00:00
|
|
|
LOG_CHANNEL(rsx_log, "RSX");
|