This example demonstrates comprehensive crash protection mechanisms for logging systems including emergency logging, log file recovery, automatic backups, and signal-safe logging operations.
#include <iostream>
#include <thread>
#include <chrono>
#include <random>
#include <vector>
#include <memory>
#include <atomic>
#include <fstream>
#include "interfaces/logger_crash_safety.h"
#include "logger/logger.h"
#include <kcenon/common/interfaces/logger_interface.h>
namespace ci = kcenon::common::interfaces;
std::cout << "[CRASH] Simulating logger system crash..." << std::endl;
std::raise(SIGTERM);
}
std::cout << "[CRASH] Simulating log file corruption..." << std::endl;
std::ofstream corrupted_file("./logs/corrupted.log", std::ios::binary);
corrupted_file << "CORRUPTED_HEADER";
corrupted_file.write("\x00\x00\x00\x00", 4);
corrupted_file << "INVALID_LOG_DATA";
corrupted_file.close();
}
std::cout << "[CRASH] Simulating disk full scenario..." << std::endl;
logger_crash_safety::instance().emergency_log("ERROR",
"Disk space critical - switching to emergency logging mode");
}
std::cout << "[LOG] Logging task " << task_id << " starting" << std::endl;
for (int i = 0; i < 5; ++i) {
std::string message = "Task " + std::to_string(task_id) +
" - Log entry " + std::to_string(i);
logger_instance->log(ci::log_level::info, message);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
std::cout << "[OK] Logging task " << task_id << " completed" << std::endl;
}
std::cout << "[LOG] Heavy logging task " << task_id << " starting" << std::endl;
for (int i = 0; i < 20; ++i) {
std::string large_message = "Heavy Task " + std::to_string(task_id) +
" - Large log entry " + std::to_string(i) +
" with lots of data: " + std::string(100, 'X');
logger_instance->log(ci::log_level::debug, large_message);
if (i % 5 == 0) {
logger_instance->log(ci::log_level::warning,
"Checkpoint " + std::to_string(i) + " for task " + std::to_string(task_id));
}
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
std::cout << "[OK] Heavy logging task " << task_id << " completed" << std::endl;
}
std::cout << "[WARN] Risky logging task " << task_id << " starting" << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> crash_dist(1, 10);
for (int i = 0; i < 10; ++i) {
std::string message = "Risky Task " + std::to_string(task_id) +
" - Entry " + std::to_string(i);
logger_instance->log(ci::log_level::info, message);
int outcome = crash_dist(gen);
if (outcome <= 7) {
std::this_thread::sleep_for(std::chrono::milliseconds(30));
} else if (outcome == 8) {
logger_crash_safety::instance().emergency_log("CRITICAL",
"Emergency condition detected in task " + std::to_string(task_id));
} else if (outcome == 9) {
break;
} else {
break;
}
}
std::cout << "[WARN] Risky logging task " + std::to_string(task_id) + " finished" << std::endl;
}
std::cout << "\n[ALERT] LOGGER CRASH DETECTED: " << logger_name << std::endl;
logger_crash_safety::instance().emergency_log("CRITICAL",
"Logger " + logger_name + " has crashed - emergency mode activated");
}
std::cout << "[FLUSH] Emergency flush of main logger" << std::endl;
}
std::cout << "[BACKUP] Creating emergency backup: " << backup_path << std::endl;
std::ifstream source("./logs/application.log", std::ios::binary);
std::ofstream backup(backup_path, std::ios::binary);
backup << source.rdbuf();
std::cout << "[OK] Backup created successfully" << std::endl;
}
std::cout << "[SAVE] Saving emergency logger state..." << std::endl;
std::cout <<
"Logs written: " <<
logs_written.load() << std::endl;
std::cout <<
"Emergency logs: " <<
emergency_logs.load() << std::endl;
}
std::cout << "=== Logger System Crash Protection Demo ===" << std::endl;
std::cout << "This demo shows comprehensive logging crash protection mechanisms\n" << std::endl;
system("mkdir -p ./logs");
std::cout << "--- Step 1: Initialize Logger Crash Protection ---" << std::endl;
auto& logger_safety = logger_crash_safety::instance();
logger_safety.initialize(logger_crash_safety_level::standard,
"./logs/emergency.log", 2000);
logger_safety.set_auto_backup(true, 3000);
logger_safety.set_max_emergency_entries(500);
std::cout << "[OK] Logger crash protection initialized" << std::endl;
std::cout << "\n--- Step 2: Create Logger with Crash Protection ---" << std::endl;
auto main_logger = std::make_shared<logger>(true);
main_logger->add_writer(std::make_unique<console_writer>());
main_logger->add_writer(std::make_unique<file_writer>("./logs/application.log"));
main_logger->set_level(ci::log_level::debug);
main_logger->start();
{
scoped_logger_crash_protection logger_protection("MainLogger",
std::cout << "[OK] Logger created and protected" << std::endl;
std::cout << "\n--- Step 3: Normal Logging Operations ---" << std::endl;
main_logger->log(ci::log_level::info, std::string("Logger crash protection demo started"));
main_logger->log(ci::log_level::debug, std::string("Debug information available"));
main_logger->log(ci::log_level::warning, std::string("This is a warning message"));
std::cout << "\n--- Step 4: Multi-threaded Logging Stress Test ---" << std::endl;
std::vector<std::thread> logging_threads;
for (int i = 0; i < 3; ++i) {
}
for (int i = 3; i < 5; ++i) {
}
for (auto& t : logging_threads) {
t.join();
}
logging_threads.clear();
std::cout << "[OK] Multi-threaded stress test completed" << std::endl;
std::cout << "\n--- Step 5: File Recovery Test ---" << std::endl;
if (log_file_recovery::is_corrupted("./logs/corrupted.log")) {
std::cout << "[DETECT] Corruption detected in test file" << std::endl;
if (log_file_recovery::recover_file("./logs/corrupted.log",
"./logs/recovered.log")) {
std::cout << "[OK] File recovery successful" << std::endl;
} else {
std::cout << "[FAIL] File recovery failed" << std::endl;
}
}
log_file_recovery::create_backup_with_checksum("./logs/application.log",
"./logs/application_checksum_backup.log");
if (log_file_recovery::verify_integrity("./logs/application_checksum_backup.log",
"./logs/application_checksum_backup.log.checksum")) {
std::cout << "[OK] Backup integrity verified" << std::endl;
}
std::cout << "\n--- Step 6: Emergency Logging Test ---" << std::endl;
logger_safety.emergency_log("INFO", "Testing emergency logging system");
logger_safety.emergency_log("WARNING", "Emergency logging is signal-safe");
logger_safety.emergency_log("ERROR", "This log survives crashes");
std::cout << "\n--- Step 7: Risky Operations Test ---" << std::endl;
std::cout << "[WARN] Some operations may trigger crash protection" << std::endl;
for (int i = 10; i < 15; ++i) {
}
for (auto& t : logging_threads) {
t.join();
}
std::cout << "\n--- Step 8: Async Logger Crash Safety ---" << std::endl;
async_logger_crash_safety::configure_async_safety("MainLogger", 2000, true);
async_logger_crash_safety::set_overflow_handler("MainLogger",
[](size_t dropped) {
std::cout << "[WARN] Buffer overflow: " << dropped << " messages dropped" << std::endl;
});
for (int i = 0; i < 1000; ++i) {
main_logger->log(ci::log_level::debug, "Burst log " + std::to_string(i));
}
logger_safety.force_flush_all();
logger_safety.force_backup_all();
}
std::cout << "\n--- Step 9: Crash Protection Statistics ---" << std::endl;
auto stats = logger_safety.get_stats();
std::cout << "Emergency Log Statistics:" << std::endl;
std::cout << " Total emergency logs: " << stats.total_emergency_logs << std::endl;
std::cout << " Successful flushes: " << stats.successful_flushes << std::endl;
std::cout << " Failed flushes: " << stats.failed_flushes << std::endl;
std::cout << " Backup count: " << stats.backup_count << std::endl;
std::cout << "\nApplication Statistics:" << std::endl;
std::cout <<
" Total logs written: " <<
logs_written.load() << std::endl;
std::cout <<
" Emergency logs: " <<
emergency_logs.load() << std::endl;
std::cout <<
" Logging active: " << (
logging_active.load() ?
"Yes" :
"No") << std::endl;
std::cout << "\n--- Step 10: Recovery Test ---" << std::endl;
if (logger_safety.check_and_recover()) {
std::cout << "[OK] Recovery actions were taken" << std::endl;
} else {
std::cout << "[INFO] No recovery needed" << std::endl;
}
std::cout << "\n--- Step 11: Graceful Shutdown ---" << std::endl;
main_logger->log(ci::log_level::info, std::string("Shutting down logger crash protection demo"));
main_logger->stop();
std::cout << "\n=== Demo Completed Successfully ===" << std::endl;
std::cout << "Key features demonstrated:" << std::endl;
std::cout << "[OK] Emergency logging (signal-safe)" << std::endl;
std::cout << "[OK] Automatic log flushing on crash" << std::endl;
std::cout << "[OK] Log file corruption detection and recovery" << std::endl;
std::cout << "[OK] Backup creation with integrity verification" << std::endl;
std::cout << "[OK] Async logger crash safety" << std::endl;
std::cout << "[OK] Multi-threaded logging protection" << std::endl;
std::cout << "[OK] RAII-based crash protection registration" << std::endl;
std::cout << "[OK] Buffer overflow handling" << std::endl;
return 0;
}
Console writer for logging to stdout/stderr.
File writer for logging to files with optional buffering.
std::atomic< bool > logging_active
void simulate_file_corruption()
void simulate_logger_crash()
std::atomic< int > logs_written
void heavy_logging_task(int task_id, std::shared_ptr< logger > logger_instance)
void backup_main_logger(const std::string &backup_path)
std::atomic< int > emergency_logs
void save_emergency_state()
void on_logger_crash(const std::string &logger_name)
void simulate_disk_full()
void potentially_crashing_logging_task(int task_id, std::shared_ptr< logger > logger_instance)
void normal_logging_task(int task_id, std::shared_ptr< logger > logger_instance)