ブースト ログ 2.0 を多用するアプリケーションがあります。std::setprecision(std::numeric_limits<double>::digits10 + 1)
ここで、そのアプリケーションに、 、などのデフォルト フラグを設定したいと思いstd::scientific
ますstd::left
。しかし、どうすればそれを行うことができますか?1 つのアプローチは、メイン関数の最初にロガーを作成し、ダミーのログ メッセージを作成することです。これにより、必要なフラグが永続的に設定されます。しかし、これを行うより良い方法はありませんか?
「OPは実際のコードを表示する必要があります」に返信して編集します。
L と呼ばれるグローバル ロギング シングルトンがあります。
class L{
public:
enum severity_level
{
dddebug,
ddebug,
debug,
control,
iiinfo,
iinfo,
info,
result,
warning,
error,
critical
};
typedef boost::log::sources::severity_channel_logger<
severity_level, // the type of the severity level
std::string // the type of the channel name
> logger_t;
typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > text_sink;
boost::shared_ptr< text_sink > sink_;
static L& get();
static boost::shared_ptr<text_sink> sink();
static double t0();
static double tElapsed();
private:
L();
double t0_p;
static std::string tElapsedFormat();
L(const L&) = delete;
void operator=(const L&) = delete;
};
ログ シンク、重大度レベルを提供し、MPI ノード間で同期されたタイムキーピングのために MPI メソッドを利用します。クラスメンバーの実装は次のとおりです。
#include "log.h"
#include <iomanip>
#include <limits>
#include <fstream>
#include <boost/log/attributes/function.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
#include "mpiwrap.h"
#include <mpi.h>
BOOST_LOG_ATTRIBUTE_KEYWORD(t, "Time", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(rank, "Rank", int)
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", L::severity_level)
L::L():
sink_(boost::make_shared< text_sink >()),
t0_p(MPI_Wtime())
{
sink_->locked_backend()->add_stream(
boost::make_shared< std::ofstream >("log." + std::to_string(MpiWrap::getRank())));
sink_->set_formatter
(
expr::stream
<< "< "
<< t << " "
<< "[p:" << rank << "] "
<< "[c:" << channel << "] "
<< "[s:" << severity << "] "
<< expr::smessage
);
logging::core::get()->add_sink(sink_);
logging::core::get()->set_filter(
(channel == "ChannelName1" && severity >= dddebug)
|| (channel == "ChannelName2" && severity >= info)
|| (channel == "ChannelName3" && severity >= result)
);
// Add attributes
logging::core::get()->add_global_attribute("Time", attrs::make_function(&tElapsedFormat));
logging::core::get()->add_global_attribute("Rank", attrs::constant<int>(MpiWrap::getRank()));
}
L& L::get(){
static L instance;
return instance;
}
boost::shared_ptr<L::text_sink> L::sink(){
return get().sink_;
}
double L::t0(){
return get().t0_p;
}
double L::tElapsed(){
return MPI_Wtime() - t0();
}
std::string L::tElapsedFormat(){
std::stringstream ss;
const int prec = std::numeric_limits<double>::digits10;
ss << std::setw(prec + 2 + 6) << std::left << std::setprecision(prec) << tElapsed();
return ss.str();
}
std::ostream& operator<< (std::ostream& strm, L::severity_level level)
{
static const char* strings[] =
{
"DBG3",
"DBG2",
"DBG1",
"CTRL",
"INF3",
"INF2",
"INF1",
"RSLT",
"WARN",
"ERRR",
"CRIT"
};
if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast< int >(level);
return strm;
}
使用法について:私のクラスには通常、静的logger_t
( typedef for boost::log::sources::severity_channel_logger<severity_level, std::string>
)メンバーがあります
class A {
public:
logger_t logger;
//other stuff here
void function_which_does_logging();
};
L::logger_t A::logger(boost::log::keywords::channel = "ClassA");
void A::function_which_does_logging(){
//do non logging related stuff
BOOST_LOG_SEV(logger, L::result) << "the error is: " << 0.1234567890;
//do non logging related stuff
}
問題に対する私の現在の解決策は、ログステートメントをプログラムの先頭に置くことです
int main(){
L::logger_t logger(boost::log::keywords::channel = "init");
BOOST_LOG_SEV(logger, L::critical) << "setting up logger" << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1);
//do stuff
}