3232namespace {
3333 struct SpdlogErrorHandlerInitializer {
3434 SpdlogErrorHandlerInitializer () {
35- // Set spdlog to be completely silent about file rotation issues
36- spdlog::set_error_handler ([](const std::string& msg) {
37- // Suppress ALL spdlog errors to avoid CI/CD noise
38- // This is intentional for production stability
39- });
40-
41- // Set global log level to critical only
42- spdlog::set_level (spdlog::level::critical);
35+ try {
36+ // Set spdlog to be completely silent about file rotation issues
37+ spdlog::set_error_handler ([](const std::string&) {
38+ // Suppress ALL spdlog errors to avoid CI/CD noise
39+ // This is intentional for production stability
40+ });
41+
42+ // Set global log level to critical only
43+ spdlog::set_level (spdlog::level::critical);
44+ } catch (...) {
45+ // Ignore any initialization errors
46+ }
4347 }
48+
4449 };
4550
4651 // Static instance to ensure error handler is set before any logger creation
@@ -74,7 +79,6 @@ class Logger {
7479 std::string pattern; // /< Log message pattern
7580 size_t queueSize; // /< Queue size for async logging
7681 size_t flushInterval; // /< Flush interval in seconds
77- bool safeFileRotation; // /< Enable safe file rotation (prevents errors)
7882
7983 // Default constructor with default values
8084 Config () :
@@ -86,8 +90,7 @@ class Logger {
8690 maxFiles (5 ),
8791 pattern (" [%Y-%m-%d %H:%M:%S.%e] [%l] [%t] %v" ),
8892 queueSize (8192 ),
89- flushInterval (3 ),
90- safeFileRotation (true ) {}
93+ flushInterval (3 ) {}
9194 };
9295
9396 /* *
@@ -179,14 +182,15 @@ class Logger {
179182 // File sink setup
180183 if (!config.logFilePath .empty ()) {
181184 try {
182- // Suppress spdlog file rotation errors by setting environment variables
183- setenv (" SPDLOG_LEVEL" , " error" , 1 ); // Only show errors, not warnings
184- setenv (" SPDLOG_ERROR_LEVEL" , " critical" , 1 ); // Only show critical errors
185-
186185 // Temporarily redirect stderr to suppress file rotation errors
187186 std::stringstream buffer;
188- std::streambuf* old_stderr = std::cerr.rdbuf ();
189- std::cerr.rdbuf (buffer.rdbuf ());
187+ struct StderrRedirectGuard {
188+ std::ostream& stream;
189+ std::streambuf* old;
190+ explicit StderrRedirectGuard (std::ostream& s, std::streambuf* nb)
191+ : stream(s), old(s.rdbuf(nb)) {}
192+ ~StderrRedirectGuard () { stream.rdbuf (old); }
193+ } guard (std::cerr, buffer.rdbuf ());
190194
191195 // Ensure directory exists and is writable
192196 std::filesystem::path logPath (config.logFilePath );
@@ -210,8 +214,7 @@ class Logger {
210214 throw std::runtime_error (" Cannot create test file in log directory" );
211215 }
212216 } catch (const std::exception& ex) {
213- // Restore stderr before printing warning
214- std::cerr.rdbuf (old_stderr);
217+ // stderr will be restored by guard destructor
215218 std::cerr << " Warning: Log directory not writable: " << logDir << " - " << ex.what () << std::endl;
216219 // Fall back to console only
217220 if (sinks.empty ()) {
@@ -233,8 +236,7 @@ class Logger {
233236
234237 sinks.push_back (file_sink);
235238
236- // Restore stderr after file sink creation
237- std::cerr.rdbuf (old_stderr);
239+ // stderr will be restored automatically when guard goes out of scope
238240
239241 } catch (const std::exception& ex) {
240242 // Fallback to console if file creation fails
@@ -306,17 +308,7 @@ class Logger {
306308 }
307309 }
308310
309- LogLevel convertLevel (spdlog::level::level_enum level) const {
310- switch (level) {
311- case spdlog::level::trace: return LogLevel::TRACE ;
312- case spdlog::level::debug: return LogLevel::DEBUG ;
313- case spdlog::level::info: return LogLevel::INFO ;
314- case spdlog::level::warn: return LogLevel::WARNING ;
315- case spdlog::level::err: return LogLevel::ERROR ;
316- case spdlog::level::critical: return LogLevel::FATAL ;
317- default : return LogLevel::INFO ;
318- }
319- }
311+
320312
321313 std::shared_ptr<spdlog::logger> m_logger; // /< Underlying spdlog logger instance
322314 Config m_config; // /< Current logger configuration
0 commit comments