Apache log4cxx

Apache財団によるJava log4jのC++移植版。Java開発者に馴染みのあるAPI設計と設定方式を提供。アペンダー、レイアウト、フィルター等の概念をC++に適用した伝統的なロギングフレームワーク。

ロギングC++アペンダーレイアウトフィルター

ライブラリ

Apache log4cxx

概要

Apache log4cxxは、Apache財団によって開発されたJava log4jのC++移植版です。Java開発者に馴染みのあるAPI設計と設定方式を提供し、アペンダー、レイアウト、フィルター等のlog4j由来の概念をC++環境に適用した伝統的なロギングフレームワークです。スレッドセーフ性、柔軟な設定、階層的なロガー管理といったエンタープライズ級の機能を備え、C++アプリケーションでの包括的なログ管理を実現します。

詳細

Apache log4cxx 2025年版は、Java log4jの設計思想を忠実にC++に移植した成熟したロギングソリューションとして15年以上の開発実績を持ちます。XMLやプロパティファイルによる設定管理、複数の出力先への同時ログ出力、メッセージフィルタリング、ログローテーション機能など、大規模C++システムで求められる高度な要件に対応しています。CMakeビルドシステムに完全対応し、クロスプラットフォーム開発をサポート。Java開発経験を持つチームでのC++プロジェクト移行において、学習コストを最小化できる設計が特徴です。

主な特徴

  • Java log4j API互換: 馴染みのあるLogger、Appender、Layout概念の踏襲
  • XML設定サポート: 外部ファイルによる柔軟な設定管理
  • 階層的ロガー: パッケージ階層に対応したロガー管理システム
  • マルチプラットフォーム: Windows、Linux、macOS対応
  • 豊富なアペンダー: ファイル、コンソール、ネットワーク出力対応
  • スレッドセーフ: マルチスレッド環境での安全な動作保証

メリット・デメリット

メリット

  • Java log4j経験者にとって直感的で理解しやすいAPI設計
  • XML設定による実行時のログレベル・出力先変更が容易
  • 豊富なアペンダーとレイアウトによる柔軟な出力カスタマイズ
  • 階層的ロガー管理による大規模プロジェクトでの統一的なログ制御
  • Apache財団による長期的な保守とコミュニティサポート
  • Java・C++混在環境での統一的なログ管理アプローチ

デメリット

  • 現代的なC++プロジェクトでは他の軽量ライブラリが優先される傾向
  • 設定の複雑さにより小規模プロジェクトでは過剰機能となる場合
  • パフォーマンス面でspdlogやBoost.Logなど専用C++ライブラリに劣る
  • メンテナンス活動が限定的で最新C++標準への対応が遅い
  • 依存関係とビルド設定の複雑さによる導入コスト
  • Java特有の概念がC++の慣例と合わない場面での違和感

参考ページ

書き方の例

インストールと基本セットアップ

# Ubuntu/Debianでの依存関係インストール
sudo apt-get update
sudo apt-get install build-essential cmake libapr1-dev libaprutil1-dev

# ソースからのビルド
git clone https://github.com/apache/logging-log4cxx.git
cd logging-log4cxx
mkdir build && cd build

# CMakeでのビルド設定
cmake .. -DCMAKE_BUILD_TYPE=Release \
         -DCMAKE_INSTALL_PREFIX=/usr/local \
         -DLOG4CXX_ENABLE_TESTS=OFF

# ビルドとインストール
make -j$(nproc)
sudo make install

# pkg-configの確認
pkg-config --modversion liblog4cxx
pkg-config --cflags --libs liblog4cxx

# CMakeLists.txtでの使用例
find_package(log4cxx REQUIRED)
target_link_libraries(your_target ${LOG4CXX_LIBRARIES})
target_include_directories(your_target PRIVATE ${LOG4CXX_INCLUDE_DIRS})

基本的なロギング(Hello World)

#include <log4cxx/logger.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/configurator.h>
#include <log4cxx/initializer.h>

