How to Use the Windows Event Log Sink (win_eventlog_sink) with spdlog

To write logs to the Windows Event Viewer using spdlog, register your application source name in the Windows Registry, then instantiate win_eventlog_sink_mt from include/spdlog/sinks/win_eventlog_sink.h and attach it to a logger; the sink automatically maps spdlog levels to Event Log types and submits entries via the ReportEventA API.

The spdlog library provides native Windows Event Log integration through the win_eventlog_sink implementation. Located in include/spdlog/sinks/win_eventlog_sink.h, this sink allows C++ applications to write structured logs directly to the Windows Event Viewer without external dependencies. Understanding how to properly configure the registry and initialize the sink ensures seamless integration with Windows logging infrastructure.

Prerequisites: Registering the Event Source

Before instantiating the sink, you must create registry entries for your application. The sink calls RegisterEventSourceA during initialization, which requires a pre-existing source name under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application.

Create a .reg file with the following content and execute it as Administrator:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\MyApp]
"TypesSupported"=dword:00000007
"EventMessageFile"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,\
  00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,\
  5c,00,6d,00,73,00,63,00,6f,00,72,00,65,00,65,00,2e,00,64,00,6c,00,6c,00,00,00

Replace MyApp with your desired source name. The EventMessageFile typically points to mscoree.dll in the system32 directory.

Implementation Architecture

The win_eventlog_sink implementation in include/spdlog/sinks/win_eventlog_sink.h inherits from the base_sink template, providing the same thread-safety guarantees as other spdlog sinks.

Thread Safety Variants

The header exposes two type aliases:

  • win_eventlog_sink_mt: Multi-threaded variant using mutex locking
  • win_eventlog_sink_st: Single-threaded variant for scenarios where external synchronization is guaranteed

Event Type Mapping

Internally, the sink maps spdlog severity levels to Windows Event Log types through the eventlog::get_event_type function:

  • level::trace → EVENTLOG_SUCCESS
  • level::debug and level::info → EVENTLOG_INFORMATION_TYPE
  • level::warn → EVENTLOG_WARNING_TYPE
  • level::error and level::critical → EVENTLOG_ERROR_TYPE

The numeric level value is also passed as the event category via eventlog::get_event_category.

User SID Attachment

The sink optionally retrieves the current user’s SID using sid_t::get_current_user_sid and attaches it to the event record. If the SID retrieval fails, the sink continues operating but the Event Viewer will not display a user name for those entries.

Error Handling

All Windows API failures are wrapped in win32_error, a class derived from spdlog_ex that formats the system error code into a human-readable message. This includes failures from RegisterEventSourceA, ReportEventA, or DeregisterEventSource during destruction.

Creating a Windows Event Log Logger

The following example demonstrates creating a multi-threaded sink and logging to the Application log:

#include <spdlog/spdlog.h>
#include <spdlog/sinks/win_eventlog_sink.h>

int main()
{
    // Create the sink with the registered source name "MyApp"
    auto eventlog_sink = std::make_shared<spdlog::sinks::win_eventlog_sink_mt>("MyApp");
    
    // Create and register the logger
    auto logger = std::make_shared<spdlog::logger>("eventlog_logger", eventlog_sink);
    spdlog::register_logger(logger);
    
    // Write log entries
    logger->info("Service started successfully.");
    logger->warn("Cache miss for key {}", 42);
    logger->error("Failed to open database: {}", "access denied");
}

Custom Formatters

You can apply custom pattern formatters to the sink before attaching it to a logger:

#include <spdlog/sinks/win_eventlog_sink.h>
#include <spdlog/pattern_formatter.h>

auto sink = std::make_shared<spdlog::sinks::win_eventlog_sink_mt>("MyApp");
auto formatter = std::make_unique<spdlog::pattern_formatter>("%Y-%m-%d %H:%M:%S.%e [%l] %v");
sink->set_formatter(std::move(formatter));

auto logger = std::make_shared<spdlog::logger>("custom_logger", sink);
logger->info("Custom formatted entry");

Note that while the sink accepts formatters, the Windows Event Viewer may interpret certain formatting differently than console outputs.

Summary

  • Registry Requirement: You must create the source name under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application before first use
  • Header Location: The implementation resides in include/spdlog/sinks/win_eventlog_sink.h
  • Thread Safety: Choose win_eventlog_sink_mt for multi-threaded applications or win_eventlog_sink_st for single-threaded contexts
  • API Flow: The sink caches the handle from RegisterEventSourceA, submits via ReportEventA, and cleans up with DeregisterEventSource in the destructor
  • Error Handling: Windows API errors throw win32_error exceptions with system error messages
  • Level Mapping: spdlog levels automatically translate to Event Log types (Information, Warning, Error)

Frequently Asked Questions

Do I need administrative privileges to use the Windows Event Log sink?

Yes, but only once. Creating the registry keys under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application requires Administrator rights. Once the source name is registered, the application can write to the Event Log with standard user privileges.

What is the difference between win_eventlog_sink_mt and win_eventlog_sink_st?

win_eventlog_sink_mt includes internal mutex locking from the base_sink template, making it safe to use across multiple threads concurrently. win_eventlog_sink_st omits this locking overhead and should only be used when you guarantee external synchronization or single-threaded access, as noted in the win_eventlog_sink.h implementation.

How do I view the logs created by this sink?

Open the Windows Event Viewer (eventvwr.msc), navigate to Windows Logs → Application, and filter by the source name you registered (e.g., "MyApp"). Entries appear with the mapped event types (Information, Warning, Error) based on the original spdlog level.

Can I use Unicode characters with win_eventlog_sink?

Yes. When SPDLOG_WCHAR_TO_UTF8_SUPPORT is enabled, the sink uses ReportEventW instead of ReportEventA, allowing proper Unicode message submission. Ensure your registry entries and source name are compatible with your chosen character encoding.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →