.. Sphinx standard indentations # with overline, for parts * with overline, for chapters =, for sections -, for subsections ^, for subsubsections ", for paragraphs 「Short introduction to Apache log4cxx」への補足 ########################################################################## 「Short introduction to Apache log4cxx」で抜けている説明や、わかりにくい箇所の補足。 リンクするライブラリとヘッダファイルの場所 ************************************************************************** log4cxx のインストール先が /usr/local とした場合、 .. code-block:: console me@host: ~$ cd /usr/local/lib me@host: /usr/local/lib$ ls -l *log4cxx* -rwxr-xr-x. 1 root root 13143893 Jan 16 21:03 liblog4cxx.so.10.0.0 lrwxrwxrwx. 1 root root 20 Jan 16 21:03 liblog4cxx.so -> liblog4cxx.so.10.0.0 -rw-r--r--. 1 root root 34497458 Jan 16 21:03 liblog4cxx.a lrwxrwxrwx. 1 root root 20 Jan 16 21:03 liblog4cxx.so.10 -> liblog4cxx.so.10.0.0 -rwxr-xr-x. 1 root root 950 Jan 16 21:03 liblog4cxx.la me@host: /usr/local/lib$ cd /usr/local/include me@host: /usr/local/include$ ls -dl log4cxx drwxr-xr-x. 14 root root 4096 Jan 16 21:03 log4cxx すなわち、Makefile に記述する場合は .. code-block:: makefile .SUFFIXES: .SUFFIXES: .c .cpp .o .PHONY: all clean CC = gcc CXX = g++ NOVERB = CFLAGS = -O3 -DNDEBUG -I/usr/local/include CXXFLAGS = $(CFLAGS) #CXXFLAGS = $(CFLAGS) -std=c++0x -Weffc++ LFLAGS = -L/usr/local/lib -llog4cxx OBJS = your_app.o your_app: $(OBJS) $(CXX) $(LFLAGS) $(OBJS) -oyour_app などとする。 「Default Initialization Procedure」の具体 ************************************************************************** 「Default Initialization Procedure」部分がわかりにくいので、実際にやってみる。 カレントディレクトリに、以下の(デフォルトと違う) `log4cxx.properties` を置いてみる: .. code-block:: bash # Set root logger level to DEBUG and its only appender to A1. log4j.rootLogger=DEBUG, A1 # A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout #log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n log4j.appender.A1.layout.ConversionPattern=%-5p %c - %m%n これを使うプログラムは以下: .. code-block:: c++ // include log4cxx header files. #include "log4cxx/logger.h" #include "log4cxx/helpers/exception.h" using namespace log4cxx; using namespace log4cxx::helpers; LoggerPtr logger(Logger::getLogger("your_app")); int main(int argc, char **argv) { try { LOG4CXX_INFO(logger, "Entering application."); LOG4CXX_INFO(logger, "Exiting application."); } catch(const log4cxx::helpers::Exception& e) { return -1; } return 0; } つまり、 `BasicConfigurator` も `PropertyConfigurator` も ( `DOMConfigurator` も)何も記述しない。これでビルドして動かすと、 .. code-block:: none INFO your_app - Entering application. INFO your_app - Exiting application. となる。「これらもない場合には、カレントディレクトリにある~」が効いている。 今度は、 `log4cxx_otr.properties` という別名で、かつ、さっきと少しフォーマットが違う ものを置いてみる: .. code-block:: bash # Set root logger level to DEBUG and its only appender to A1. log4j.rootLogger=DEBUG, A1 # A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout #log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n log4j.appender.A1.layout.ConversionPattern=%d %-5p %c - %m%n 今度は、以下のようなシェル経由で起動してみる: .. code-block:: bash #! /bin/sh export LOG4CXX_CONFIGURATION=./log4cxx_otr.properties ./your_app 今度は出力は以下のようになる: .. code-block:: none 2014-01-20 13:00:32,095 INFO your_app - Entering application. 2014-01-20 13:00:32,095 INFO your_app - Exiting application. つまり「環境変数 `LOG4CXX_CONFIGURATION` があれば」の場合。 この方式が一番柔軟なのではないか。 class に貼り付けたいロガー ************************************************************************** 「Short introduction to Apache log4cxx」に全て書かれてはいるのだが、わかりにくいかも しれないので、もっと単純化した例を示しておく。 `Makefile`: .. literalinclude:: sample_sources/sample02/Makefile :language: makefile :encoding: utf-8 `your_app.cpp`: .. literalinclude:: sample_sources/sample02/your_app.cpp :language: cpp :encoding: utf-8 `your_class.h`: .. literalinclude:: sample_sources/sample02/your_class.h :language: cpp :encoding: utf-8 `your_class.cpp`: .. literalinclude:: sample_sources/sample02/your_class.cpp :language: cpp :encoding: utf-8 `log4cxx_otr.properties`: .. literalinclude:: sample_sources/sample02/log4cxx_otr.properties :language: bash :encoding: utf-8 `your_app.sh`: .. literalinclude:: sample_sources/sample02/your_app.sh :language: bash :encoding: utf-8 これで実行させた場合の出力は .. code-block:: none 2014-01-20 13:42:46,365 INFO your_app (your_app.cpp:15) - Entering application. 2014-01-20 13:42:46,365 INFO YourClass (your_class.cpp:10) - do something 2014-01-20 13:42:46,365 INFO your_app (your_app.cpp:18) - Exiting application. という具合。 「Short introduction to Apache log4cxx」でくどく書かれているのは .. code-block:: c++ // getLogger を static に。 LoggerPtr YourClass::logger(Logger::getLogger("YourClass")); 部分のロガー命名の話。「あなたの」class が `namespace` に囲まれて管理されているならば、 例えば `namespace my { namespace app { class YourClass; } }` の場合、 ロガー名は .. code-block:: c++ // getLogger を static に。 LoggerPtr YourClass::logger(Logger::getLogger("my.app.yourclass")); の方が適切、という話である。これについてはアプリケーション・ライブラリの構造依存でもあり、どうすると 管理しやすいかの話であり、任意とは言えるが、綺麗に構造化しないと使いにくいログになるので、その配慮はして欲しい。 (つまり、C++的に namespace に囲まれているいないに関わらず、ログは構造化する、などは考えて良い、と思う。) 出したいログを事細かにコントロール、の具体 ************************************************************************** 一つ前の例から少し変えるだけの、ここでも非常に単純化した例を示しておく。 .. literalinclude:: sample_sources/sample03/your_class.cpp :language: cpp :encoding: utf-8 `log4cxx_otr.properties`: .. literalinclude:: sample_sources/sample03/log4cxx_otr.properties :language: bash :encoding: utf-8 この場合、出力は .. code-block:: none 2014-01-20 13:50:52,413 INFO your_app (your_app.cpp:15) - Entering application. 2014-01-20 13:50:52,413 WARN YourClass (your_class.cpp:11) - a little problem had occured 2014-01-20 13:50:52,413 INFO your_app (your_app.cpp:18) - Exiting application. となり、 .. code-block:: c++ void YourClass::DoSomething() { LOG4CXX_INFO(logger, "do something"); LOG4CXX_WARN(logger, "a little problem had occured"); } この一つ目のログが揉み消されている。 PatternLayout のフルスペック、などの情報について ************************************************************************** 「Short introduction to Apache log4cxx」は都度 API 仕様にリンクしているものの、 インターネット上のリソースであるため、環境によっては参照出来ないであろう。これについては、 log4cxx をインストールすると、インストール先が `/usr/local` の場合は `/usr/local/share/log4cxx` に html ドキュメントがインストールされるので、適宜そちらを参照のこと。