int main()
{
    // log4cxxの初期化
    log4cxx::Initializer initializer;

    // 基本設定の適用
    log4cxx::BasicConfigurator config;
    config.configure();

    // ロガーインスタンスの取得
    log4cxx::Logger logger = log4cxx::Logger::getInstance(
        LOG4CPLUS_TEXT("MyApp"));
    
    // 基本的なログ出力
    LOG4CXX_TRACE(logger, "アプリケーションを開始します");
    LOG4CXX_DEBUG(logger, "デバッグ情報: システム初期化完了");
    LOG4CXX_INFO(logger, "情報: ユーザーログイン成功");
    LOG4CXX_WARN(logger, "警告: メモリ使用量が高くなっています");
    LOG4CXX_ERROR(logger, "エラー: データベース接続に失敗");
    LOG4CXX_FATAL(logger, "致命的エラー: システムを停止します");

    return 0;
}

ログレベル制御とフィルタリング

#include <log4cxx/logger.h>
#include <log4cxx/loglevel.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/configurator.h>
#include <log4cxx/initializer.h>

void printAllLogLevels(log4cxx::Logger const & logger)
{
    LOG4CXX_TRACE(logger, "TRACE メッセージ - 最詳細デバッグ情報");
    LOG4CXX_DEBUG(logger, "DEBUG メッセージ - デバッグ情報");
    LOG4CXX_INFO(logger, "INFO メッセージ - 一般情報");
    LOG4CXX_WARN(logger, "WARN メッセージ - 警告");
    LOG4CXX_ERROR(logger, "ERROR メッセージ - エラー");
    LOG4CXX_FATAL(logger, "FATAL メッセージ - 致命的エラー");
}

void testLogLevel(log4cxx::LogLevel level, const std::string& levelName)
{
    log4cxx::Logger logger = log4cxx::Logger::getInstance(
        LOG4CPLUS_TEXT("TestLogger"));

    // ログレベルの設定
    logger.setLogLevel(level);

    std::cout << "=== " << levelName << " レベルでのテスト ===" << std::endl;
    printAllLogLevels(logger);
    std::cout << std::endl;
}

int main()
{
    log4cxx::Initializer initializer;
    log4cxx::BasicConfigurator config;
    config.configure();

    // 各ログレベルでのテスト
    testLogLevel(log4cxx::TRACE_LOG_LEVEL, "TRACE");
    testLogLevel(log4cxx::DEBUG_LOG_LEVEL, "DEBUG");
    testLogLevel(log4cxx::INFO_LOG_LEVEL, "INFO");
    testLogLevel(log4cxx::WARN_LOG_LEVEL, "WARN");
    testLogLevel(log4cxx::ERROR_LOG_LEVEL, "ERROR");
    testLogLevel(log4cxx::FATAL_LOG_LEVEL, "FATAL");

    // 条件付きログ実行の例
    log4cxx::Logger mainLogger = log4cxx::Logger::getInstance(
        LOG4CPLUS_TEXT("MainApp"));
    
    if (mainLogger.isDebugEnabled()) {
        // DEBUGレベルが有効な場合のみ実行される重い処理
        std::string expensiveDebugInfo = generateExpensiveDebugInfo();
        LOG4CXX_DEBUG(mainLogger, "詳細デバッグ情報: " << expensiveDebugInfo);
    }

    return 0;
}

std::string generateExpensiveDebugInfo() {
    // 時間のかかるデバッグ情報生成をシミュレート
    std::stringstream ss;
    for (int i = 0; i < 1000; ++i) {
        ss << "Item " << i << " ";
    }
    return ss.str();
}

XML設定ファイルの使用

// main.cpp
#include <log4cxx/logger.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/initializer.h>

