Log actually not always compact (#4035)

This commit is contained in:
Niram7777 2026-02-14 20:31:19 +00:00 committed by GitHub
parent e0850d5cfc
commit 8d4cbdbca9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 84 additions and 44 deletions

View File

@ -73,6 +73,8 @@ You can configure the emulator by editing the `config.toml` file found in the `u
- Examples:
- If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages.
- If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Critical Render.Vulkan:Info`
- `isIdenticalLogGrouped`: Group same logs in one line with a counter (`true`/`false`)
- By default, the emulator will not rewrite the same line, and instead add a counter.
- `Fullscreen`: Display the game in a full screen borderless window.

View File

@ -141,6 +141,7 @@ static ConfigEntry<bool> isTrophyPopupDisabled(false);
static ConfigEntry<double> trophyNotificationDuration(6.0);
static ConfigEntry<string> logFilter("");
static ConfigEntry<string> logType("sync");
static ConfigEntry<bool> isIdenticalLogGrouped(true);
static ConfigEntry<string> userName("shadPS4");
static ConfigEntry<bool> isShowSplash(false);
static ConfigEntry<string> isSideTrophy("right");
@ -395,6 +396,10 @@ string getLogType() {
return logType.get();
}
bool groupIdenticalLogs() {
return isIdenticalLogGrouped.get();
}
string getUserName() {
return userName.get();
}
@ -694,6 +699,10 @@ void setLogType(const string& type, bool is_game_specific) {
logType.set(type, is_game_specific);
}
void setIdenticalLogGrouped(bool enable, bool is_game_specific) {
isIdenticalLogGrouped.set(enable, is_game_specific);
}
void setLogFilter(const string& type, bool is_game_specific) {
logFilter.set(type, is_game_specific);
}
@ -893,6 +902,7 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", enableDiscordRPC);
logFilter.setFromToml(general, "logFilter", is_game_specific);
logType.setFromToml(general, "logType", is_game_specific);
isIdenticalLogGrouped.setFromToml(general, "isIdenticalLogGrouped", is_game_specific);
userName.setFromToml(general, "userName", is_game_specific);
isShowSplash.setFromToml(general, "showSplash", is_game_specific);
isSideTrophy.setFromToml(general, "sideTrophy", is_game_specific);
@ -1081,6 +1091,7 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
is_game_specific);
logFilter.setTomlValue(data, "General", "logFilter", is_game_specific);
logType.setTomlValue(data, "General", "logType", is_game_specific);
isIdenticalLogGrouped.setTomlValue(data, "General", "isIdenticalLogGrouped", is_game_specific);
userName.setTomlValue(data, "General", "userName", is_game_specific);
isShowSplash.setTomlValue(data, "General", "showSplash", is_game_specific);
isSideTrophy.setTomlValue(data, "General", "sideTrophy", is_game_specific);
@ -1224,6 +1235,7 @@ void setDefaultValues(bool is_game_specific) {
trophyNotificationDuration.set(6.0, is_game_specific);
logFilter.set("", is_game_specific);
logType.set("sync", is_game_specific);
isIdenticalLogGrouped.set("isIdenticalLogGrouped", is_game_specific);
userName.set("shadPS4", is_game_specific);
isShowSplash.set(false, is_game_specific);
isSideTrophy.set("right", is_game_specific);

View File

@ -101,6 +101,8 @@ void setPipelineCacheEnabled(bool enable, bool is_game_specific = false);
void setPipelineCacheArchived(bool enable, bool is_game_specific = false);
std::string getLogType();
void setLogType(const std::string& type, bool is_game_specific = false);
bool groupIdenticalLogs();
void setGroupIdenticalLogs(bool enable, bool is_game_specific = false);
std::string getLogFilter();
void setLogFilter(const std::string& type, bool is_game_specific = false);
double getTrophyNotificationDuration();

View File

@ -209,41 +209,62 @@ public:
}
}
std::unique_lock entry_loc(_mutex);
if (_last_entry.message == message) {
++_last_entry.counter;
return;
}
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::steady_clock;
this->_last_entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
if (Config::groupIdenticalLogs()) {
std::unique_lock entry_loc(_mutex);
if (_last_entry.message == message) {
++_last_entry.counter;
return;
}
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
this->_last_entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
} else {
const Entry entry = {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_num,
.function = function,
.message = message,
.thread = Common::GetCurrentThreadName(),
.counter = 1,
};
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(entry);
} else {
ForEachBackend([&entry](auto& backend) { backend.Write(entry); });
std::fflush(stdout);
}
}
}
private:
@ -275,21 +296,23 @@ private:
}
void StopBackendThread() {
// log last message
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
if (Config::groupIdenticalLogs()) {
// log last message
if (_last_entry.counter >= 2) {
_last_entry.message += " x" + std::to_string(_last_entry.counter);
}
}
this->_last_entry = {};
if (_last_entry.counter >= 1) {
if (Config::getLogType() == "async") {
message_queue.EmplaceWait(_last_entry);
} else {
ForEachBackend([this](auto& backend) { backend.Write(this->_last_entry); });
std::fflush(stdout);
}
}
this->_last_entry = {};
}
backend_thread.request_stop();
if (backend_thread.joinable()) {

View File

@ -239,6 +239,7 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
LOG_INFO(Config, "Game-specific config exists: {}", has_game_config);
LOG_INFO(Config, "General LogType: {}", Config::getLogType());
LOG_INFO(Config, "General isIdenticalLogGrouped: {}", Config::groupIdenticalLogs());
LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole());
LOG_INFO(Config, "General isDevKit: {}", Config::isDevKitConsole());
LOG_INFO(Config, "General isConnectedToNetwork: {}", Config::getIsConnectedToNetwork());