How to Implement Custom Error Handlers in spdlog: A Complete Guide
You can implement custom error handlers in spdlog by installing a callback function with the signature void(const std::string&) using spdlog::set_error_handler() for global coverage or logger::set_error_handler() for per-logger interception of internal logging failures.
The gabime/spdlog library routes internal failure notifications—such as file permission errors or sink initialization failures—through a configurable callback mechanism rather than silently dropping errors. Implementing custom error handlers in spdlog enables you to redirect diagnostics to monitoring systems, trigger application alerts, or execute recovery logic when the logging infrastructure encounters problems.
Understanding Error Handling Levels
spdlog implements a two-tier error handling architecture that operates at different scopes within the logging hierarchy. The system distinguishes between global handlers that apply to all loggers and per-logger handlers that override the global behavior for specific instances.
When no custom handler is registered, spdlog defaults to writing error messages to stderr. According to the source in include/spdlog/details/registry.h and registry-inl.h (lines 165-168), the registry propagates global handlers to newly created loggers during initialization.
Global Error Handler API
The global interface declared in include/spdlog/spdlog.h (line 91) and implemented in include/spdlog/spdlog-inl.h (line 54) provides application-wide error interception.
spdlog::set_error_handler(void(*handler)(const std::string& msg));
Per-Logger Error Handler API
Individual logger instances override global behavior using the member function declared in include/spdlog/logger.h (line 310) and implemented in include/spdlog/logger-inl.h (line 112).
logger::set_error_handler(err_handler handler);
Implementing a Global Custom Error Handler
To capture all spdlog errors application-wide, define a function matching the required signature and register it before creating any loggers. This ensures the registry propagates your handler to all subsequent logger instances.
#include <spdlog/spdlog.h>
#include <iostream>
void global_error_handler(const std::string& msg)
{
std::cerr << "[CRITICAL LOG FAILURE] " << msg << std::endl;
// Integration point: send to monitoring APIs or metrics collection
}
int main()
{
// Install before any logger creation
spdlog::set_error_handler(global_error_handler);
// This logger inherits the global error handler
auto console = spdlog::stdout_color_mt("console");
console->info("Application started");
}
Configuring Per-Logger Error Handlers
For granular control over specific output destinations, override the error handler on individual logger instances. This approach is essential when file sinks require specialized failure handling distinct from console outputs.
auto file_logger = spdlog::basic_logger_mt("file", "/var/log/application.txt");
file_logger->set_error_handler([](const std::string& msg) {
// Specialized handling for disk-full or permission errors
std::cerr << "[File Logger Alert] " << msg << std::endl;
// Could trigger alerts or roll over to fallback storage
});
Complete Implementation Example
The following example demonstrates both global and per-logger error handling strategies, including handler installation, logger creation, and error propagation through the registry.
#include <spdlog/spdlog.h>
#include <iostream>
// Global handler with external system integration
void my_error_handler(const std::string& msg)
{
std::cerr << "[spdlog error] " << msg << std::endl;
// Optional: monitoring_api::alert("logging_failure", msg);
}
int main()
{
// 1. Register global handler via registry
spdlog::set_error_handler(my_error_handler);
// 2. Create logger using global handler
auto console = spdlog::stdout_color_mt("console");
console->info("Console initialized with global handler");
// 3. Override for specific logger
auto file_logger = spdlog::basic_logger_mt("file", "logs.txt");
file_logger->set_error_handler([](const std::string& msg) {
std::cerr << "[file-specific] " << msg << std::endl;
});
// 4. Errors in file_logger trigger per-logger handler
// Errors in console trigger my_error_handler
return 0;
}
Summary
- Global Registration: Use
spdlog::set_error_handler()(declared inspdlog.h, line 91) to intercept all logging errors application-wide via the registry mechanism. - Per-Logger Override: Call
logger::set_error_handler()(declared inlogger.h, line 310) to implement specialized error processing for individual logger instances. - Implementation Details: Global handlers reside in
spdlog-inl.h(line 54), per-logger implementations inlogger-inl.h(line 112), and registry propagation logic inregistry-inl.h(lines 165-168). - Signature Requirement: Handlers must conform to
void(const std::string&)to receive error descriptions from spdlog's internal failure detection. - Default Behavior: Without custom handlers, spdlog writes error messages to
stderrusing its internal default callback.
Frequently Asked Questions
What function signature is required for spdlog custom error handlers?
Custom error handlers must implement the signature void(const std::string& msg). The spdlog library passes a descriptive error message string to your callback when internal failures occur, such as file permission errors or sink write failures, as defined in the handler type aliases within logger.h.
Can I throw exceptions inside a custom error handler?
While the source code in logger-inl.h permits throwing exceptions within custom error handlers, doing so will immediately terminate the current logging operation and propagate the exception up the call stack. Because handlers are invoked synchronously during log writes, exceptions should only be thrown if your application architecture safely tolerates interruptions during logging operations.
How do I reset the error handler to default spdlog behavior?
To restore the default stderr output, invoke spdlog::set_error_handler(nullptr) or pass a default-constructed handler. The registry implementation in registry-inl.h automatically falls back to the internal default handler that writes to standard error when no custom handler is registered.
Are custom error handlers thread-safe in spdlog?
Error handler registration is thread-safe according to the implementation in registry.h and registry-inl.h, which uses internal synchronization to propagate global handlers across threads. However, your custom handler implementation must be thread-safe if multiple loggers might invoke it concurrently from different threads.
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 →