2

C++ プログラムに次の (簡略化された) コードがあります。

std::string DataRequest::toString() const {
LOG4CPLUS_TRACE(logger,
        LOG4CPLUS_TEXT("symbol=" << m_contract.symbol));

std::ostringstream oss;
oss << "id=" << reqId
    << ",symbol=" << m_contract.symbol;
return oss.str();
}

int DataService::requestData(
    DataRequest request) {

LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("requestData: " << request.toString()));
}

このコードは、ログ メッセージを生成します。

TRACE symbol=AAA
INFO  symbol=AAArequestData: id=1,symbol=AAA

しかし、私は期待していた

TRACE symbol=AAA
INFO  requestData: id=1,symbol=AAA

log4cplus メッセージ内に log4cplus メッセージが生成されているため、2 つのメッセージが 1 つのメッセージに連結されているように見えます。これは正常な動作ですか?各メッセージを強制的に個別に生成する解決策はありますか?

4

1 に答える 1

2

これは間違ったコードです

LOG4CPLUS_TRACE(logger,
        LOG4CPLUS_TEXT("symbol=" << m_contract.symbol));

それは読むべきです

LOG4CPLUS_TRACE(logger,
        LOG4CPLUS_TEXT("symbol=") << m_contract.symbol);

代わりは。

連結されたメッセージについては、どの出力レイアウトを使用していますか? パターン レイアウトの場合は%n、フォーマット文字列の最後にフォーマッタを追加する必要があります。

編集:

残念ながら、ログ メッセージが連結されているという問題がまだ残っています。これは、ログメッセージ自体の呼び出し request.toString() にもログメッセージへの呼び出しがあるという事実に関係していると思いますが、何らかの理由で、コード修正後でも2つのメッセージが一緒に出力されています。:(

ああ、最初は問題を誤解していました。したがって、最初の準備中に 2 番目のイベントを記録しています。問題は、フォーマットがスレッドローカルに行われることostringstreamです。スレッド ローカルostringstreamは、パフォーマンスの向上として使用されます。(ostringstreamログに記録されたメッセージごとに を構築および破棄する必要はありません。)

すぐに回避するには、2 つのオプションがあります。まず、このネストされたロギングを停止します。LOG4CPLUS_*()次に、スレッド ローカルを使用しないようにマクロを「修正」するostringstreamか、独自のログ マクロをロールします。どちらもそれほど難しくないはずです。

長期的には、ロギング マクロに特別なケースを追加してostringstream、ユース ケースを許可するたびに新しいものを使用できるようにすることができます。

編集2:

バグ レポートに記入し、回避策を実装するパッチを添付しました。https://sourceforge.net/p/log4cplus/bugs/153/を参照してください。

于 2012-12-31T07:27:32.700 に答える