int main()
{
    log4cxx::Initializer initializer;

    // XML設定ファイルの読み込み
    log4cxx::xml::DOMConfigurator::configure("log4cxx.xml");

    // 複数のロガーを使用
    log4cxx::Logger rootLogger = log4cxx::Logger::getRootLogger();
    log4cxx::Logger appLogger = log4cxx::Logger::getLogger("app");
    log4cxx::Logger dbLogger = log4cxx::Logger::getLogger("app.database");
    log4cxx::Logger netLogger = log4cxx::Logger::getLogger("app.network");

    // アプリケーションログ
    LOG4CXX_INFO(appLogger, "アプリケーション開始");
    LOG4CXX_DEBUG(appLogger, "設定ファイル読み込み完了");

    // データベースログ
    LOG4CXX_INFO(dbLogger, "データベース接続確立");
    LOG4CXX_WARN(dbLogger, "接続プールの使用率: 85%");
    LOG4CXX_ERROR(dbLogger, "SQLクエリ実行失敗: タイムアウト");

    // ネットワークログ
    LOG4CXX_INFO(netLogger, "APIサーバー接続成功");
    LOG4CXX_DEBUG(netLogger, "HTTPリクエスト送信: GET /api/users");
    LOG4CXX_WARN(netLogger, "レスポンス時間遅延: 2.5秒");

    LOG4CXX_INFO(appLogger, "アプリケーション終了");

    return 0;
}
<!-- log4cxx.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<log4cxx:configuration xmlns:log4cxx="http://logging.apache.org/log4cxx">

  <!-- コンソールアペンダー -->
  <appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1} - %m%n"/>
    </layout>
  </appender>

  <!-- アプリケーション用ファイルアペンダー -->
  <appender name="appFile" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="logs/application.log"/>
    <param name="MaxFileSize" value="10MB"/>
    <param name="MaxBackupIndex" value="5"/>
    <param name="Append" value="true"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{ISO8601} [%t] %-5p %c - %m%n"/>
    </layout>
  </appender>

  <!-- データベース専用ファイルアペンダー -->
  <appender name="dbFile" class="org.apache.log4j.DailyRollingFileAppender">
    <param name="File" value="logs/database.log"/>
    <param name="DatePattern" value="'.'yyyy-MM-dd"/>
    <param name="Append" value="true"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %-5p [%c{2}] %m%n"/>
    </layout>
  </appender>

  <!-- ロガー設定 -->
  <logger name="app">
    <level value="INFO"/>
    <appender-ref ref="appFile"/>
    <appender-ref ref="console"/>
  </logger>

  <logger name="app.database">
    <level value="DEBUG"/>
    <appender-ref ref="dbFile"/>
  </logger>

  <logger name="app.network">
    <level value="WARN"/>
  </logger>

  <!-- ルートロガー -->
  <root>
    <level value="ERROR"/>
    <appender-ref ref="console"/>
  </root>

</log4cxx:configuration>

高度な設定とカスタマイズ

#include <log4cxx/logger.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/appender.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/layout.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/initializer.h>

// カスタムログフィルター
class PerformanceFilter : public log4cxx::spi::Filter
{
public:
    FilterDecision decide(const log4cxx::spi::LoggingEventPtr& event) const override
    {
        // パフォーマンス関連のメッセージのみ通す
        std::string message = event->getMessage();
        if (message.find("performance") != std::string::npos ||
            message.find("timing") != std::string::npos) {
            return FilterDecision::ACCEPT;
        }
        return FilterDecision::DENY;
    }
};

int main()
{
    log4cxx::Initializer initializer;

    // プログラマティック設定
    log4cxx::helpers::Pool pool;

    // パターンレイアウトの作成
    log4cxx::PatternLayoutPtr layout(new log4cxx::PatternLayout());
    layout->setConversionPattern(
        LOG4CXX_STR("%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{2} (%F:%L) - %m%n"));
    layout->activateOptions(pool);

    // ファイルアペンダーの作成
    log4cxx::FileAppenderPtr fileAppender(new log4cxx::FileAppender());
    fileAppender->setName(LOG4CXX_STR("FileAppender"));
    fileAppender->setFile(LOG4CXX_STR("logs/custom.log"));
    fileAppender->setAppend(true);
    fileAppender->setLayout(layout);
    fileAppender->activateOptions(pool);

    // カスタムフィルターの追加
    fileAppender->addFilter(log4cxx::spi::FilterPtr(new PerformanceFilter()));

    // コンソールアペンダーの作成
    log4cxx::ConsoleAppenderPtr consoleAppender(new log4cxx::ConsoleAppender());
    consoleAppender->setName(LOG4CXX_STR("ConsoleAppender"));
    consoleAppender->setTarget(LOG4CXX_STR("System.out"));
    
    // 色付きレイアウト(簡易版)
    log4cxx::PatternLayoutPtr colorLayout(new log4cxx::PatternLayout());
    colorLayout->setConversionPattern(
        LOG4CXX_STR("\\033[36m%d{HH:mm:ss}\\033[0m [\\033[35m%t\\033[0m] \\033[1m%-5p\\033[0m %c - %m%n"));
    colorLayout->activateOptions(pool);
    consoleAppender->setLayout(colorLayout);
    consoleAppender->activateOptions(pool);

    // ロガーの設定
    log4cxx::Logger rootLogger = log4cxx::Logger::getRootLogger();
    rootLogger.addAppender(fileAppender);
    rootLogger.addAppender(consoleAppender);
    rootLogger.setLevel(log4cxx::Level::getDebug());

    // カスタムロガーの作成
    log4cxx::Logger perfLogger = log4cxx::Logger::getLogger("performance");
    perfLogger.setLevel(log4cxx::Level::getTrace());

    // ログ出力テスト
    LOG4CXX_INFO(rootLogger, "カスタム設定による初期化完了");
    LOG4CXX_DEBUG(rootLogger, "デバッグモードが有効です");
    
    // パフォーマンスログ(フィルターを通過)
    LOG4CXX_INFO(perfLogger, "performance: 処理時間 123ms");
    LOG4CXX_WARN(perfLogger, "timing: レスポンス遅延検出");
    
    // 通常ログ(フィルターで除外される)
    LOG4CXX_INFO(perfLogger, "通常メッセージ - フィルターで除外");

    return 0;
}

