Google glog

Googleによる堅牢なC++ロギングライブラリ。クラッシュハンドリング機能(SIGSEGV、SIGILL、SIGFPE等)を持つ唯一のライブラリとして特徴的。シンプルで堅牢なスタンドアローンアプリケーション向け。G2logの後継として開発された。

ロギングC++Googleスレッドセーフマクロベース

GitHub概要

google/glog

C++ implementation of the Google logging module

スター7,316
ウォッチ265
フォーク2,095
作成日:2015年2月23日
言語:C++
ライセンス:BSD 3-Clause "New" or "Revised" License

トピックス

なし

スター履歴

google/glog Star History
データ取得日時: 2025/7/17 08:20

ライブラリ

glog

概要

glogはGoogleが開発したC++向けのロギングライブラリです。シンプルで効率的なAPIを提供し、ログレベル制御、条件付きログ出力、カスタムプレフィックス、自動ログクリーニング機能を備えています。スレッドセーフで高性能な設計により、大規模なアプリケーションでの使用に適しており、GoogleのプロダクションシステムでAD内で広く使用されている実績のあるライブラリです。CHECKマクロによるアサーション機能も提供し、デバッグとプロダクション両方で有用です。

詳細

glogは2008年にGoogleによって開発され、現在もアクティブに開発が続けられているC++ロギングライブラリです。LOG、VLOG、CHECKなどの直感的なマクロベースのAPIを特徴とし、ログレベル(INFO、WARNING、ERROR、FATAL)による階層的なログ管理を提供します。VLOGによる冗長ログ制御、LOG_IF/LOG_EVERY_N等の条件付きログ、カスタムプレフィックスフォーマッター、自動スタックトレース出力、シグナルハンドリング機能など、エンタープライズレベルの要求に応える包括的な機能セットを搭載しています。

主な特徴

  • マクロベースAPI: LOG、VLOG、CHECKなどの直感的で使いやすいマクロ
  • 階層的ログレベル: INFO、WARNING、ERROR、FATALによる体系的なログ管理
  • VLOG冗長制御: --vフラグによるデバッグログの細かい制御
  • 条件付きログ: LOG_IF、LOG_EVERY_N、LOG_FIRST_Nなどの効率的なログ制御
  • CHECKアサーション: プログラムの事前条件・事後条件チェック機能
  • カスタムシンク: LogSinkインターフェースによる柔軟な出力先制御

メリット・デメリット

メリット

  • Googleプロダクションでの実績による高い信頼性と安定性
  • シンプルで直感的なマクロAPIによる高い開発効率
  • VLOGによる段階的なデバッグログ制御で効率的なデバッグ
  • 豊富な条件付きログ機能によるパフォーマンス最適化
  • CHECKマクロによる堅牢なエラーハンドリング
  • CMake、Bazel、vcpkg等の主要ビルドシステム対応

デメリット

  • C++専用でマルチ言語環境での統一が困難
  • 基本的には同期ログのため、高負荷時のパフォーマンス制約
  • ログフォーマットのカスタマイズ性がやや限定的
  • FATALログによるプログラム終了が予期しない動作を引き起こす場合がある
  • Windows環境ではERRORマクロの競合に注意が必要
  • デフォルトではログローテーション機能が無く、外部ツールが必要

参考ページ

書き方の例

基本セットアップ

#include <glog/logging.h>

int main(int argc, char* argv[]) {
    // glogの初期化(通常はプログラム名を渡す)
    google::InitGoogleLogging(argv[0]);
    
    // 基本的なログ設定
    FLAGS_logtostderr = 1;  // 標準エラー出力にログを出力
    FLAGS_log_dir = "./logs/";  // ログディレクトリの設定
    
    LOG(INFO) << "glog initialized successfully";
    
    // glogは通常、プログラム終了時に自動的にクリーンアップされる
    return 0;
}

基本的なログ出力

#include <glog/logging.h>

void basicLogging() {
    // 基本的なログレベル
    LOG(INFO) << "アプリケーションが開始されました";
    LOG(WARNING) << "警告: 設定ファイルが見つかりません";
    LOG(ERROR) << "エラー: データベース接続に失敗";
    
    // FATALログ(プログラムを終了させる)
    // LOG(FATAL) << "致命的エラーが発生しました";  // この行でプログラム終了
    
    // 条件付きログ
    int num_users = 150;
    LOG_IF(INFO, num_users > 100) << "多数のユーザーが接続中: " << num_users;
    
    // 一定回数ごとのログ(パフォーマンス向上)
    for (int i = 0; i < 1000; ++i) {
        LOG_EVERY_N(INFO, 100) << "100回に1回のログ: " << google::COUNTER;
    }
    
    // 最初のN回だけのログ
    for (int i = 0; i < 1000; ++i) {
        LOG_FIRST_N(INFO, 5) << "最初の5回だけ: " << google::COUNTER;
    }
    
    // 時間ベースの制限付きログ
    LOG_EVERY_T(INFO, 2.0) << "2秒に1回程度のログ";
}

