# Debugging Techniques and Tools in the Pyrite64 Editor: Log Window and Notification System

> Master Pyrite64 debugging with the Log Window and Notification system. Diagnose runtime issues directly in the UI using this efficient diagnostics tool. Learn more now!

- Repository: [Max Bebök/pyrite64](https://github.com/hailtododongo/pyrite64)
- Tags: how-to-guide
- Published: 2026-02-19

---

**The Pyrite64 editor provides a lightweight runtime diagnostics infrastructure centered around a thread-safe logger, a real-time Log Window, and a transient Notification system to diagnose issues without leaving the UI.**

The Pyrite64 editor, part of the `HailToDodongo/pyrite64` repository, includes built-in debugging techniques and tools designed for runtime issue diagnosis. These features allow developers to monitor execution flow and catch errors through a dedicated Log Window and a non-intrusive Notification system, both implemented using ImGui for seamless integration.

## Core Logging Infrastructure

### The Logger API in src/utils/logger.h

The foundation of Pyrite64's diagnostics is the `Utils::Logger` namespace defined in [`src/utils/logger.h`](https://github.com/HailToDodongo/pyrite64/blob/main/src/utils/logger.h). It exposes severity levels and functions for emitting structured messages:

```cpp
namespace Utils::Logger
{
    constexpr int LEVEL_INFO  = 0;
    constexpr int LEVEL_WARN  = 1;
    constexpr int LEVEL_ERROR = 2;

    void log(const std::string& msg, int level = LEVEL_INFO);
    void logRaw(const std::string& msg, int level = LEVEL_INFO);
    void clear();
    std::string getLog();
}

```

### Thread-Safe Buffer Implementation in src/utils/logger.cpp

The implementation in [`src/utils/logger.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/utils/logger.cpp) maintains a **thread-safe static `std::string` buffer** that accumulates all log entries. When `log()` is called, the function prepends severity tags like `[INFO]`, `[WARN]`, or `[ERROR]` automatically. The `getLog()` method returns the entire buffer content, enabling the UI to display a complete history without file I/O overhead.

Typical usage inside the editor or engine modules looks like this:

```cpp
Utils::Logger::log("Project opened: " + projectPath);
Utils::Logger::log("Missing texture asset!", Utils::Logger::LEVEL_ERROR);

```

## Real-Time Log Window Visualization

### LogWindow::draw Implementation in src/editor/pages/parts/logWindow.cpp

The `LogWindow` class in [`src/editor/pages/parts/logWindow.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/pages/parts/logWindow.cpp) renders the buffered log using ImGui's `InputTextMultiline` widget. The `draw()` method fetches the current log buffer via `Utils::Logger::getLog()` and displays it in a read-only text field with a monospaced font for alignment:

```cpp
void Editor::LogWindow::draw()
{
    auto log = Utils::Logger::getLog();
    
    ImGui::PushFont(ImGui::getFontMono());
    ImGui::InputTextMultiline("", log.data(), log.size()+1,
                              ImVec2(ImGui::GetWindowSize().x-18,
                                     ImGui::GetWindowSize().y-44),
                              ImGuiInputTextFlags_ReadOnly);
    // Auto-scroll logic follows...
}

```

### Auto-Scroll and Read-Only Features

To ensure developers always see the latest entries, the implementation tracks buffer length changes. When `lastLen != log.length()`, the code calculates the maximum scroll value and calls `ImGui::SetScrollY()` to snap to the bottom. The `ImGuiInputTextFlags_ReadOnly` flag prevents accidental modification of the diagnostic history while allowing text selection for copying.

## Transient Notification System

### Notification Structure and Rendering in src/editor/imgui/notification.cpp

For user-facing alerts that don't require persistent log storage, Pyrite64 uses a lightweight notification system defined in [`src/editor/imgui/notification.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/imgui/notification.cpp). It maintains a `static std::vector<Notification>` where each entry contains message text, a time-to-live counter (`ttl`), and a severity type:

```cpp
struct Notification
{
    std::string text;
    uint32_t    ttl;
    int         type;  // Maps to LEVEL_INFO, LEVEL_WARN, LEVEL_ERROR
};

static std::vector<Notification> notifications{};

```

The rendering loop positions these as small pop-ups in the top-right corner using `ImGui::SetNextWindowPos()` and `ImGui::Begin()` with `ImGuiWindowFlags_NoTitleBar` and `ImGuiWindowFlags_AlwaysAutoResize`.

### Triggering User-Facing Alerts

Developers emit notifications via the `Notify()` function, which pushes a new entry into the vector with a default lifespan of 180 frames (approximately 3 seconds at 60 FPS):

```cpp
void Notify(const std::string& msg, int type = Utils::Logger::LEVEL_INFO, uint32_t ttl = 180)
{
    notifications.push_back({msg, ttl, type});
}

```

Typical usage appears in UI controllers after significant events:

```cpp
void AssetManager::onAssetLoaded(const std::string& name)
{
    Utils::Logger::log("Asset loaded: " + name);
    Notify("✅ " + name + " ready", Utils::Logger::LEVEL_INFO, 120);
}

```

## Practical Debugging Workflow

Combining these debugging techniques and tools creates a seamless diagnostic pipeline:

1. **Instrument your code** with `Utils::Logger::log()` calls at key execution points. Files like [`src/editor/globalActions.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/globalActions.cpp) use this pattern for project operations.

2. **Monitor in real-time** by opening the Log Window from the *View* menu. The window auto-scrolls to show the latest `LEVEL_ERROR` or `LEVEL_WARN` entries as they are emitted by the thread-safe buffer.

3. **Surface critical events** using `Notify()` for user-facing feedback—such as build completion in [`src/build/projectBuilder.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/build/projectBuilder.cpp)—without requiring the user to check the log buffer.

4. **Clear history** via `Utils::Logger::clear()` when starting a new debugging session to ensure fresh output without restarting the editor.

## Summary

- **`Utils::Logger`** provides the backbone for runtime diagnostics with thread-safe buffering and severity levels (`LEVEL_INFO`, `LEVEL_WARN`, `LEVEL_ERROR`).
- The **Log Window** ([`src/editor/pages/parts/logWindow.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/pages/parts/logWindow.cpp)) renders the buffered log using ImGui with auto-scroll and read-only protection.
- The **Notification System** ([`src/editor/imgui/notification.cpp`](https://github.com/HailToDodongo/pyrite64/blob/main/src/editor/imgui/notification.cpp)) displays transient, colour-coded pop-ups via the `Notify()` function for immediate user feedback.
- Together, these debugging techniques and tools in the Pyrite64 editor enable efficient runtime issue diagnosis without external debuggers or console windows.

## Frequently Asked Questions

### How do I view the log output in the Pyrite64 editor?

Open the Log Window from the *View* menu. This window calls `Utils::Logger::getLog()` to retrieve the entire buffered history and displays it in a read-only ImGui text field that auto-scrolls to the newest entries as they arrive from the thread-safe buffer.

### What is the difference between the Log Window and the Notification System?

The **Log Window** provides a persistent, scrollable history of all diagnostic messages stored in the thread-safe logger buffer, suitable for detailed analysis. The **Notification System** displays transient pop-ups that disappear after a set TTL (time-to-live), designed for immediate user alerts without cluttering the log history.

### How do I trigger a notification from my own editor code?

Include the notification header and call the `Notify()` function with your message, severity level, and optional duration in frames:

```cpp
#include "editor/imgui/notification.h"
Notify("Operation complete", Utils::Logger::LEVEL_INFO, 180);

```

### Can I redirect the logger output to a file instead of the Log Window?

Yes. The `Utils::Logger::setOutput()` function accepts a custom callback that receives every log string. You can implement a file-writing sink and register it during editor initialization to capture diagnostics to disk while still viewing them in the Log Window.