ロギングシステムは、アプリケーションのロギングに不可欠なツールです。 それを自分で実装したくない人のために、C ++にはすでに数え切れない既製のライブラリ(Log4cplus、Apache log4cxx、Boost.Logなど)がありますが、Easylogging ++は使いやすくコンパクトで、サードパーティのライブラリやインストールは必要ありません。 そのコードはすべて1つのヘッダーファイルに含まれており、アプリケーションコードに含める必要があります。
この記事では、Easylogging ++機能の簡単な概要と、このライブラリの使用例を紹介します。
Easylogging ++の使用がいかに簡単かを示す短い例から始めましょう。
#include "easylogging++.h" _INITIALIZE_EASYLOGGINGPP int main(int argv, char* argc[]) { LOG(INFO) << " Habrahabr"; return 0; }
ライブラリは1つのヘッダーに接続されており、ライブラリは必要ありません。
上記の短い例では、_INITIALIZE_EASYLOGGINGPPマクロの呼び出しにはコメントが必要です。 一部の静的変数を初期化し、キャッシュのハンドラーを設定する必要があります。 ライブラリを使用する前に、呼び出しを1回だけ行う必要があります。
ヘルプ:
- ライブラリサイト: easylogging.org
- ライセンス:MIT
- 言語:C ++ 11
- に依存:-
- プラットフォーム:Windows、Mac OSX、Debian(Ubuntu、Mint)、Fedora
- コンパイラ:GCC 4.7 +、Visual C ++ 11.0 +、Intel C ++ 13.0 +、MinGW、Cygwin
理由:
ライブラリのシンプルさと直感性は魅了します。 単一のヘッダーファイル(プロジェクト間で使いやすい)に収まり、非常に完全な機能セットを提供する他の実装を見つけることができませんでした。
- クロスプラットフォーム
- マルチスレッド
- 出力形式の設定
- カスタムデータ型の発行(STLコンテナーの既製の実装があります)
- ログファイルの切り替え(ローリング)
- 条件付きおよび定期的な発行
- プログラムのクラッシュの確認と処理
- メソッドの実行時間の計算
フォーマット設定
私たちの意見では、ライブラリの主な利点はその自律性、コンパクトさ、シンプルさであるという事実にもかかわらず、その動作に何かを変更する必要がある場合があります。 たとえば、デフォルトでは、出力形式は次のようになります。
11/06/2014 11:23:29,218 INFO [default] Simple info message 11/06/2014 11:23:29,218 ERROR [default] Simple error message 11/06/2014 11:23:29,218 WARN [default] This is just a warning
まず、Easyloggingを使用すると、開発者は表示されるフィールドのセットとその順序をカスタマイズできます。
以下の例は、メッセージタイプを先頭に配置し、次に日付を変更された形式で配置し、呼び出し元のメソッドの署名とメッセージ自体を配置する方法を示しています。
フィールドのカスタマイズ
画面上の結果は次のようになります。
el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Format, "%level %datetime{%H:%m:%s} (%func): %msg"); LOG(INFO) << " ";
画面上の結果は次のようになります。
INFO 11:33:58 (int main(int, char**)):
メッセージの種類、日付、またはファイル名(cpp)などの形式の説明の標準的なものに加えて、独自のマクロを使用してログに追加情報を提供できます。 たとえば、次のように:
自分のフィールド
const char* getMode(void) { switch(mode) { case 1: return "Service"; default: return "App"; } return ""; // just in case } int main(int argv, char* argc[]) { el::Helpers::installCustomFormatSpecifier(el::CustomFormatSpecifier("%mode", getMode)); el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Format, "%level %mode: %msg"); LOG(INFO) << " "; return 0; }
Easyloggingの動作のさまざまな側面を変更する多くのフラグがまだあります。 たとえば、デフォルトでは、すべての出力が標準出力に複製されます。 完全に無効にするのは簡単であるという事実に加えて、反対に、カラー出力を有効にするフラグを設定することで、より視覚的にすることができます。
フラグを設定する
画面上の結果は次のようになります。
int main(int argv, char* argc[]) { /* ( ) */ el::Loggers::reconfigureAllLoggers(el::ConfigurationType::ToStandardOutput, "true"); /* */ el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); LOG(INFO) << " "; LOG(ERROR) << " "; LOG(WARNING) << " "; return 0; }
画面上の結果は次のようになります。
コードからだけでなく、任意の設定を変更できます。さらに、ライブラリは独自の形式の構成ファイル(タブ付きの通常のconf)をサポートしており、アプリケーションの起動または操作中にロードできます。 また、ライブラリはコマンドラインからパラメーターを読み取ることができます。これを行うには、適切な呼び出しをmainに入れます。
コマンドラインを読む
int main(int argv, char* argc[]) { _START_EASYLOGGINGPP(argc, argv); }
カスタムタイプ
このライブラリを使用すると、あらゆるタイプのオブジェクトの内容を記録できます。 これを行うには2つの方法があります。
- 特定のel :: Loggableからオブジェクトを継承し、対応する仮想メソッドを実装します
- 静的メソッド(演算子)を実装して、オブジェクトをログに送信します
2つ目のオプションは、クラスをあいまいな先祖で「ダーティ」にする必要がなく、さらに、ロギングを削除することにした場合、すべてのクラスをクリーンアップする必要がないため、より便利に思えます。 実装が2番目の方法でどのように見えるかを示します。
カスタムタイプ
/* */ class Dummy { public: Dummy(int i, std::string s) : m_Int(i), m_String(s){} int getInt() const{return m_Int;} std::string const& getString() const {return m_String;} private: int m_Int; std::string m_String; }; /* , operator<< */ inline MAKE_LOGGABLE(Dummy, obj, os) { /* */ os << "{i:"<<obj.getInt()<<", s:"<<obj.getString()<<"}"; return os; } int main(void) { Dummy object(1, "Habrahabr"); LOG(INFO) << "Dummy: " << object; return 0; } /* : 11:03:27 INFO Dummy: {i:1, s:Habrahabr} */
ログファイル
デフォルトでは、ログファイルはアプリケーションの作業ディレクトリにあり、パスは../logs/myeasylog.logになります。
ログファイルの名前または場所はいつでも変更できます。 これは、たとえば、毎日新しいファイルに切り替える必要がある場合に便利です。 ログファイルを手動で切り替える例を次に示します。
手動スイッチ
int main(void) { LOG(INFO) << " "; el::Loggers::reconfigureAllLoggers(el::ConfigurationType::Filename, "logs/20140205.log"); LOG(INFO) << " "; return 0; }
これを完了すると、ログフォルダーにmyeasylog.logと20140205.logの2つのファイルが表示されます。 各メッセージは独自のファイルにあります。 「手動」モードでは、特定のアルゴリズムに従ってログを切り替えることも同様に可能であることが容易にわかります(たとえば、毎日のログを作成したり、各ファイルに特定の数のレコードを割り当てたりします)
Easylogging ++はログを自動的に切り替えることができますが、ファイルのサイズにのみ基づいています。 設定により、ファイルサイズのしきい値を設定できます。その後、現在のログがリセットされます。 このイベントが発生する前に、以前のログファイルをコピーする機会が与えられます。 以下は、ファイルサイズに1 KBの制限を設定し、新しいログに切り替える前に古いログをバックアップする例です。
非表示のテキスト
/* . * timestamp.*/ int log_sequence = 1; /* Callback fname */ void LogsRollout(const char* fname, size_t fsize) { /* ( ) */ string fileName = fname; size_t position = fileName.find("."); string extractName = (string::npos == position)? fileName : fileName.substr(0, position); extractName = extractName + to_string(log_sequence++) + ".log"; /* , */ int status = rename(fname, extractName.c_str()); if(status) { /* */ } } int main(void) { /* */ el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); /* 1 */ el::Loggers::reconfigureAllLoggers(el::ConfigurationType::MaxLogFileSize, "1024"); /* callback */ el::Helpers::installPreRollOutCallback(LogsRollout); /* */ for(int i=0; i<1024; i++) { LOG(INFO) << "Message #"<< i+1; } return 0; }
条件付きおよび定期的な発行
指定された条件が満たされた場合にのみ、ログにメッセージを発行するマクロLOG_IFがライブラリで宣言されています。
非表示のテキスト
LOG_IF(true, INFO) << " "; LOG_IF(false, WARNING) << " ";
定期的な発行も多くの場合に役立つ場合があります。 この方法は、すべてのメッセージがログに記録されるのではなく、たとえば、10番目または100番目ごとに記録されることを意味します。 この場合、2つの可能性が実装されます。
- LOG_EVERY_N(n、LEVEL)-n番目ごとのメッセージを表示します
- LOG_AFTER_N(n、LEVEL)-n操作後にのみメッセージを表示します
プログラムのクラッシュの確認と処理
CHECK、CHECK_EQ、CHECK_NE、CHECK_NOTNULLなど、いくつかの重大な条件が満たされない場合にのみ、ログにメッセージを発行して異常終了するマクロがライブラリで宣言されています。 これらのマクロはassertに非常に似ていますが、ロギングがあります。
それらを使用すると非常に便利です。
非表示のテキスト
これは、条件が満たされないときにどのように落ちるかです:
CHECK(true) << " "; CHECK_LE(2, 1) << "2 < 1 ???"; CHECK_STREQ(argv[3], "1") << " 1";
これは、条件が満たされないときにどのように落ちるかです:
07:12:51,375 FATAL Check failed: [2 <= 1] 2 < 1 ??? 07:12:51,375 WARN Aborting application. Reason: Fatal log at [/home/borg/Temp/App/main.cpp:34] Aborted
デフォルト設定を変更しない場合、条件が満たされない場合、プログラムは中断され、FATALレベルでメッセージがログに表示されます。
さらに、ライブラリはデフォルトでアプリケーションのクラッシュを処理します。 もちろん、この動作はオフにすることもできますが、たとえば、SIGFPE、SIGILL、SIGSEGVなど、多数の信号のログを受信すると便利な場合があります。 gccの場合、コールスタックログを発行することもできます。
非表示のテキスト
これが落ちる方法です:
#include "easylogging++.h" _INITIALIZE_EASYLOGGINGPP void CustomCrashHandler(int signal) { LOG(ERROR) << " !!"; /* */ el::Helpers::crashAbort(signal); } int main(int argv, char* argc[]) { /* */ el::Helpers::setCrashHandler(CustomCrashHandler); /* 0 */ int a = 0; a = 1/a; return 0; }
これが落ちる方法です:
17:46:53,074 ERROR !! Aborted
結論
Easylogging ++ライブラリは、このような製品で期待されるほぼ完全な機能セットを提供します。
紛れもない利点には、そのコンパクトさ、操作の容易さ、およびクロスプラットフォームが含まれます。
唯一の欠点は、C ++ 11を使用する必要があることですが、おそらく作成者は「通常の」C ++を使用できます。