deargui-vpl/examples/blueprints-example/LOGGING_INTEGRATION.md

6.3 KiB

Spdlog Logger Integration Summary

Overview

Integrated spdlog (high-performance C++ logging library) into the imgui-node-editor blueprints-example for Win32/ImGui. The system uses LOG_* macros that can be disabled via DISABLE_LOGGING compile flag.

Files Created/Modified

Core Logger Files

  • Logging.h - Simple wrapper with LOG_* macros for spdlog
  • Logging.cpp - Initialization/shutdown using spdlog
  • external/spdlog/ - Copied locally (header-only mode)

Modified Files

  1. examples/CMakeLists.txt - Added spdlog INTERFACE library
  2. examples/blueprints-example/CMakeLists.txt - Added include path and /utf-8 compiler flag
  3. app.cpp - Initialize/cleanup logger with InitLogger() and ShutdownLogger()
  4. app-render.cpp - Replaced key printf() calls with LOG_* macros

Features

Log Levels (spdlog)

LOG_TRACE(...)    // Most verbose (detailed trace info)
LOG_DEBUG(...)    // Debug information
LOG_INFO(...)     // Informational messages
LOG_WARN(...)     // Warnings
LOG_ERROR(...)    // Errors
LOG_CRITICAL(...) // Critical errors (renamed from FATAL)

// Legacy compatibility
LOG_FATAL(...)    -> LOG_CRITICAL(...)
LOG_VERBOSE(...)  -> LOG_TRACE(...)

Sinks (Output Targets)

  • Console Sink - Color-coded output to stdout (Windows console colors via spdlog)
  • File Sink - Persistent logging to blueprints.log

Usage

Initialization (in app.cpp::OnStart)

// Initialize spdlog logger system
InitLogger("blueprints", true, true, "blueprints.log");
//         ^app name    ^console ^file  ^filename

Logging Examples

// Info level
LOG_INFO("[DELETE] DeleteNodeAndInstances: Starting deletion of node {} (ptr={})",
       nodeId, (void *)&node);

// Error level  
LOG_ERROR("[ERROR] RenderNodes: Node pointer corrupted: 0x{:x}", nodePtrValue);

// Warning level
LOG_WARN("[WARNING] RenderNodes: null node pointer in container!");

Shutdown (in app.cpp::OnStop)

// Shutdown spdlog logger
ShutdownLogger();

Architecture

Header-Only Mode

  • Spdlog compiled in header-only mode (SPDLOG_HEADER_ONLY)
  • No separate library linking required
  • All template code included at compile time

Multi-Sink Support

  • Console sink: [HH:MM:SS] [LEVEL] message
  • File sink: [YYYY-MM-DD HH:MM:SS.mmm] [LEVEL] message

Thread Safety

  • Spdlog provides thread-safe logging via _mt (multi-threaded) sinks
  • stdout_color_sink_mt and basic_file_sink_mt are thread-safe

Log Format

Console Output

[14:32:15] [info] === Logger System Initialized (spdlog) ===
[14:32:16] [error] Node pointer itself is corrupted: 0xDDDDDDDDDDDDDDDD
[14:32:17] [warn] null node pointer in container!

File Output (blueprints.log)

[2025-11-07 14:32:15.123] [info] === Logger System Initialized (spdlog) ===
[2025-11-07 14:32:16.456] [error] Node pointer itself is corrupted: 0xDDDDDDDDDDDDDDDD
[2025-11-07 14:32:17.789] [warn] null node pointer in container!

Advantages Over Custom Logger

Why Spdlog?

Performance - Extremely fast, async logging support
Feature-Rich - Rotating files, daily files, custom sinks
Mature - Battle-tested library used in production
Cross-Platform - Works on Windows, Linux, macOS
Modern C++ - Uses C++11/14/17 features properly
No Dependencies - Header-only mode, no external libs

Performance

  • Zero-cost abstractions when logging is disabled
  • Minimal overhead in release builds
  • Optional async logging for high-throughput scenarios

Build Configuration

Required CMake Changes

  1. examples/CMakeLists.txt:

    • Added spdlog INTERFACE library
  2. examples/blueprints-example/CMakeLists.txt:

    # Add local spdlog include directory
    target_include_directories(blueprints-example PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/external")
    
    # Add /utf-8 compiler flag for spdlog on MSVC
    if (MSVC)
        target_compile_options(blueprints-example PRIVATE /utf-8)
    endif()
    

Build Verification

Build successful with sh scripts/build.sh

  • Spdlog compiles cleanly in header-only mode
  • /utf-8 flag required for MSVC (Unicode support)
  • All LOG_* macros expand correctly

Output Files

Console

  • Color-coded log messages (via spdlog wincolor_sink)
  • Real-time feedback during execution

blueprints.log

  • Persistent log history with millisecond precision
  • Appends to existing file (doesn't overwrite)
  • Full timestamp format

Configuration

Disable Logging Completely

Define DISABLE_LOGGING before including Logging.h:

#define DISABLE_LOGGING
#include "Logging.h"

All LOG_* macros become (void)0 - zero runtime cost!

Change Log Level at Runtime

// Set global level (only works if you access spdlog directly)
g_logger->set_level(spdlog::level::err);  // Only errors and critical

Add Custom Sinks

// You can extend InitLogger() to add more sinks:
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
    "app.log", 1024*1024*5, 3);  // 5MB, 3 files
g_logger->sinks().push_back(rotating_sink);

Testing

Run the application:

./build/bin/blueprints-example_d.exe

Check:

  • Console - Colored log messages with timestamps
  • build/bin/blueprints.log - Persistent log file

Future Enhancements

Possible additions:

  • Async logging - For high-throughput scenarios
  • Rotating files - Size/time based rotation
  • Remote logging - Network sinks (UDP/TCP)
  • Custom formatters - Different log formats per sink
  • Log filtering - By component/category
  • ImGui log viewer - In-app log window

Example Advanced Usage

Multiple Loggers

// Create separate loggers for different subsystems
auto render_logger = spdlog::stdout_color_mt("render");
auto physics_logger = spdlog::basic_logger_mt("physics", "physics.log");

Structured Logging

LOG_INFO("User {} performed action {}", username, action);
LOG_ERROR("Failed to load file: {} (error: {})", filename, err_code);

Conditional Compilation

#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG
    LOG_DEBUG("Expensive debug info: {}", compute_debug_info());
#endif

Integration Date: November 7, 2025
Spdlog Version: Header-only (bundled)
Status: Complete and verified
Build: Successful with /utf-8 flag