高度な設定(VLOG、CHECKマクロ、カスタム設定)

#include <glog/logging.h>

void advancedLogging() {
    // VLOG (Verbose Logging) - --vフラグで制御
    VLOG(1) << "詳細レベル1のデバッグ情報";
    VLOG(2) << "詳細レベル2のより細かいデバッグ情報";
    VLOG(3) << "詳細レベル3の非常に詳細な情報";
    
    // VLOG条件付きマクロ
    bool debug_mode = true;
    VLOG_IF(1, debug_mode) << "デバッグモードが有効な場合のみ出力";
    VLOG_EVERY_N(2, 10) << "10回に1回、VLOGレベル2で出力";
    
    // VLOGが有効かどうかのチェック
    if (VLOG_IS_ON(2)) {
        // 高コストな処理(VLOGレベル2以上でのみ実行)
        std::string expensive_debug_info = calculateDebugInfo();
        VLOG(2) << "高コストなデバッグ情報: " << expensive_debug_info;
    }
    
    // CHECKマクロ(アサーション)
    int* ptr = getData();
    CHECK(ptr != nullptr) << "データポインタがnullです";
    CHECK_NOTNULL(ptr);  // ptrを返す(nullでない場合)
    
    // 比較CHECK
    int expected = 42;
    int actual = calculateValue();
    CHECK_EQ(expected, actual) << "期待値と実際の値が異なります";
    CHECK_NE(0, actual) << "値が0になってはいけません";
    CHECK_LT(actual, 100) << "値が100以上になっています";
    CHECK_LE(actual, 99) << "値が99を超えています";
    CHECK_GT(actual, 0) << "値が0以下になっています";
    CHECK_GE(actual, 1) << "値が1未満になっています";
    
    // 文字列比較CHECK
    const char* result = getResult();
    CHECK_STREQ(result, "success") << "処理が成功していません";
    CHECK_STRNE(result, "error") << "エラーが発生しています";
    
    // デバッグビルドでのみ有効なDLOG
    DLOG(INFO) << "デバッグビルドでのみ表示されるログ";
    DLOG_IF(INFO, condition) << "デバッグビルド + 条件付きログ";
}

// カスタムプレフィックスフォーマッター
void MyPrefixFormatter(std::ostream& s, const google::LogMessage& m, void* /*data*/) {
    s << "[" << m.time().year() + 1900 
      << "-" << std::setw(2) << std::setfill('0') << m.time().month() + 1
      << "-" << std::setw(2) << std::setfill('0') << m.time().day()
      << " " << std::setw(2) << std::setfill('0') << m.time().hour()
      << ":" << std::setw(2) << std::setfill('0') << m.time().min()
      << ":" << std::setw(2) << std::setfill('0') << m.time().sec()
      << "." << std::setw(6) << std::setfill('0') << m.time().usec()
      << "] [" << google::GetLogSeverityName(m.severity())[0]
      << "] [" << m.thread_id() << "] "
      << m.basename() << ":" << m.line() << "]";
}

void customConfiguration() {
    // カスタムプレフィックスフォーマッターの設定
    google::InstallPrefixFormatter(&MyPrefixFormatter);
    
    // ログクリーニング機能の有効化(C++20以降)
    using namespace std::chrono_literals;
    google::EnableLogCleaner(3 * 24h);  // 3日間ログを保持
    
    LOG(INFO) << "カスタム設定が適用されました";
}

エラーハンドリングとカスタムシンク

#include <glog/logging.h>

// カスタム失敗処理関数
void MyFailureFunction() {
    std::cerr << "FATAL error detected, performing cleanup..." << std::endl;
    // クリーンアップ処理
    cleanup_resources();
    exit(EXIT_FAILURE);
}

// カスタムログシンクの実装
class CustomLogSink : public google::LogSink {
public:
    void send(google::LogSeverity severity, const char* full_filename,
              const char* base_filename, int line,
              const google::LogMessageTime& time, const char* message,
              size_t message_len) override {
        
        // カスタムログ処理
        if (severity >= google::GLOG_ERROR) {
            // エラーレベル以上の場合は外部監視システムに通知
            sendToMonitoringSystem(severity, message, message_len);
        }
        
        // データベースへのログ記録
        logToDatabase(severity, base_filename, line, time, message);
        
        // メール通知(FATAL時のみ)
        if (severity == google::GLOG_FATAL) {
            sendEmailAlert(message, message_len);
        }
    }
    
private:
    void sendToMonitoringSystem(google::LogSeverity severity, 
                              const char* message, size_t len) {
        // 監視システムへの通知実装
    }
    