エラーハンドリングとトラブルシューティング

#include <log4cxx/logger.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/initializer.h>
#include <iostream>
#include <exception>

// カスタム例外クラス
class DatabaseException : public std::exception
{
public:
    DatabaseException(const std::string& message) : message_(message) {}
    const char* what() const noexcept override { return message_.c_str(); }
private:
    std::string message_;
};

// 安全なロガー初期化
bool initializeLogging(const std::string& configFile)
{
    try {
        log4cxx::xml::DOMConfigurator::configure(configFile);
        return true;
    }
    catch (const log4cxx::helpers::Exception& e) {
        std::cerr << "log4cxx設定エラー: " << e.what() << std::endl;
        return false;
    }
    catch (const std::exception& e) {
        std::cerr << "設定ファイル読み込みエラー: " << e.what() << std::endl;
        return false;
    }
}

// 例外処理とログ出力
void processDatabase()
{
    log4cxx::Logger logger = log4cxx::Logger::getLogger("app.database");
    
    try {
        LOG4CXX_INFO(logger, "データベース処理開始");
        
        // データベース操作をシミュレート
        bool connectionFailed = true;  // 実際の条件に置き換え
        if (connectionFailed) {
            throw DatabaseException("接続タイムアウト: サーバーが応答しません");
        }
        
        LOG4CXX_INFO(logger, "データベース処理正常完了");
    }
    catch (const DatabaseException& e) {
        LOG4CXX_ERROR(logger, "データベースエラー: " << e.what());
        
        // スタックトレース情報の追加
        LOG4CXX_DEBUG(logger, "エラー発生箇所: " << __FILE__ << ":" << __LINE__);
        
        // リトライロジック
        LOG4CXX_WARN(logger, "5秒後に再試行します...");
        throw;  // 上位レイヤーに例外を再送出
    }
    catch (const std::exception& e) {
        LOG4CXX_FATAL(logger, "予期しないエラー: " << e.what());
        throw;
    }
}

// ログローテーションとクリーンアップ
class LogManager
{
private:
    log4cxx::Logger logger_;
    
public:
    LogManager() : logger_(log4cxx::Logger::getLogger("LogManager")) 
    {
        LOG4CXX_INFO(logger_, "ログマネージャー初期化");
    }
    
    ~LogManager()
    {
        LOG4CXX_INFO(logger_, "ログマネージャー終了処理");
        // log4cxxのシャットダウンは自動的に行われる
    }
    
    void forceLogRotation()
    {
        LOG4CXX_INFO(logger_, "手動ログローテーション実行");
        // 実装はアペンダーの種類に依存
    }
    
