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 lockingwin_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_SUCCESSlevel::debugandlevel::info→EVENTLOG_INFORMATION_TYPElevel::warn→EVENTLOG_WARNING_TYPElevel::errorandlevel::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\Applicationbefore first use - Header Location: The implementation resides in
include/spdlog/sinks/win_eventlog_sink.h - Thread Safety: Choose
win_eventlog_sink_mtfor multi-threaded applications orwin_eventlog_sink_stfor single-threaded contexts - API Flow: The sink caches the handle from
RegisterEventSourceA, submits viaReportEventA, and cleans up withDeregisterEventSourcein the destructor - Error Handling: Windows API errors throw
win32_errorexceptions 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →