log4cxx使ってみた

無理やりコンパイルを通したので実際に使ってみた。

まずはここの例を見ながらソースコードを書いてみた。
http://logging.apache.org/log4cxx/index.html

#include 
#include 					// LOG4CXX_STR
#include 
#include 
#include 								// cerr
#include 

using namespace log4cxx;


int main(int argc, char **argv)
{
	try
	{
		if (argc > 1)
		{
			xml::DOMConfigurator::configure(argv[1]);
		}
		else
		{
			BasicConfigurator::configure();
		}

		LoggerPtr		errLogger(Logger::getLogger("Error"));
		LoggerPtr		hifLogger(Logger::getLogger("HighFrequency"));

		LOG4CXX_TRACE(hifLogger, "Entering application.");
		LOG4CXX_TRACE(hifLogger, "Entering error messages.");
		LOG4CXX_FATAL(errLogger, "fatal error");
		LOG4CXX_ERROR(errLogger, "normal error");
		LOG4CXX_WARN (errLogger, "warning message");
		LOG4CXX_TRACE(hifLogger, "Leaving  error messages.");
		LOG4CXX_TRACE(hifLogger, "Entering japanese messages.");
		LOG4CXX_INFO (hifLogger, L"wchar_t型文字列はOK?");
		LOG4CXX_DEBUG(hifLogger, LOG4CXX_STR("日本語メッセージのテスト."));
		LOG4CXX_TRACE(hifLogger, "Leaving  japanese messages.");
		LOG4CXX_TRACE(hifLogger, "Leaving  application.");
	}
	catch(std::exception &e)
	{
		std::cerr << e.what() << std::endl;
		return -1;
	}

	return 0;
}

PropertyConfiguratorを使わずにDOMConfiguratorを使ったのはAsyncAppenderのコメントに「DOMしか対応してないよ」的な注意が書いてあったので。あと、log4cxxのException類はstd::exceptionを継承してるっぽいのをsrc\main\include\log4cxx\helpers\exception.hあたりで見かけたのでcatchはstd::exceptionで統一。
ダメ元で日本語も試してみる感じで。bcc的にSJISしかソースコードを受け付けないっぽいのでたぶんダメかも。ググったらwchar_tはUTF-16っぽいし…

んで、configファイルは
この辺とか
http://www.nurs.or.jp/~sug/soft/log4j/log4j3.htm
あと、
src\test\resources\input\xml
ここに入っているXMLファイルとか最初のlog4cxx公式サイトの設定例を見ながら書いてみた。
ソースコードと見比べてみた感じだと各クラスのsetXXX()のXXXに値を設定すれば良いっぽい。例えばSyslogAppender::setSyslogHost()ってのがあるのでを書いてみる、みたいな。




いろいろAppenderって名前のヘッダファイルを見て回った感じだと気になったのはこいつら。

  • DailyRollingFileAppender

 名前からすると日付単位でぐるぐるログファイルを回せる?

  • net.SyslogAppender

 syslogを外部に飛ばす。リアルタイムでデバッグしたいときに外部のデバッグPCにログを飛ばす

  • AsyncAppender

 専用スレッドにロギング処理を丸投げできそう。実際のロギング処理はAppenderを登録してやる感じっぽい。




あと、ログレベルはLoggerって単位でしか設定できなさそう。上のソースコードもレベルの影響を受けたい感じの区分で分けてみた。

ということで、エラー処理はファイルへ出力、トレース系はsyslogへ出力って感じにしてみた。

<?xml version="1.0" encoding="UTF-8"?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">

	<!-- 標準出力設定 -->
	<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d %5p %c{1} %F L:%L - %m%n"/>
		</layout>
	</appender>

	<!-- ファイル出力設定 -->
	<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="File" value="errlog.csv"/>				<!-- 出力先ファイル名 -->
		<param name="Append" value="true"/>					<!-- 追記モード -->
		<param name="MaxBackupIndex" value="1"/>			<!-- 1ファイルだけバックアップを取る -->
		<param name="MaxFileSize" value="1KB"/>				<!-- 1ファイルは最大1KBまで -->
		<param name="DatePattern" value="'.'yyyy/MM/dd"/>	<!-- 日付が変わったらファイルを切り替える -->
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value='"%d","%F","%L","%m"%n'/>
		</layout>
	</appender>

	<!-- syslog出力設定 -->
	<appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
		<param name="SyslogHost" value="127.0.0.1"/>		<!-- syslogサーバアドレスorホスト名(ログを受け取る人) -->
		<param name="Facility" value="USER"/>				<!-- syslogのファシリティ設定。とりあえず USER で -->
		<param name="FacilityPrinting" value="true"/>		<!-- ファシリティ表示ON。「<15>」とかのことだよね -->
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d %-5p %F %L %m"/>
		</layout>
	</appender>

	<!-- 遅延書き込み用設定 -->
	<appender name="async" class="org.apache.log4j.AsyncAppender">
		<param name="BufferSize" value="1024"/>
		<param name="Blocking" value="false"/>
		<param name="LocationInfo" value="true"/>
		<appender-ref ref="syslog"/>
<!--		<appender-ref ref="file"/>-->	<!-- これを有効にすればファイルにも書き込むはず -->
	</appender>


	<!-- ここからロギング全体の設定 -->
	<!-- エラー用 -->
	<logger name="Error">
		<level value="error"/>			<!-- error 以上のログしか残さない(とりあえずWARNは放置...) -->
		<appender-ref ref="file"/>		<!-- 出力先は"file"設定 -->
	</logger>
	<!-- 高頻度ログ用 -->
	<logger name="HighFrequency">
		<level value="trace"/>			<!-- デバッグ時以外は"OFF" -->
<!--		<appender-ref ref="async"/>-->		<!-- こっちを使うと書き込むとき?に死んでしまう -->
		<appender-ref ref="syslog"/>
	</logger>
	<root>
		<level value="OFF"/>
<!--		<appender-ref ref="stdout"/>-->		<!-- OFFにしてもなぜか出力されちゃうのでコメントアウト -->
	</root>
</log4j:configuration>

CSVのログ

"2009-09-23 22:00:56,781","test.cpp","29","fatal error"
"2009-09-23 22:00:56,781","test.cpp","30","normal error"

syslogのログ

<15>2009-09-23 22:00:56,765 TRACE test.cpp 27 Entering application.
<15>2009-09-23 22:00:56,781 TRACE test.cpp 28 Entering error messages.
<15>2009-09-23 22:00:56,781 TRACE test.cpp 32 Leaving  error messages.
<15>2009-09-23 22:00:56,796 TRACE test.cpp 33 Entering japanese messages.
<14>2009-09-23 22:00:56,796 INFO  test.cpp 34 wchar_t?????O??
<15>2009-09-23 22:00:56,796 DEBUG test.cpp 35 ????????????.
<15>2009-09-23 22:00:56,796 TRACE test.cpp 36 Leaving  japanese messages.
<15>2009-09-23 22:00:56,812 TRACE test.cpp 37 Leaving  application.

動かしてみてわかったことは

  • 接続先ホストがいないとsyslogは最初に時間がかかる(秒単位で)
  • Asyncにしてもsyslogのホスト探し時間(?)はかわらなさそう(ブロックされる)
  • 日本語は???表示される
  • Async経由で出力しようとすると死んでしまう(なんで?)

ということで、Asyncと日本語は封印の方向で(^^;
どうせsyslogる時はデバッグ中だから遅くても良いし。てか、ネットワーク通信って言ってもそんなに遅くないし。
気が向いたらAPRとかlog4cxx本体にデバッグコードでも埋め込んで解析かなぁ。


ってあれ?ログファイルがrollingしてない…(´・ω・`)