    void logToDatabase(google::LogSeverity severity, 
                      const char* filename, int line,
                      const google::LogMessageTime& time, 
                      const char* message) {
        // データベースログ実装
    }
    
    void sendEmailAlert(const char* message, size_t len) {
        // メール通知実装
    }
};

int main(int argc, char* argv[]) {
    google::InitGoogleLogging(argv[0]);
    
    // カスタム失敗処理関数を設定
    google::InstallFailureFunction(&MyFailureFunction);
    
    // カスタムログシンクを追加
    CustomLogSink custom_sink;
    google::AddLogSink(&custom_sink);
    
    try {
        // アプリケーション処理
        performCriticalOperation();
        
    } catch (const std::exception& e) {
        LOG(ERROR) << "例外が発生: " << e.what();
        // プログラムは継続
    }
    
    // 重要: カスタムシンクを削除
    google::RemoveLogSink(&custom_sink);
    
    return 0;
}

実用例(Webサーバーアプリケーション)

#include <glog/logging.h>
#include <thread>
#include <chrono>

class WebServerLogger {
public:
    static void initialize(const std::string& program_name) {
        google::InitGoogleLogging(program_name.c_str());
        
        // 設定フラグ
        FLAGS_log_dir = "./logs";
        FLAGS_max_log_size = 100;  // 100MB
        FLAGS_stop_logging_if_full_disk = true;
        
        // エラーレベル以上のログをstderrにも出力
        FLAGS_alsologtostderr = true;
        FLAGS_stderrthreshold = google::GLOG_ERROR;
        
        // ログクリーニング設定
        using namespace std::chrono_literals;
        google::EnableLogCleaner(7 * 24h);  // 1週間保持
        
        LOG(INFO) << "Web server logging initialized";
    }
    
    static void logRequest(const std::string& client_ip, 
                          const std::string& method,
                          const std::string& path,
                          int status_code,
                          std::chrono::milliseconds response_time) {
        
        // アクセスログ
        LOG(INFO) << "REQUEST: " << client_ip << " " << method << " " << path
                  << " " << status_code << " " << response_time.count() << "ms";
        
        // 異常なレスポンス時間の警告
        LOG_IF(WARNING, response_time.count() > 1000) 
            << "Slow response detected: " << response_time.count() << "ms for " << path;
        
        // エラーステータスコードのログ
        LOG_IF(ERROR, status_code >= 500) 
            << "Server error: " << status_code << " for " << path;
        LOG_IF(WARNING, status_code >= 400 && status_code < 500)
            << "Client error: " << status_code << " for " << path;
    }
    
    static void logError(const std::string& component, 
                        const std::string& error_message,
                        bool is_fatal = false) {
        if (is_fatal) {
            LOG(FATAL) << "[" << component << "] " << error_message;
        } else {
            LOG(ERROR) << "[" << component << "] " << error_message;
        }
    }
    
    static void logPerformanceMetric(const std::string& metric_name, 
                                   double value) {
        // パフォーマンスメトリクスは5分に1回程度に制限
        LOG_EVERY_T(INFO, 300) << "METRIC: " << metric_name << " = " << value;
    }
};

// 使用例
void handleHttpRequest(const std::string& client_ip, 
                      const std::string& method, 
                      const std::string& path) {
    auto start_time = std::chrono::high_resolution_clock::now();
    
    VLOG(1) << "Processing request: " << method << " " << path;
    
    try {
        // リクエスト処理のシミュレーション
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        
        auto end_time = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            end_time - start_time);
        
        // 成功ケース
        WebServerLogger::logRequest(client_ip, method, path, 200, duration);
        
    } catch (const std::exception& e) {
        WebServerLogger::logError("RequestHandler", 
                                 "Request processing failed: " + std::string(e.what()));
        
        auto end_time = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            end_time - start_time);
        
        WebServerLogger::logRequest(client_ip, method, path, 500, duration);
    }
}

int main(int argc, char* argv[]) {
    WebServerLogger::initialize(argv[0]);
    
    LOG(INFO) << "Web server starting up";
    
    // サンプルリクエストの処理
    handleHttpRequest("192.168.1.100", "GET", "/api/users");
    handleHttpRequest("192.168.1.101", "POST", "/api/orders");
    
    // パフォーマンスメトリクスの記録
    WebServerLogger::logPerformanceMetric("cpu_usage", 75.5);
    WebServerLogger::logPerformanceMetric("memory_usage", 1024.0);
    
    LOG(INFO) << "Web server shutting down";
    
    return 0;
}