[ C++で開発 ]
ロギングライブラリの1つで、Java言語用の有名なオープンソース・ロギングライブラリ log4j をC++言語用に移植したものです。
ロギングの初期化は、プログラムで記述する方法と設定ファイルに記述して読み込ませる方法があります。
ロギング設定をファイルに記述し、プログラムの起動時に読み込みます。設定ファイルの記述には歴史的経緯で2種類の書式があります。
1.の書式は簡易的に用いられ、正式なドキュメントには定義されていません。2.の書式は途中で追加され、log4jと同じ書式です。1.の方法は今後のバージョンで廃止が予定されている”deprecated”なAPIです。
#include <log4cpp/Category.hh> #include <log4cpp/SimpleConfigurator.hh> bool initLog4cpp() { try { log4cpp::SimpleConfigurator::configure("logging.conf"); return true; } catch (log4cpp::ConfigureFailure& ex) { return false; } } int main(int argc, char *argv[]) { bool configured = initLog4cpp(); if (!configured) { return -1; } log4cpp::Category& logger = log4cpp::Category::getInstance("main"); logger.info("Hello, log4cpp"); return 0; } |
log4cpp::SimpleConfiguratorクラスのconfigureメンバ関数でロギング設定ファイルを指定すると、その内容を読み込み初期化します。設定ファイルの名前は任意で構いません。
logging.conf記述 | 記述の説明 |
---|---|
appender root basic console priority root ERROR appender main basic file sample.log priority main DEBUG |
(1) rootカテゴリの出力はbasicフォーマットでコンソールへ (2) rootカテゴリはERRORレベル以上を出力 (3) mainカテゴリの出力はbasicフォーマットでファイルsample.logへ (4) mainカテゴリはDEBUGレベル以上を出力 |
フォーマットの種類は、simple, basic, patternがあります。patternの場合、フォーマットをマクロ定義で指定します。
appenderの出力先は、file, rolling, console, stdout, stderr, syslog, nteventlog(WIN32のみ), remotesyslogが選べます。
フォーマット種類 | フォーマット例 | 定義 |
simple |
ERROR : Hello, log4cpp world! |
%p - %m%n |
basic |
1217167556 ERROR : Hello, log4cpp world! |
%R %p %c %x: %m%n |
フォーマットを設定ファイルで定義することができます。
appender main pattern console %d %c - %m%n priority main DEBUG |
表示例は以下 2008-07-28 00:17:44,031 main - Hello, log4cpp world! |
フォーマット定義のメッセージマクロ
%m | メッセージ文字列 | 引数で指定した文字列 |
%n | 改行 | |
%c | カテゴリ名 | |
%d | 日付時刻 | |
%p | プライオリティ | |
%r | エポックからの経過ミリ秒 | |
%R | エポックからの経過秒数 | |
%t | スレッド名 | |
%u | プロセッサ時間 | |
%x | インデント |
初期化およびログ出力のコードは、1.SimpleConfiguratorのときと、Configuratorクラス名が違うだけどほとんど同じです。
#include <log4cpp/Category.hh> #include <log4cpp/PropertyConfigurator.hh> bool initLog4cpp() { try { log4cpp::PropertyConfigurator::configure("logging.conf"); return true; } catch (log4cpp::ConfigureFailure& ex) { return false; } } int main(int argc, char *argv[]) { bool configured = initLog4cpp(); if (!configured) { return -1; } log4cpp::Category& logger = log4cpp::Category::getInstance("sample"); logger.info("Hello, log4cpp"); return 0; } |
log4cpp::PropertyConfiguratorクラスのconfigureメンバ関数でロギング設定ファイルを指定すると、その内容を読み込み初期化します。設定ファイルの名前は任意で構いません。
logging.conf記述 | 記述の説明 |
---|---|
# カテゴリの設定 log4cpp.rootCategory=DEBUG, rootAppender log4cpp.category.sample=INFO, sampleAppender log4cpp.category.sample.calc=NOTICE # アペンダの設定 # rootAppenderの設定 log4cpp.appender.rootAppender=ConsoleAppender log4cpp.appender.rootAppender.layout=BasicLayout # sampleAppenderの設定 log4cpp.appender.sampleAppender=RollingFileAppender log4cpp.appender.sampleAppender.fileName=sample.log log4cpp.appender.sampleAppender.MaxFileSize=1024KB log4cpp.appender.sampleAppender.MacBackupIndex=8 log4cpp.appender.sampleAppender.layout=BasicLayout |
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) |
(1) rootカテゴリの出力はDEBUGレベル以上とし、出力先Appender名は、"rootAppender"とする
(2) sampleカテゴリの出力はINFOレベル以上とし、出力先Appender名は、"sampleAppender"とする
(3) sample.calcカテゴリの出力はNOTICEレベル以上とする
(4) "rootAppender"は、コンソール出力Appenderである
(5) "rootAppender"のレイアウトはBasicLayoutとする
(6) "sampleAppender"の出力先ファイルは、ローテーション可能なファイルとする
(7) "sampleAppender"の出力先ファイル名は、"sample.log"とする
(8) "sampleAppender"の出力先ファイルは最大で1024KB(1MB)とする
(9) "sampleAppender"の出力先ファイルのローテーション数は8とする
(10) "sampleAppender"のレイアウトはBasicLayoutとする
出力Appender名は、設定ファイル内で一致していれば任意の名前を付けてかまいません。
上記で、"sample.calc"カテゴリに出力したログは、まず(3)のレベルでフィルターされます。そして、"sample.calc"にはAppenderが設定されていないので、階層が1つ上のカテゴリ"sample"のAppenderに出力されます。
出力する書式を指定するには、レイアウトにPatternLayoutを指定し、ConversionPatternで設定します。
log4cpp.appender.sampleAppender.layout=PatterLayout log4cpp.appender.sampleAppender.layout.ConversionPattern= %d %-5p %c - %m%n |
フォーマット定義のメッセージマクロ
%の直後には、'-'、数値(0-9の1桁)、または'.'を指定することができる。
数値の場合、その情報の出力最低桁数を指定する。
-の場合は左詰めを指定する
.の場合は、最大桁数を指定する
記号 | 種類 | 内容 |
---|---|---|
%m | メッセージ文字列 | 引数で指定した文字列 |
%n | 改行 | |
%c | カテゴリ名 | %c{1}と階層レベルを数字で指定すると、ピリオドで区切られた階層名から指定された階層名が出力される |
%d | 日付時刻 |
%d{XXX}の形でオプション指定可能。XXXには、 ISO8601 : %Y-%m-%d %H:%M:%S,%l (省略時はこれがデフォルト) ABSOLUTE : %H:%M:%S,%l DATE : %d %b %Y %H:%M:%S,%l または、%指定子による書式指定が可能。%指定子の意味は、std::strftime で指定可能なもの。 |
%p | プライオリティ | 桁数を合わせるため、%6p、%-6p(左詰の場合-を付ける)のように桁指定できる。 |
%r | プログラム起動してからの経過秒 | |
%R | エポックからの経過秒数 | |
%t | スレッド名 | スレッドID(アドレス?) |
%x | インデント | スタックレベルによるインデントを追加する |
CPU、ディスクI/O性能によって大きく処理時間は変わります。ここは参考値を示します。
rootカテゴリ、appenderにbasicフォーマットでconsoleのみ指定、ERRORレベル以上を指定
ERROR以上のログ出力: 40μ秒
WARNING以下(DEBUGを除く)の出力: 4μ秒
DEBUGの出力: 0.2μ秒
mainカテゴリ、appenderにpattern指定でファイルとコンソール出力指定、DEBUGレベル以上を指定
DEBUG以上の出力: 120μ秒
通常は、Categoryクラスのオブジェクトに対してメンバ関数を呼びロギングを行います。
ログレベルと出力メッセージを指定するメンバ関数で、以下の3形式があります。
void log4cpp::Category::log(log4cpp::Priority::PriorityLevel, const std::string&) throw()
void log4cpp::Category::log(log4cpp::Priority::PriorityLevel, const char*, ...) throw()
log4cpp::CategoryStream log4cpp::Category::operator<<(log4cpp::Priority::PriorityLevel)
printfライクな書式指定文字列が2.で、std::coutライクな<<のストリーム形式が3.で利用可能です。
log4cpp::Category& logger = log4cpp::Category::getInstance("main"); logger.log(log4cpp::Priority::INFO, "Hello, log4cpp"); logger.log(log4cpp::Priority::DEBUG, "start %d, end %d", start, end); logger << log4cpp::Priority::WARN << "failed in " << place_ << "value=" << x << log4cpp::eol;
ログレベルごとに、レベル名にちなんだメンバ関数があります。ログレベルの指定が簡便になったものです。
以下は、DEBUGレベル用のメンバ関数です。
void log4cpp::Category::debug(const std::string& message) throw()
void log4cpp::Category::debug(const char* format, ...) throw()
log4cpp::CategoryStream log4cpp::Category::debugStream()