How to Set a Custom Error Handler in spdlog: Global and Per-Logger APIs
You can intercept spdlog's internal error messages by installing a user-defined callback with signature void(const std::string&) either globally via spdlog::set_error_handler() or per-logger via logger::set_error_handler(), allowing you to redirect failures like file write errors to monitoring systems instead of stderr.
The spdlog library provides a flexible mechanism to capture internal logging failures through custom error handlers. When operations like opening a log file or writing to a sink fail, spdlog routes these errors to a registered callback rather than silently dropping them. This article explains how to set a custom error handler in spdlog using both global and per-logger scopes, based on the actual implementation in the gabime/spdlog repository.
Understanding spdlog's Error Handling Mechanism
spdlog reports internal failures—such as being unable to create a log file or write to a sink—through a dedicated error handler callback. By default, spdlog writes these messages to stderr, but you can override this behavior to log errors to external monitoring systems, perform cleanup, or trigger application termination.
The error handler uses the signature void(const std::string& msg), receiving a descriptive message about the failure. You can register this handler at two scopes: global (affecting all loggers) or per-logger (overriding the global handler for specific instances).
Setting a Global Custom Error Handler
The global API affects every logger in your application unless explicitly overridden. According to the spdlog source code, the global handler is declared in include/spdlog/spdlog.h at line 91 and implemented in include/spdlog/spdlog-inl.h at line 54.
When you call spdlog::set_error_handler(), the implementation updates the registry's global handler, which then propagates to newly created loggers via include/spdlog/details/registry.h and registry-inl.h (lines 165-168).
To set a global handler:
#include <spdlog/spdlog.h>
#include <iostream>
void global_error_handler(const std::string& msg)
{
std::cerr << "[Global spdlog error] " << msg << std::endl;
// Optional: log to monitoring system or terminate
}
int main()
{
// Install before creating loggers
spdlog::set_error_handler(global_error_handler);
auto logger = spdlog::stdout_color_mt("console");
// Any errors in 'logger' will now call global_error_handler
}
Setting a Per-Logger Custom Error Handler
Individual loggers can override the global handler using the set_error_handler member function. This is declared in include/spdlog/logger.h at line 310 and implemented in include/spdlog/logger-inl.h at line 112.
This approach allows different loggers to handle errors differently—for example, a file logger might attempt backup operations while a console logger simply reports to stderr.
auto file_logger = spdlog::basic_logger_mt("file", "app.log");
// Override with lambda handler
file_logger->set_error_handler([](const std::string& msg)
{
std::cerr << "[File logger specific error] " << msg << std::endl;
// Perform file-specific recovery or alerting
});
Complete Implementation Example
The following example demonstrates installing both global and per-logger handlers, showing how spdlog routes errors through the appropriate callback:
#include <spdlog/spdlog.h>
#include <iostream>
#include <cstdlib>
void my_global_handler(const std::string& msg)
{
std::cerr << "[MONITORING ALERT] Logging failure: " << msg << std::endl;
// Could send to external service here
}
int main()
{
// 1. Set global handler before any logger creation
spdlog::set_error_handler(my_global_handler);
// 2. Create logger using global handler
auto console = spdlog::stdout_color_mt("console");
// 3. Create file logger with specific error handling
auto file_logger = spdlog::basic_logger_mt("file", "logs.txt");
file_logger->set_error_handler([](const std::string& msg)
{
std::cerr << "[File backup initiated] Error: " << msg << std::endl;
// Attempt recovery or alert operations team
});
// Normal usage - errors will route to appropriate handler
console->info("Application started");
file_logger->error("Test message");
return 0;
}
Key Source Files and Implementation Details
The error handler mechanism spans several files in the spdlog repository:
include/spdlog/spdlog.h(line 91): Declaresspdlog::set_error_handler(void(*handler)(const std::string&))include/spdlog/spdlog-inl.h(line 54): Implements the global registration functioninclude/spdlog/logger.h(line 310): Declareslogger::set_error_handler(err_handler handler)include/spdlog/logger-inl.h(line 112): Implements the per-logger setterinclude/spdlog/details/registry.handregistry-inl.h(lines 165-168): Manage propagation of the global handler to logger instances
Summary
- Use
spdlog::set_error_handler()to define a global callback that catches errors for all loggers, implemented inspdlog-inl.h. - Use
logger::set_error_handler()to override the global handler for specific logger instances, declared inlogger.hat line 310. - Implement the signature
void(const std::string&)to receive error messages describing the failure. - Register global handlers before logger creation to ensure all loggers inherit the custom handler via the registry mechanism in
registry-inl.h. - Handle errors appropriately based on logger type—file errors might need different recovery than console errors.
Frequently Asked Questions
What function signature must a custom error handler have?
A custom error handler must match the signature void(const std::string& msg), accepting a string parameter containing the error description. This signature is strictly enforced by the template parameters in spdlog.h and logger.h.
Does a per-logger error handler override the global handler?
Yes. When you call set_error_handler() on a specific logger instance, that handler replaces the global handler for that logger only. Other loggers continue to use the global handler or their own specific handlers.
What types of errors trigger the custom handler?
The handler catches internal spdlog failures such as inability to open log files, write errors to sinks, flush failures, and other I/O operations that fail during the logging process. It does not catch application logic errors or logging API misuse.
Can I throw exceptions from within a custom error handler?
While technically possible, throwing exceptions from within the error handler is generally discouraged because spdlog calls the handler from within its logging operations. An unhandled exception could terminate your application. Instead, log to a fallback mechanism or set a flag for later inspection.
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 →