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

> Learn to use the Windows Event Log sink with spdlog. Easily send application logs to the Windows Event Viewer by registering your source and configuring the win_eventlog_sink.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-14

---

**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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/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:

```registry
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`](https://github.com/gabime/spdlog/blob/main/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:

```cpp
#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:

```cpp
#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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/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.