    void checkLogFileSize()
    {
        // ログファイルサイズのチェック例
        LOG4CXX_DEBUG(logger_, "ログファイルサイズをチェック中...");
        
        // 実際のファイルサイズチェックロジック
        long fileSize = getLogFileSize();
        if (fileSize > 100 * 1024 * 1024) {  // 100MB
            LOG4CXX_WARN(logger_, "ログファイルサイズが大きくなっています: " 
                        << fileSize << " bytes");
        }
    }
    
private:
    long getLogFileSize() {
        // 実際の実装では stat() などを使用
        return 50 * 1024 * 1024;  // 50MB をシミュレート
    }
};

int main()
{
    log4cxx::Initializer initializer;
    
    // 段階的な初期化とエラーハンドリング
    if (!initializeLogging("log4cxx.xml")) {
        std::cerr << "フォールバック: 基本設定を使用します" << std::endl;
        log4cxx::BasicConfigurator::configure();
    }
    
    log4cxx::Logger mainLogger = log4cxx::Logger::getRootLogger();
    LOG4CXX_INFO(mainLogger, "アプリケーション開始");
    
    // ログマネージャーの使用
    LogManager logManager;
    
    try {
        processDatabase();
    }
    catch (const std::exception& e) {
        LOG4CXX_FATAL(mainLogger, "致命的エラーによりアプリケーションを終了: " << e.what());
        return 1;
    }
    
    // 定期的なメンテナンス
    logManager.checkLogFileSize();
    
    LOG4CXX_INFO(mainLogger, "アプリケーション正常終了");
    return 0;
}

プロダクション環境での最適化

#include <log4cxx/logger.h>
#include <log4cxx/loggingmacros.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/helpers/properties.h>
#include <log4cxx/mdc.h>
#include <log4cxx/ndc.h>
#include <log4cxx/initializer.h>
#include <thread>
#include <chrono>

// パフォーマンス測定用クラス
class PerformanceTimer
{
private:
    std::chrono::high_resolution_clock::time_point start_;
    log4cxx::Logger logger_;
    std::string operation_;

public:
    PerformanceTimer(const std::string& operation) 
        : start_(std::chrono::high_resolution_clock::now())
        , logger_(log4cxx::Logger::getLogger("performance"))
        , operation_(operation)
    {
        LOG4CXX_DEBUG(logger_, operation_ << " 開始");
    }
    
    ~PerformanceTimer()
    {
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start_);
        
        if (duration.count() > 1000) {  // 1秒以上の場合は警告
            LOG4CXX_WARN(logger_, operation_ << " 完了 (遅延: " << duration.count() << "ms)");
        } else {
            LOG4CXX_INFO(logger_, operation_ << " 完了 (" << duration.count() << "ms)");
        }
    }
};

// マルチスレッド対応ログ処理
void workerThread(int threadId)
{
    // スレッド固有の診断コンテキスト
    log4cxx::NDC::push("WorkerThread-" + std::to_string(threadId));
    log4cxx::MDC::put("threadId", std::to_string(threadId));
    
    log4cxx::Logger logger = log4cxx::Logger::getLogger("worker");
    
    LOG4CXX_INFO(logger, "ワーカースレッド開始");
    
    for (int i = 0; i < 5; ++i) {
        // MDCによるコンテキスト情報追加
        log4cxx::MDC::put("iteration", std::to_string(i));
        
        {
            PerformanceTimer timer("DB Query " + std::to_string(i));
            
            // データベースクエリをシミュレート
            std::this_thread::sleep_for(std::chrono::milliseconds(100 + (i * 200)));
            
            LOG4CXX_DEBUG(logger, "クエリ実行: SELECT * FROM users WHERE id = " << i);
        }
        
        // 条件付きログ出力(パフォーマンス最適化)
        if (logger.isTraceEnabled()) {
            std::string debugInfo = "詳細情報生成: Thread=" + std::to_string(threadId) 
                                  + ", Iteration=" + std::to_string(i);
            LOG4CXX_TRACE(logger, debugInfo);
        }
    }
    
    LOG4CXX_INFO(logger, "ワーカースレッド終了");
    
    // クリーンアップ
    log4cxx::MDC::remove("threadId");
    log4cxx::MDC::remove("iteration");
    log4cxx::NDC::pop();
}

// リソース監視とアラート
class SystemMonitor
{
private:
    log4cxx::Logger logger_;
    std::thread monitorThread_;
    bool running_;

public:
    SystemMonitor() 
        : logger_(log4cxx::Logger::getLogger("monitor"))
        , running_(true)
    {
        LOG4CXX_INFO(logger_, "システム監視開始");
        monitorThread_ = std::thread(&SystemMonitor::monitorLoop, this);
    }
    
