refactor(logging): changed the way source-linked traces are logged

This commit is contained in:
maelstrom 2025-07-11 10:09:02 +02:00
parent c63e91285b
commit c628fa2b83
6 changed files with 32 additions and 56 deletions

View file

@ -77,7 +77,7 @@ int main() {
} }
void errorCatcher(int id, const char* str) { void errorCatcher(int id, const char* str) {
Logger::fatalError(std::format("GLFW Error: [{}] {}", id, str)); Logger::fatalErrorf("GLFW Error: [{}] {}", id, str);
} }
float lastTime; float lastTime;

View file

@ -9,7 +9,6 @@
static std::ofstream logStream; static std::ofstream logStream;
static std::vector<Logger::LogListener> logListeners; static std::vector<Logger::LogListener> logListeners;
static std::vector<Logger::TraceLogListener> traceLogListeners;
std::string Logger::currentLogDir = "NULL"; std::string Logger::currentLogDir = "NULL";
void Logger::init() { void Logger::init() {
@ -28,7 +27,7 @@ void Logger::finish() {
logStream.close(); logStream.close();
} }
void Logger::log(std::string message, Logger::LogLevel logLevel) { void Logger::log(std::string message, Logger::LogLevel logLevel, ScriptSource source) {
std::string logLevelStr = logLevel == Logger::LogLevel::INFO ? "INFO" : std::string logLevelStr = logLevel == Logger::LogLevel::INFO ? "INFO" :
logLevel == Logger::LogLevel::DEBUG ? "DEBUG" : logLevel == Logger::LogLevel::DEBUG ? "DEBUG" :
logLevel == Logger::LogLevel::TRACE ? "TRACE" : logLevel == Logger::LogLevel::TRACE ? "TRACE" :
@ -44,7 +43,7 @@ void Logger::log(std::string message, Logger::LogLevel logLevel) {
printf("%s\n", formattedLogLine.c_str()); printf("%s\n", formattedLogLine.c_str());
for (Logger::LogListener listener : logListeners) { for (Logger::LogListener listener : logListeners) {
listener(logLevel, message); listener(logLevel, message, source);
} }
if (logLevel == Logger::LogLevel::FATAL_ERROR) { if (logLevel == Logger::LogLevel::FATAL_ERROR) {
@ -52,20 +51,6 @@ void Logger::log(std::string message, Logger::LogLevel logLevel) {
} }
} }
void Logger::trace(std::string source, int line, void* userData) {
std::string message = "'" + source + "' Line " + std::to_string(line);
log(message, Logger::LogLevel::TRACE);
for (Logger::TraceLogListener listener : traceLogListeners) {
listener(message, source, line, userData);
}
}
void Logger::addLogListener(Logger::LogListener listener) { void Logger::addLogListener(Logger::LogListener listener) {
logListeners.push_back(listener); logListeners.push_back(listener);
} }
void Logger::addLogListener(Logger::TraceLogListener listener) {
traceLogListeners.push_back(listener);
}

View file

@ -1,9 +1,11 @@
#pragma once #pragma once
#include <format>
#include <functional> #include <functional>
#include <memory>
#include <string> #include <string>
class Script;
namespace Logger { namespace Logger {
enum class LogLevel { enum class LogLevel {
INFO, INFO,
@ -14,32 +16,37 @@ namespace Logger {
FATAL_ERROR, FATAL_ERROR,
}; };
typedef std::function<void(LogLevel logLevel, std::string message)> LogListener; struct ScriptSource {
typedef std::function<void(std::string message, std::string source, int line, void* userData)> TraceLogListener; std::shared_ptr<Script> script;
int line;
};
typedef std::function<void(LogLevel logLevel, std::string message, ScriptSource source)> LogListener;
extern std::string currentLogDir; extern std::string currentLogDir;
void init(); void init();
void finish(); void finish();
void addLogListener(LogListener); void addLogListener(LogListener);
void addLogListener(TraceLogListener);
void log(std::string message, LogLevel logLevel); void log(std::string message, LogLevel logLevel, ScriptSource source = {});
inline void info(std::string message) { log(message, LogLevel::INFO); } inline void info(std::string message) { log(message, LogLevel::INFO); }
inline void debug(std::string message) { log(message, LogLevel::DEBUG); } inline void debug(std::string message) { log(message, LogLevel::DEBUG); }
inline void warning(std::string message) { log(message, LogLevel::WARNING); } inline void warning(std::string message) { log(message, LogLevel::WARNING); }
inline void error(std::string message) { log(message, LogLevel::ERROR); } inline void error(std::string message) { log(message, LogLevel::ERROR); }
inline void fatalError(std::string message) { log(message, LogLevel::FATAL_ERROR); } inline void fatalError(std::string message) { log(message, LogLevel::FATAL_ERROR); }
inline void trace(std::string message) { log(message, LogLevel::TRACE); };
inline void traceStart() { log("Stack start", LogLevel::TRACE); } template <typename ...Args>
inline void traceEnd() { log("Stack end", LogLevel::TRACE); } void scriptLogf(std::string format, LogLevel logLevel, ScriptSource source, Args&&... args) {
void trace(std::string source, int line, void* userData = nullptr); char message[200];
sprintf(message, format.c_str(), args...);
log(message, logLevel, source);
}
template <typename ...Args> template <typename ...Args>
void logf(std::string format, LogLevel logLevel, Args&&... args) { void logf(std::string format, LogLevel logLevel, Args&&... args) {
char message[200]; scriptLogf(format, logLevel, {}, args...);
sprintf(message, format.c_str(), args...);
log(message, logLevel);
} }
template <typename ...Args> inline void infof(std::string format, Args&&... args) { logf(format, LogLevel::INFO, args...); } template <typename ...Args> inline void infof(std::string format, Args&&... args) { logf(format, LogLevel::INFO, args...); }

View file

@ -118,7 +118,7 @@ int script_errhandler(lua_State* L) {
// Traceback // Traceback
Logger::traceStart(); Logger::trace("Stack start");
lua_Debug dbg; lua_Debug dbg;
int stack = 1; int stack = 1;
@ -128,10 +128,10 @@ int script_errhandler(lua_State* L) {
if (strcmp(dbg.what, "C") == 0 || strcmp(dbg.source, "=PCALL_WRAPPER") == 0) if (strcmp(dbg.what, "C") == 0 || strcmp(dbg.source, "=PCALL_WRAPPER") == 0)
continue; continue;
Logger::trace(dbg.source, dbg.currentline); Logger::scriptLogf("'%s', Line %d", Logger::LogLevel::TRACE, {}, dbg.source, dbg.currentline);
} }
Logger::traceEnd(); Logger::trace("Stack end");
return 0; return 0;
} }

View file

@ -1,4 +1,5 @@
#include "outputtextview.h" #include "outputtextview.h"
#include "logger.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "objects/script.h" #include "objects/script.h"
#include "panes/outputtextview.h" #include "panes/outputtextview.h"
@ -12,8 +13,7 @@
#include <string> #include <string>
OutputTextView::OutputTextView(QWidget* parent) : QTextEdit(parent) { OutputTextView::OutputTextView(QWidget* parent) : QTextEdit(parent) {
Logger::addLogListener(std::bind(&OutputTextView::handleLog, this, std::placeholders::_1, std::placeholders::_2)); Logger::addLogListener(std::bind(&OutputTextView::handleLog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
Logger::addLogListener(std::bind(&OutputTextView::handleLogTrace, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
ensureCursorVisible(); ensureCursorVisible();
QFont font(""); QFont font("");
@ -36,13 +36,9 @@ OutputTextView::OutputTextView(QWidget* parent) : QTextEdit(parent) {
OutputTextView::~OutputTextView() = default; OutputTextView::~OutputTextView() = default;
void OutputTextView::handleLog(Logger::LogLevel logLevel, std::string message) { void OutputTextView::handleLog(Logger::LogLevel logLevel, std::string message, Logger::ScriptSource source) {
if (logLevel == Logger::LogLevel::DEBUG) return; if (logLevel == Logger::LogLevel::DEBUG) return;
// Skip if trace, as that is handled by handleLogTrace
if (logLevel == Logger::LogLevel::TRACE && !message.starts_with("Stack"))
return;
// https://stackoverflow.com/a/61722734/16255372 // https://stackoverflow.com/a/61722734/16255372
moveCursor(QTextCursor::MoveOperation::End); moveCursor(QTextCursor::MoveOperation::End);
QTextCursor cursor = textCursor(); QTextCursor cursor = textCursor();
@ -58,21 +54,10 @@ void OutputTextView::handleLog(Logger::LogLevel logLevel, std::string message) {
format.setFontWeight(QFont::Bold); format.setFontWeight(QFont::Bold);
} }
cursor.insertText(message.c_str(), format); // Add anchor point if source is provided
cursor.insertText("\n", QTextCharFormat()); if (source.script != nullptr) {
}
void OutputTextView::handleLogTrace(std::string message, std::string source, int line, void* userData) {
std::weak_ptr<Script>* script = (std::weak_ptr<Script>*)userData;
// https://stackoverflow.com/a/61722734/16255372
QTextCursor cursor = textCursor();
QTextCharFormat format = cursor.charFormat();
format.setForeground(QColor(0, 127, 255));
if (userData != nullptr && !script->expired()) {
int id = stackTraceScriptsLastId++; int id = stackTraceScriptsLastId++;
stackTraceScripts[id] = *script; stackTraceScripts[id] = source.script;
format.setAnchor(true); format.setAnchor(true);
format.setAnchorHref(QString::number(id)); format.setAnchorHref(QString::number(id));

View file

@ -14,8 +14,7 @@ private:
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void handleLog(Logger::LogLevel, std::string); void handleLog(Logger::LogLevel, std::string, Logger::ScriptSource source);
void handleLogTrace(std::string, std::string, int, void*);
std::map<int, std::weak_ptr<Script>> stackTraceScripts; std::map<int, std::weak_ptr<Script>> stackTraceScripts;
int stackTraceScriptsLastId = 0; int stackTraceScriptsLastId = 0;