2020-11-29 13:03:50 +01:00
|
|
|
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
|
2014-06-17 17:44:03 +02:00
|
|
|
|
2020-03-28 15:28:23 +01:00
|
|
|
#include <map>
|
2020-03-06 20:29:16 +01:00
|
|
|
#include <memory>
|
2020-03-07 10:29:23 +01:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <initializer_list>
|
2020-12-06 10:10:00 +01:00
|
|
|
#include "util/atomic.hpp"
|
2020-03-07 10:29:23 +01:00
|
|
|
#include "Utilities/StrFmt.h"
|
2014-06-17 17:44:03 +02:00
|
|
|
|
2016-05-13 16:01:48 +02:00
|
|
|
namespace logs
|
2014-06-17 17:44:03 +02:00
|
|
|
{
|
2021-05-19 13:30:39 +02:00
|
|
|
enum class level : unsigned char
|
2014-06-17 17:44:03 +02:00
|
|
|
{
|
2021-05-19 13:30:39 +02:00
|
|
|
always = 0, // Highest log severity (cannot be disabled)
|
|
|
|
|
fatal = 1,
|
|
|
|
|
error = 2,
|
|
|
|
|
todo = 3,
|
|
|
|
|
success = 4,
|
|
|
|
|
warning = 5,
|
|
|
|
|
notice = 6,
|
|
|
|
|
trace = 7, // Lowest severity (usually disabled)
|
2014-06-17 17:44:03 +02:00
|
|
|
};
|
|
|
|
|
|
2016-07-21 00:00:31 +02:00
|
|
|
struct channel;
|
|
|
|
|
|
2018-09-15 23:36:20 +02:00
|
|
|
// Message information
|
2016-07-21 00:00:31 +02:00
|
|
|
struct message
|
|
|
|
|
{
|
2021-05-19 13:30:39 +02:00
|
|
|
// Default constructor
|
|
|
|
|
consteval message() = default;
|
|
|
|
|
|
|
|
|
|
// Cannot be moved because it relies on its location
|
|
|
|
|
message(const message&) = delete;
|
|
|
|
|
|
|
|
|
|
message& operator =(const message&) = delete;
|
|
|
|
|
|
|
|
|
|
// Send log message to the given channel with severity
|
|
|
|
|
template <typename... Args>
|
|
|
|
|
void operator()(const const_str& fmt, const Args&... args) const;
|
|
|
|
|
|
|
|
|
|
operator level() const
|
|
|
|
|
{
|
|
|
|
|
return level(reinterpret_cast<uptr>(this) & 7);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const channel* operator->() const
|
|
|
|
|
{
|
|
|
|
|
return reinterpret_cast<const channel*>(reinterpret_cast<uptr>(this) & -16);
|
|
|
|
|
}
|
2016-07-21 00:00:31 +02:00
|
|
|
|
2018-09-15 23:36:20 +02:00
|
|
|
private:
|
2016-08-05 18:49:45 +02:00
|
|
|
// Send log message to global logger instance
|
2018-09-19 13:14:04 +02:00
|
|
|
void broadcast(const char*, const fmt_type_info*, ...) const;
|
2018-09-15 23:36:20 +02:00
|
|
|
|
|
|
|
|
friend struct channel;
|
2016-07-21 00:00:31 +02:00
|
|
|
};
|
|
|
|
|
|
2020-03-06 20:29:16 +01:00
|
|
|
struct stored_message
|
|
|
|
|
{
|
2021-05-19 13:30:39 +02:00
|
|
|
const message& m;
|
2020-03-06 20:29:16 +01:00
|
|
|
u64 stamp;
|
|
|
|
|
std::string prefix;
|
|
|
|
|
std::string text;
|
|
|
|
|
};
|
|
|
|
|
|
2016-07-21 00:00:31 +02:00
|
|
|
class listener
|
|
|
|
|
{
|
|
|
|
|
// Next listener (linked list)
|
2020-12-06 10:10:00 +01:00
|
|
|
atomic_t<listener*> m_next{};
|
2016-07-21 00:00:31 +02:00
|
|
|
|
2016-08-05 18:49:45 +02:00
|
|
|
friend struct message;
|
2016-07-21 00:00:31 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
constexpr listener() = default;
|
|
|
|
|
|
2017-01-25 00:22:19 +01:00
|
|
|
virtual ~listener();
|
2016-07-21 00:00:31 +02:00
|
|
|
|
|
|
|
|
// Process log message
|
2017-02-22 10:52:03 +01:00
|
|
|
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) = 0;
|
2016-07-21 00:00:31 +02:00
|
|
|
|
|
|
|
|
// Add new listener
|
|
|
|
|
static void add(listener*);
|
2020-03-06 20:29:16 +01:00
|
|
|
|
|
|
|
|
// Special purpose
|
|
|
|
|
void broadcast(const stored_message&) const;
|
2016-07-21 00:00:31 +02:00
|
|
|
};
|
|
|
|
|
|
2021-05-19 13:30:39 +02:00
|
|
|
struct alignas(16) channel : private message
|
2014-06-17 17:44:03 +02:00
|
|
|
{
|
2016-02-01 22:55:43 +01:00
|
|
|
// Channel prefix (added to every log message)
|
|
|
|
|
const char* const name;
|
2016-01-12 22:57:16 +01:00
|
|
|
|
|
|
|
|
// The lowest logging level enabled for this channel (used for early filtering)
|
2020-12-06 10:10:00 +01:00
|
|
|
atomic_t<level> enabled;
|
2016-01-12 22:57:16 +01:00
|
|
|
|
2020-02-02 12:09:20 +01:00
|
|
|
// Initialize channel
|
2021-05-19 13:30:39 +02:00
|
|
|
consteval channel(const char* name) noexcept
|
|
|
|
|
: message{}
|
|
|
|
|
, name(name)
|
2020-02-02 12:09:20 +01:00
|
|
|
, enabled(level::notice)
|
|
|
|
|
{
|
|
|
|
|
}
|
2016-01-12 22:57:16 +01:00
|
|
|
|
2021-05-19 13:30:39 +02:00
|
|
|
// Special access to "always visible" channel which shouldn't be used
|
|
|
|
|
const message& always() const
|
|
|
|
|
{
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-12 22:57:16 +01:00
|
|
|
#define GEN_LOG_METHOD(_sev)\
|
2021-05-19 13:30:39 +02:00
|
|
|
const message _sev{};\
|
|
|
|
|
|
2016-01-12 22:57:16 +01: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 17:44:03 +02:00
|
|
|
};
|
|
|
|
|
|
2021-05-19 13:30:39 +02:00
|
|
|
template <typename... Args>
|
|
|
|
|
FORCE_INLINE SAFE_BUFFERS(void) message::operator()(const const_str& fmt, const Args&... args) const
|
|
|
|
|
{
|
|
|
|
|
if (*this < (*this)->enabled) [[unlikely]]
|
|
|
|
|
{
|
|
|
|
|
if constexpr (sizeof...(Args) > 0)
|
|
|
|
|
{
|
|
|
|
|
broadcast(fmt, fmt::type_info_v<Args...>, u64{fmt_unveil<Args>::get(args)}...);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
broadcast(fmt, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-02 12:09:20 +01:00
|
|
|
struct registerer
|
|
|
|
|
{
|
|
|
|
|
registerer(channel& _ch);
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-13 20:30:37 +02:00
|
|
|
// Log level control: set all channels to level::notice
|
|
|
|
|
void reset();
|
|
|
|
|
|
2020-01-31 13:18:25 +01:00
|
|
|
// Log level control: set all channels to level::always
|
|
|
|
|
void silence();
|
|
|
|
|
|
2017-05-13 20:30:37 +02:00
|
|
|
// Log level control: register channel if necessary, set channel level
|
|
|
|
|
void set_level(const std::string&, level);
|
2020-01-31 10:09:34 +01:00
|
|
|
|
|
|
|
|
// Log level control: get channel level
|
|
|
|
|
level get_level(const std::string&);
|
2020-01-31 13:04:40 +01:00
|
|
|
|
2020-03-28 15:28:23 +01:00
|
|
|
// Log level control: set specific channels to level::fatal
|
|
|
|
|
void set_channel_levels(const std::map<std::string, logs::level>& map);
|
|
|
|
|
|
2020-01-31 13:04:40 +01:00
|
|
|
// Get all registered log channels
|
|
|
|
|
std::vector<std::string> get_channels();
|
2020-02-01 08:43:43 +01:00
|
|
|
|
|
|
|
|
// Helper: no additional name specified
|
2021-04-29 19:54:17 +02:00
|
|
|
consteval const char* make_channel_name(const char* name, const char* alt = nullptr)
|
2020-02-01 08:43:43 +01:00
|
|
|
{
|
2021-04-29 19:54:17 +02:00
|
|
|
return alt ? alt : name;
|
2020-02-01 08:43:43 +01:00
|
|
|
}
|
2020-03-06 20:29:16 +01:00
|
|
|
|
|
|
|
|
// Called in main()
|
|
|
|
|
std::unique_ptr<logs::listener> make_file_listener(const std::string& path, u64 max_size);
|
|
|
|
|
|
|
|
|
|
// Called in main()
|
|
|
|
|
void set_init(std::initializer_list<stored_message>);
|
2014-06-27 15:26:46 +02:00
|
|
|
}
|
2016-01-12 22:57:16 +01:00
|
|
|
|
2020-02-02 12:09:20 +01: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 14:39:00 +02:00
|
|
|
|
2020-02-01 09:07:25 +01:00
|
|
|
LOG_CHANNEL(rsx_log, "RSX");
|