rpcs3/Utilities/Log.h

121 lines
2.8 KiB
C
Raw Normal View History

#pragma once
2016-02-01 21:55:43 +00:00
#include "types.h"
#include "util/atomic.hpp"
#include "StrFmt.h"
2017-05-13 18:30:37 +00:00
#include <climits>
2016-05-13 14:01:48 +00:00
namespace logs
{
enum class level : uint
{
2017-05-13 18:30:37 +00:00
always, // Highest log severity (unused, cannot be disabled)
fatal,
error,
todo,
success,
warning,
notice,
2017-05-13 18:30:37 +00:00
trace, // Lowest severity (usually disabled)
};
struct channel;
// Message information
struct message
{
2017-05-13 18:30:37 +00:00
channel* ch;
level sev;
private:
2016-08-05 16:49:45 +00:00
// Send log message to global logger instance
void broadcast(const char*, const fmt_type_info*, ...) const;
friend struct channel;
};
class listener
{
// Next listener (linked list)
atomic_t<listener*> m_next{};
2016-08-05 16:49:45 +00:00
friend struct message;
public:
constexpr listener() = default;
2017-01-24 23:22:19 +00:00
virtual ~listener();
// 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;
// Add new listener
static void add(listener*);
};
struct channel
{
2016-02-01 21:55:43 +00:00
// Channel prefix (added to every log message)
const char* const name;
// The lowest logging level enabled for this channel (used for early filtering)
2016-02-01 21:55:43 +00:00
atomic_t<level> enabled;
// Initialize and register channel
channel(const char* name);
#define GEN_LOG_METHOD(_sev)\
const message msg_##_sev{this, level::_sev};\
template <std::size_t N, typename... Args>\
void _sev(const char(&fmt)[N], const Args&... args)\
{\
if (UNLIKELY(level::_sev <= enabled))\
{\
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};\
msg_##_sev.broadcast(fmt, type_list, u64{fmt_unveil<Args>::get(args)}...);\
}\
}
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
};
2017-05-13 18:30:37 +00:00
// Log level control: set all channels to level::notice
void reset();
// Log level control: register channel if necessary, set channel level
void set_level(const std::string&, level);
}
#define LOG_CHANNEL(ch, ...) inline ::logs::channel ch(#ch, ##__VA_ARGS__)
// Legacy:
namespace logs
{
/* Small set of predefined channels */
inline channel GENERAL("");
inline channel LOADER("LDR");
inline channel MEMORY("MEM");
LOG_CHANNEL(RSX);
LOG_CHANNEL(HLE);
LOG_CHANNEL(PPU);
LOG_CHANNEL(SPU);
}
2016-08-14 21:04:42 +00:00
#define LOG_SUCCESS(ch, fmt, ...) logs::ch.success("" fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) logs::ch.notice ("" fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) logs::ch.warning("" fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) logs::ch.error ("" fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) logs::ch.todo ("" fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) logs::ch.trace ("" fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) logs::ch.fatal ("" fmt, ##__VA_ARGS__)