Poco::NestedDiagnosticContext

Poco::NestedDiagnosticContext を紹介します。

“Pattern Languages of Program Design 3”
(Addison-Wesley) の Neil Harrison の “Patterns for Logging Diagnostic Messages” で述べられている Nested Diagnostic Context (NDC) の実装です。

NDC は、method 名とソースコード行番号、ファイル名で構成されるコンテキスト情報を保持します。
全ての thread は、自分自身の NDC を持ち、必要とされる時生成され、thread 終了時に破棄されます。
スコープ開始時に情報を push し、スコープ終了時に pop するように、Poco::NDCScope を使うことができます。マクロ poco_ndc(info) で登録すると、ソースコード行番号、ファイル名も共に記録されます。

NestedDiagnosticContextTest.cpp

・スレッドを3つ作り、再帰的に呼ぶ回数を変えつつ、それぞれのスレッドで TestFunction() を呼び、
 NDC の内容を表示。
・比較用に main スレッドでも poco_ndc(main) をコールし、内容を表示。
・今回は Debug/Release 両ビルドで同じ出力にしたかったので poco_ndc() を呼んだが、本来の使い方
 としては poco_ndc_dbg() を呼んで、Relase ビルドでは出さないようにするべき。

#include <Poco/NestedDiagnosticContext.h>
#include <Poco/Runnable.h>
#include <Poco/Thread.h>
#include <Poco/Format.h>
 
#include <sstream>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
const std::size_t kNumThreads = 3;
 
void DumpNDCMessage(ScopedLogMessage& msg)
{
	std::ostringstream sstr;
	Poco::NDC::current().dump(sstr);
	msg.Message(Poco::format(	"\n- Poco::NDC::current().depth()    : %d"
					"\n- Poco::NDC::current().toString() :\n%s"
					"\n- Poco::NDC::current().dump()     :\n%s"
					, Poco::NDC::current().depth()
					, Poco::NDC::current().toString()
					, sstr.str()));
}
 
void TestFunction(ScopedLogMessage& msg, std::size_t i)
{
	poco_ndc(TestFunction);
 
	if(0 == i)
	{
		DumpNDCMessage(msg);
	}
	else
	{
		TestFunction(msg, --i);
	}
}
 
class MyRunnable: public Poco::Runnable
{
public:
	MyRunnable() :
		m_pMsg(NULL)
	,	m_funcDepth(0)
	{
	}
 
	void setDepth(ScopedLogMessage* pMsg, std::size_t depth)
	{
		m_pMsg = pMsg;
		m_funcDepth = depth;
	}
 
	void run()
	{
		poco_ndc(run);
 
		if(NULL != m_pMsg)
		{
			TestFunction(*m_pMsg, m_funcDepth);
		}
	}
 
private:
	ScopedLogMessage*	m_pMsg;
	std::size_t		m_funcDepth;
};
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("NestedDiagnosticContextTest ", "start", "end");
 
	poco_ndc(main);
 
	Poco::Thread thread[kNumThreads];
	MyRunnable r[kNumThreads];
	for(std::size_t i=0; i<kNumThreads; ++i)
	{
		r[i].setDepth(&msg, i);
		thread[i].start(r[i]);
	}
	Poco::Thread::sleep(200);
	for(std::size_t i=0; i<kNumThreads; ++i)
	{
		thread[i].join();
	}
 
	DumpNDCMessage(msg);
 
	return 0;
}

Results of execution

[0] NestedDiagnosticContextTest start
[1] 
- Poco::NDC::current().depth()    : 2
- Poco::NDC::current().toString() :
run:TestFunction
- Poco::NDC::current().dump()     :
run (in "NestedDiagnosticContextTest.cpp", line 98)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
 
[2] 
- Poco::NDC::current().depth()    : 3
- Poco::NDC::current().toString() :
run:TestFunction:TestFunction
- Poco::NDC::current().dump()     :
run (in "NestedDiagnosticContextTest.cpp", line 98)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
 
[3] 
- Poco::NDC::current().depth()    : 4
- Poco::NDC::current().toString() :
run:TestFunction:TestFunction:TestFunction
- Poco::NDC::current().dump()     :
run (in "NestedDiagnosticContextTest.cpp", line 98)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
TestFunction (in "NestedDiagnosticContextTest.cpp", line 66)
 
[0] 
- Poco::NDC::current().depth()    : 1
- Poco::NDC::current().toString() :
main
- Poco::NDC::current().dump()     :
main (in "NestedDiagnosticContextTest.cpp", line 132)
 
[0] NestedDiagnosticContextTest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年6月23日からのダウンロード数:843

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Powered by POCO Copyright © 2010 Round Square Inc. All rights reserved.


Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>