    ~SystemMonitor()
    {
        running_ = false;
        if (monitorThread_.joinable()) {
            monitorThread_.join();
        }
        LOG4CXX_INFO(logger_, "システム監視終了");
    }

private:
    void monitorLoop()
    {
        log4cxx::NDC::push("SystemMonitor");
        
        while (running_) {
            checkMemoryUsage();
            checkCpuUsage();
            checkDiskSpace();
            
            std::this_thread::sleep_for(std::chrono::seconds(30));
        }
        
        log4cxx::NDC::pop();
    }
    
    void checkMemoryUsage()
    {
        // メモリ使用量シミュレート (実際は /proc/meminfo 等を使用)
        double memoryUsage = 67.5;
        
        log4cxx::MDC::put("memoryUsage", std::to_string(memoryUsage));
        
        if (memoryUsage > 90.0) {
            LOG4CXX_ERROR(logger_, "メモリ使用量が危険水準: " << memoryUsage << "%");
        } else if (memoryUsage > 80.0) {
            LOG4CXX_WARN(logger_, "メモリ使用量が高くなっています: " << memoryUsage << "%");
        } else {
            LOG4CXX_DEBUG(logger_, "メモリ使用量正常: " << memoryUsage << "%");
        }
        
        log4cxx::MDC::remove("memoryUsage");
    }
    
    void checkCpuUsage()
    {
        double cpuUsage = 45.2;
        log4cxx::MDC::put("cpuUsage", std::to_string(cpuUsage));
        
        if (cpuUsage > 95.0) {
            LOG4CXX_FATAL(logger_, "CPU使用率が限界: " << cpuUsage << "%");
        } else if (cpuUsage > 80.0) {
            LOG4CXX_WARN(logger_, "CPU使用率が高い: " << cpuUsage << "%");
        }
        
        log4cxx::MDC::remove("cpuUsage");
    }
    
    void checkDiskSpace()
    {
        double diskUsage = 72.1;
        log4cxx::MDC::put("diskUsage", std::to_string(diskUsage));
        
        if (diskUsage > 90.0) {
            LOG4CXX_ERROR(logger_, "ディスク容量不足: " << diskUsage << "%");
        } else {
            LOG4CXX_TRACE(logger_, "ディスク使用量: " << diskUsage << "%");
        }
        
        log4cxx::MDC::remove("diskUsage");
    }
};

int main()
{
    log4cxx::Initializer initializer;
    
    // プロダクション設定の読み込み
    try {
        log4cxx::xml::DOMConfigurator::configureAndWatch("production-log4cxx.xml", 60000);  // 60秒間隔で設定監視
    } catch (...) {
        std::cerr << "設定ファイル読み込み失敗、基本設定を使用" << std::endl;
        log4cxx::BasicConfigurator::configure();
    }
    
    log4cxx::Logger appLogger = log4cxx::Logger::getLogger("application");
    
    // アプリケーション情報をMDCに設定
    log4cxx::MDC::put("version", "1.0.0");
    log4cxx::MDC::put("environment", "production");
    log4cxx::MDC::put("hostname", "web-server-01");
    
    LOG4CXX_INFO(appLogger, "プロダクションアプリケーション開始");
    
    // システム監視開始
    SystemMonitor monitor;
    
    // マルチスレッド処理
    std::vector<std::thread> workers;
    for (int i = 0; i < 3; ++i) {
        workers.emplace_back(workerThread, i);
    }
    
    // メインループシミュレート
    for (int i = 0; i < 10; ++i) {
        PerformanceTimer timer("MainLoop-" + std::to_string(i));
        
        LOG4CXX_INFO(appLogger, "メインループ実行中: " << i);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    
    // スレッド終了待ち
    for (auto& worker : workers) {
        worker.join();
    }
    
    LOG4CXX_INFO(appLogger, "全スレッド処理完了");
    
    // MDCクリーンアップ
    log4cxx::MDC::clear();
    
    LOG4CXX_INFO(appLogger, "アプリケーション正常終了");
    
    return 0;
}