diff --git a/Common/ConsoleListener.cpp b/Common/ConsoleListener.cpp index 34491ec49f..b5285e1f25 100644 --- a/Common/ConsoleListener.cpp +++ b/Common/ConsoleListener.cpp @@ -600,7 +600,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool void ConsoleListener::Log(const LogMessage &msg) { char Text[2048]; - snprintf(Text, sizeof(Text), "%s %s", msg.header, msg.msg.c_str()); + snprintf(Text, sizeof(Text), "%s %s %s", msg.timestamp, msg.header, msg.msg.c_str()); Text[sizeof(Text) - 2] = '\n'; Text[sizeof(Text) - 1] = '\0'; diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp index c138f34533..65545b1fc0 100644 --- a/Common/LogManager.cpp +++ b/Common/LogManager.cpp @@ -225,22 +225,17 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const if (fileshort != file) file = fileshort + 1; } - - char formattedTime[13]; std::lock_guard lk(log_lock_); - Common::Timer::GetTimeFormatted(formattedTime); + Common::Timer::GetTimeFormatted(message.timestamp); - size_t prefixLen; if (hleCurrentThreadName) { - prefixLen = snprintf(message.header, sizeof(message.header), "%s %-12.12s %c[%s]: %s:%d", - formattedTime, + snprintf(message.header, sizeof(message.header), "%-12.12s %c[%s]: %s:%d", hleCurrentThreadName, level_to_char[(int)level], log.m_shortName, file, line); } else { - prefixLen = snprintf(message.header, sizeof(message.header), "%s %s:%d %c[%s]:", - formattedTime, + snprintf(message.header, sizeof(message.header), "%s:%d %c[%s]:", file, line, level_to_char[(int)level], log.m_shortName); } @@ -250,15 +245,14 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const va_copy(args_copy, args); size_t neededBytes = vsnprintf(msgBuf, sizeof(msgBuf), format, args); + message.msg.resize(neededBytes + 1); if (neededBytes > sizeof(msgBuf)) { // Needed more space? Re-run vsnprintf. - message.msg.resize(neededBytes + 1); vsnprintf(&message.msg[0], neededBytes + 1, format, args_copy); } else { - message.msg.resize(neededBytes + 1); memcpy(&message.msg[0], msgBuf, neededBytes); } - message.msg[message.msg.size() - 1] = '\n'; + message.msg[neededBytes] = '\n'; va_end(args_copy); std::lock_guard listeners_lock(listeners_lock_); @@ -313,7 +307,7 @@ void FileLogListener::Log(const LogMessage &message) { return; std::lock_guard lk(m_log_lock); - m_logfile << message.header << " " << message.msg << std::flush; + m_logfile << message.timestamp << " " << message.header << " " << message.msg << std::flush; } void OutputDebugStringLogListener::Log(const LogMessage &message) { diff --git a/Common/LogManager.h b/Common/LogManager.h index 3a778ba11c..1e8e39547d 100644 --- a/Common/LogManager.h +++ b/Common/LogManager.h @@ -34,7 +34,8 @@ extern const char *hleCurrentThreadName; // Struct that listeners can output how they want. For example, on Android we don't want to add // timestamp or write the level as a string, those already exist. struct LogMessage { - char header[64]; // timestamp and the other stuff in front... + char timestamp[16]; + char header[64]; // Filename/thread/etc. in front. LogTypes::LOG_LEVELS level; const char *log; std::string msg; // The actual log message. diff --git a/Core/Debugger/WebSocket/LogBroadcaster.cpp b/Core/Debugger/WebSocket/LogBroadcaster.cpp index 2474294e0a..07070be7b0 100644 --- a/Core/Debugger/WebSocket/LogBroadcaster.cpp +++ b/Core/Debugger/WebSocket/LogBroadcaster.cpp @@ -86,27 +86,33 @@ LogBroadcaster::~LogBroadcaster() { } struct DebuggerLogEvent { - std::string header; - std::string message; - int level; - const char *channel; + const LogMessage &l; operator std::string() { JsonWriter j; j.begin(); j.writeString("event", "log"); - j.writeString("header", header); - j.writeString("message", message); - j.writeInt("level", level); - j.writeString("channel", channel); + j.writeString("timestamp", l.timestamp); + j.writeString("header", l.header); + j.writeString("message", l.msg); + j.writeInt("level", l.level); + j.writeString("channel", l.log); j.end(); return j.str(); } }; +// Log message (log) +// +// Sent unexpectedly with these properties: +// - timestamp: string timestamp of event. +// - header: string header information about the event (including file/line.) +// - message: actual log message as a string. +// - level: number severity level (1 = highest.) +// - channel: string describing log channel / grouping. void LogBroadcaster::Broadcast(net::WebSocketServer *ws) { auto messages = listener_->GetMessages(); for (auto msg : messages) { - ws->Send(DebuggerLogEvent{msg.header, msg.msg, msg.level, msg.log}); + ws->Send(DebuggerLogEvent{msg}); } }