Edited at

C++のLoggingライブラリ plog

札幌C++勉強会の もくもく会#10でもくもくと調べていたことをここに記す。本家Readme.mdを読んで、そのままメモっただけ。


Plog - portable and simple log for C++

小さくまとまっているログ出力ライブラリ。


インストール

header-onlyなのでgithubからダウンロードしてインクルードパス通すだけです。

$ git clone https://github.com/SergiusTheBest/plog.git

たとえばビルドツールにSConstructを使うなら


SConstruct

 # SConstruct

Program("hello_plog", "hello_plog.cpp", CPPPATH="plog/include")


hello_plog.cpp

#include<plog/Log.h>


int main() {
plog::init(plog::debug, "Output.txt");

LOG_DEBUG << "Hello, plog!";
return 0;
}


コンパイル

$ scons

出力はこんな感じになります


Output.txt

2016-02-15 20:34:51.006 DEBUG [14279] [main@6] Hello, plog!


日付、ログタイプ(この例ではDEBUG)、行番号、メッセージがでます。

他にCSV形式とかカスタムフォーマットも作れるみたいです。


Severityの指定

Severityを指定することで、指定したレベル以上のログだけを出すことができます。

Severityは次のものがあります。

enum Severity

{
none = 0,
fatal = 1,
error = 2,
warning = 3,
info = 4,
debug = 5,
verbose = 6
};

(Severityだとfatalの数値の方が大きくなるべきなんじゃないかなあ・・)

ログ出力時におけるSeverityレベルの指定方法は、次の3つです。


  1. shortマクロ

  2. longマクロ

  3. 関数っぽく引数で指定

#include<plog/Log.h>

int main() {
plog::init(plog::debug, "Output.txt");
LOGD << "Hello, plog!"; // 1. shortマクロ
LOG_DEBUG << "Hello, plog!"; // 2. longマクロ
LOG(plog::debug) << "Hello, plog!"; // 3. 関数っぽく引数で指定
return 0;
}

DEBUG以外のSeverityを指定するときは、Longマクロなら(DEBUGも含めSeverityの順に)

LOG_VERBOSE, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_FATAL

で、これらに対応するShortマクロは

LOGV, LOGD, LOGI, LOGW, LOGE, LOGF

です。

出力したいSeverityのレベルはplogの初期化時に指定します。

例えば、

#include<plog/Log.h>

int main() {
plog::init(plog::warning, "Output.txt"); // warning以上を出力させる。
LOGV << "verbose";
LOGD << "debug";
LOGI << "info";
LOGW << "warning";
LOGE << "error";
LOGF << "fatal";
return 0;
}

というコードを書くと、出力は


Output.txt

2016-02-15 21:32:12.920 WARN  [14455] [main@7] warning

2016-02-15 21:32:12.920 ERROR [14455] [main@8] error
2016-02-15 21:32:12.920 FATAL [14455] [main@9] fatal

となります。Severityがwarning以上のログだけが出ていますね。


CSV形式での出力

出力ファイル名の拡張子を.csvにするとCSV形式で出力してくれます。ただし(デフォルトの)区切り文字はカンマではなくセミコロンです。

plog::init(plog::warning, "Output.csv");

// 他は上記コードと同じ


Output.csv

Date;Time;Severity;TID;This;Function;Message

2016/02/15;21:38:51.297;WARN;14492;0;main@7;"warning"
2016/02/15;21:38:51.298;ERROR;14492;0;main@8;"error"
2016/02/15;21:38:51.298;FATAL;14492;0;main@9;"fatal"

ちなみに、拡張子を変えてフォーマットが変わるのは.csvだけです。


条件式でログ出力を切り替える

条件式付きでログ出力することができます。

LOG_DEBUG_IF(cond) << "debug";         // longマクロ

LOGD_IF(cond) << "debug"; // shortマクロ
LOG_IF(plog::debug, cond) << "debug"; // 関数っぽく

plogのソース追っていくと結局

if (condition) LOG_(instance, severity)

とif文に展開するマクロに落ちていたので、ありがたみがあるかは人それぞれな気もします。。

複数のログを出したいときは、スコープでまとめることができます。

IF_LOG(plog::debug) // Severityがdebug以上のときはこのスコープ内を実行する

{
for (int i = 0; i < vec.size(); ++i)
{
LOGD << "vec[" << i << "]: " << vec[i];
}
}

やっぱりif文に展開するマクロに、、(ry


途中でログファイルに出力するSeverityレベルを変える場合

通常は初期化時にログの出力レベルを指定します

plog::init(plog::warning, "Output.txt");

しかし、初期化時以外で指定したかったり、途中で変更したい時があるかもしれません。そういうときは、次のようにします。

plog::get()->setMaxSeverity(plog::debug);


ログをターミナル(コンソール)に出力したい場合。

ログの出力先をファイルではなく、標準出力にしたいことがあるかもしれません。そんな時は初期化でファイル名ではなく、Appenderを指定します。コンソールに色付きで出力するAppenderは次のように指定します。

#include<plog/Log.h>

#include<plog/Appenders/ColorConsoleAppender.h>

int main() {
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
plog::init(plog::debug, &consoleAppender);
LOGD << "debug message to stdout with color";
return 0;
}

注意! このようにAppenderはstaticで宣言すべきです。

出力がカラーである必要がない場合は、ConsoleAppenderもあります。


複数の出力先を指定したい場合

コンソールとファイルの両方に出力したい場合もあるかもしれません。そんな時はAppenderを追加することができます。

#include<plog/Log.h>

#include<plog/Appenders/ColorConsoleAppender.h>

int main() {
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
static plog::RollingFileAppender<plog::TxtFormatter> fileAppender("Output.txt");
plog::init(plog::debug, &consoleAppender).addAppender(&fileAppender);
LOGD << "debug message to stdout and file";
return 0;
}


その他

もくもく会の終了時刻になったためこれで終わり。