mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-12 01:38:37 +12:00
GUI logging improved
logs::listener resurrected rpcs3 version: constexpr
This commit is contained in:
parent
8157e7cac8
commit
0227c03366
14 changed files with 283 additions and 172 deletions
|
@ -627,7 +627,7 @@ void fs::file::xnull() const
|
|||
|
||||
void fs::file::xfail() const
|
||||
{
|
||||
throw fmt::exception("Unexpected fs::error %u", g_tls_error);
|
||||
throw fmt::exception("Unexpected fs::error %s", g_tls_error);
|
||||
}
|
||||
|
||||
bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
|
|
|
@ -463,3 +463,21 @@ namespace fs
|
|||
// Error code returned
|
||||
extern thread_local error g_tls_error;
|
||||
}
|
||||
|
||||
template<>
|
||||
struct unveil<fs::error>
|
||||
{
|
||||
static inline const char* get(fs::error error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case fs::error::ok: return "OK";
|
||||
|
||||
case fs::error::inval: return "Invalid arguments";
|
||||
case fs::error::noent: return "Not found";
|
||||
case fs::error::exist: return "Already exists";
|
||||
|
||||
default: throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "File.h"
|
||||
#include "StrFmt.h"
|
||||
|
||||
#include "rpcs3_version.h"
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
|
||||
|
@ -14,15 +15,6 @@ constexpr DECLARE(bijective<logs::level, const char*>::map);
|
|||
|
||||
namespace logs
|
||||
{
|
||||
struct listener
|
||||
{
|
||||
listener() = default;
|
||||
|
||||
virtual ~listener() = default;
|
||||
|
||||
virtual void log(const channel& ch, level sev, const std::string& text) = 0;
|
||||
};
|
||||
|
||||
class file_writer
|
||||
{
|
||||
// Could be memory-mapped file
|
||||
|
@ -34,10 +26,7 @@ namespace logs
|
|||
virtual ~file_writer() = default;
|
||||
|
||||
// Append raw data
|
||||
void log(const std::string& text);
|
||||
|
||||
// Get current file size (may be used by secondary readers)
|
||||
std::size_t size() const;
|
||||
void log(const char* text, std::size_t size);
|
||||
};
|
||||
|
||||
struct file_listener : public file_writer, public listener
|
||||
|
@ -46,17 +35,19 @@ namespace logs
|
|||
: file_writer(name)
|
||||
, listener()
|
||||
{
|
||||
const std::string& start = fmt::format("\xEF\xBB\xBF" "RPCS3 v%s\n", rpcs3::version.to_string());
|
||||
file_writer::log(start.data(), start.size());
|
||||
}
|
||||
|
||||
// Encode level, current thread name, channel name and write log message
|
||||
virtual void log(const channel& ch, level sev, const std::string& text) override;
|
||||
virtual void log(const message& msg) override;
|
||||
};
|
||||
|
||||
static file_listener& get_logger()
|
||||
static file_listener* get_logger()
|
||||
{
|
||||
// Use magic static
|
||||
static file_listener logger("RPCS3.log");
|
||||
return logger;
|
||||
return &logger;
|
||||
}
|
||||
|
||||
channel GENERAL(nullptr, level::notice);
|
||||
|
@ -69,12 +60,44 @@ namespace logs
|
|||
channel ARMv7("ARMv7");
|
||||
}
|
||||
|
||||
void logs::listener::add(logs::listener* _new)
|
||||
{
|
||||
// Get first (main) listener
|
||||
listener* lis = get_logger();
|
||||
|
||||
// Install new listener at the end of linked list
|
||||
while (lis->m_next || !lis->m_next.compare_and_swap_test(nullptr, _new))
|
||||
{
|
||||
lis = lis->m_next;
|
||||
}
|
||||
}
|
||||
|
||||
void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
get_logger().log(ch, sev, fmt::unsafe_vformat(fmt, args));
|
||||
std::string&& text = fmt::unsafe_vformat(fmt, args);
|
||||
std::string&& prefix = g_tls_log_prefix ? g_tls_log_prefix() : "";
|
||||
va_end(args);
|
||||
|
||||
// Prepare message information
|
||||
message msg;
|
||||
msg.ch = &ch;
|
||||
msg.sev = sev;
|
||||
msg.text = text.data();
|
||||
msg.text_size = text.size();
|
||||
msg.prefix = prefix.data();
|
||||
msg.prefix_size = prefix.size();
|
||||
|
||||
// Get first (main) listener
|
||||
listener* lis = get_logger();
|
||||
|
||||
// Send message to all listeners
|
||||
while (lis)
|
||||
{
|
||||
lis->log(msg);
|
||||
lis = lis->m_next;
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] extern void catch_all_exceptions();
|
||||
|
@ -85,7 +108,7 @@ logs::file_writer::file_writer(const std::string& name)
|
|||
{
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
|
||||
{
|
||||
throw fmt::exception("Can't create log file %s (error %d)", name, fs::g_tls_error);
|
||||
throw fmt::exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
@ -94,54 +117,47 @@ logs::file_writer::file_writer(const std::string& name)
|
|||
}
|
||||
}
|
||||
|
||||
void logs::file_writer::log(const std::string& text)
|
||||
void logs::file_writer::log(const char* text, std::size_t size)
|
||||
{
|
||||
m_file.write(text);
|
||||
m_file.write(text, size);
|
||||
}
|
||||
|
||||
std::size_t logs::file_writer::size() const
|
||||
void logs::file_listener::log(const logs::message& msg)
|
||||
{
|
||||
return m_file.pos();
|
||||
}
|
||||
|
||||
void logs::file_listener::log(const logs::channel& ch, logs::level sev, const std::string& text)
|
||||
{
|
||||
std::string msg; msg.reserve(text.size() + 200);
|
||||
std::string text; text.reserve(msg.text_size + msg.prefix_size + 200);
|
||||
|
||||
// Used character: U+00B7 (Middle Dot)
|
||||
switch (sev)
|
||||
switch (msg.sev)
|
||||
{
|
||||
case level::always: msg = u8"·A "; break;
|
||||
case level::fatal: msg = u8"·F "; break;
|
||||
case level::error: msg = u8"·E "; break;
|
||||
case level::todo: msg = u8"·U "; break;
|
||||
case level::success: msg = u8"·S "; break;
|
||||
case level::warning: msg = u8"·W "; break;
|
||||
case level::notice: msg = u8"·! "; break;
|
||||
case level::trace: msg = u8"·T "; break;
|
||||
case level::always: text = u8"·A "; break;
|
||||
case level::fatal: text = u8"·F "; break;
|
||||
case level::error: text = u8"·E "; break;
|
||||
case level::todo: text = u8"·U "; break;
|
||||
case level::success: text = u8"·S "; break;
|
||||
case level::warning: text = u8"·W "; break;
|
||||
case level::notice: text = u8"·! "; break;
|
||||
case level::trace: text = u8"·T "; break;
|
||||
}
|
||||
|
||||
// TODO: print time?
|
||||
|
||||
if (auto prefix = g_tls_log_prefix)
|
||||
if (msg.prefix_size > 0)
|
||||
{
|
||||
msg += '{';
|
||||
msg += prefix();
|
||||
msg += "} ";
|
||||
text += fmt::format("{%s} ", msg.prefix);
|
||||
}
|
||||
|
||||
if (ch.name)
|
||||
if (msg.ch->name)
|
||||
{
|
||||
msg += ch.name;
|
||||
msg += sev == level::todo ? " TODO: " : ": ";
|
||||
text += msg.ch->name;
|
||||
text += msg.sev == level::todo ? " TODO: " : ": ";
|
||||
}
|
||||
else if (sev == level::todo)
|
||||
else if (msg.sev == level::todo)
|
||||
{
|
||||
msg += "TODO: ";
|
||||
text += "TODO: ";
|
||||
}
|
||||
|
||||
msg += text;
|
||||
msg += '\n';
|
||||
text += msg.text;
|
||||
text += '\n';
|
||||
|
||||
file_writer::log(msg);
|
||||
file_writer::log(text.data(), text.size());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,39 @@ namespace logs
|
|||
trace, // lowest level (usually disabled)
|
||||
};
|
||||
|
||||
struct channel;
|
||||
|
||||
// Message information (temporary data)
|
||||
struct message
|
||||
{
|
||||
const channel* ch;
|
||||
level sev;
|
||||
|
||||
const char* prefix;
|
||||
std::size_t prefix_size;
|
||||
const char* text;
|
||||
std::size_t text_size;
|
||||
};
|
||||
|
||||
class listener
|
||||
{
|
||||
// Next listener (linked list)
|
||||
atomic_t<listener*> m_next{};
|
||||
|
||||
friend struct channel;
|
||||
|
||||
public:
|
||||
constexpr listener() = default;
|
||||
|
||||
virtual ~listener() = default;
|
||||
|
||||
// Process log message
|
||||
virtual void log(const message& msg) = 0;
|
||||
|
||||
// Add new listener
|
||||
static void add(listener*);
|
||||
};
|
||||
|
||||
struct channel
|
||||
{
|
||||
// Channel prefix (added to every log message)
|
||||
|
@ -60,7 +93,6 @@ namespace logs
|
|||
GEN_LOG_METHOD(trace)
|
||||
|
||||
#undef GEN_LOG_METHOD
|
||||
|
||||
private:
|
||||
// Send log message to global logger instance
|
||||
static void broadcast(const channel& ch, level sev, const char* fmt...);
|
||||
|
|
|
@ -14,26 +14,12 @@ namespace utils
|
|||
case version_type::release: return "Release";
|
||||
}
|
||||
|
||||
throw;
|
||||
throw type;
|
||||
}
|
||||
|
||||
version::version(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo)
|
||||
: m_hi(hi)
|
||||
, m_mid(mid)
|
||||
, m_lo(lo)
|
||||
uint version::to_hex() const
|
||||
{
|
||||
}
|
||||
|
||||
version& version::type(version_type type, std::uint8_t type_index)
|
||||
{
|
||||
m_type = type;
|
||||
m_type_index = type_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::uint16_t version::to_hex() const
|
||||
{
|
||||
return (m_hi << 24) | (m_mid << 16) | (m_lo << 8) | ((std::uint8_t(m_type) & 0xf) << 4) | (m_type_index & 0xf);
|
||||
return (m_hi << 24) | (m_mid << 16) | (m_lo << 8) | ((uint(m_type) & 0xf) << 4) | (m_type_index & 0xf);
|
||||
}
|
||||
|
||||
std::string version::to_string() const
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
enum class version_type : std::uint8_t
|
||||
enum class version_type : uint
|
||||
{
|
||||
pre_alpha,
|
||||
alpha,
|
||||
|
@ -17,29 +18,35 @@ namespace utils
|
|||
|
||||
class version
|
||||
{
|
||||
std::uint8_t m_hi;
|
||||
std::uint8_t m_mid;
|
||||
std::uint8_t m_lo;
|
||||
uint m_hi;
|
||||
uint m_mid;
|
||||
uint m_lo;
|
||||
version_type m_type = version_type::release;
|
||||
std::uint8_t m_type_index = 1;
|
||||
std::string m_postfix;
|
||||
uint m_type_index = 1;
|
||||
const char* m_postfix;
|
||||
|
||||
public:
|
||||
version(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo = 0);
|
||||
constexpr version(uint hi, uint mid, uint lo, version_type type, uint type_index, const char* postfix)
|
||||
: m_hi(hi)
|
||||
, m_mid(mid)
|
||||
, m_lo(lo)
|
||||
, m_type(type)
|
||||
, m_type_index(type_index)
|
||||
, m_postfix(postfix)
|
||||
{
|
||||
}
|
||||
|
||||
version& type(version_type type, std::uint8_t type_index = 1);
|
||||
|
||||
std::uint8_t hi() const
|
||||
uint hi() const
|
||||
{
|
||||
return m_hi;
|
||||
}
|
||||
|
||||
std::uint8_t mid() const
|
||||
uint mid() const
|
||||
{
|
||||
return m_mid;
|
||||
}
|
||||
|
||||
std::uint8_t lo() const
|
||||
uint lo() const
|
||||
{
|
||||
return m_lo;
|
||||
}
|
||||
|
@ -54,18 +61,12 @@ namespace utils
|
|||
return m_postfix;
|
||||
}
|
||||
|
||||
version& postfix(const std::string& value)
|
||||
{
|
||||
m_postfix = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::uint8_t type_index() const
|
||||
uint type_index() const
|
||||
{
|
||||
return m_type_index;
|
||||
}
|
||||
|
||||
std::uint16_t to_hex() const;
|
||||
uint to_hex() const;
|
||||
std::string to_string() const;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue