使用Boost同时记录到控制台和文件 [英] Simultaneous Logging to Console and File using Boost

查看:1977
本文介绍了使用Boost同时记录到控制台和文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要帮助来初始化boost日志框架,同时日志到一个命名的日志文件和控制台 - (命名的日志文件不需要定期旋转或任何一个花哨的设置每多个boost教程)。



日志文本应该同时转到两个汇(文件和控制台),但是我需要格式化控制台输出略有不同,因为它将被用户查看。我能够使用 boost示例代码 。对于我需要做的是过于复杂,并且它是真正令人困惑的,就访问适当的记录器。所有我需要做的是有发送到日志文件的时间戳消息和具有相同的信息,而没有时间戳或者换行符发送到控制台日志(仅仅显式地放入新行如<< std :: endl流操作)。我真的想坚持使用boost的日志框架,因为它提供了在未来的灵活性扩展。



在这个例子中,我尝试tail -f日志文件 - 然而日志输出似乎不会在每个日志条目后自动刷新。虽然这对于文件日志不是很重要,但这对于控制台输出流是至关重要的,因为它代表用户将监视的活动。



任何帮助或



我设置我的日志记录(上面的链接)的方式如下所示,我想用一个控制台记录器替换这些注册的汇之一 - 但我不知道如何。

  //为所有接收器设置公共格式化程序
logging: :formatter fmt = expr :: stream
<< std :: setw(6)<< std :: setfill('0')<< line_id<< std :: setfill('')
<< :< <<严重性< > \t
<< expr :: if_(expr :: has_attr(tag_attr))
[
expr :: stream<< [< tag_attr<< ]
]
<< expr :: smessage;

//初始化sinks
typedef sinks :: synchronous_sink< sinks :: text_ostream_backend> text_sink;
boost :: shared_ptr< text_sink> sink =
boost :: make_shared< text_sink>();
sink-> locked_backend() - > add_stream(
boost :: make_shared< std :: ofstream>(
full.log))
sink-> set_formatter(fmt);
//注册完整的日志sink
logging :: core :: get() - > add_sink(sink);

sink = boost :: make_shared< text_sink>();
sink-> locked_backend() - > add_stream(
boost :: make_shared< std :: ofstream>(
important.log))
// sink-> set_formatter(fmt); (我删除了这个,希望没有任何特殊的格式)
sink-> set_filter(severity> = warning ||
(expr :: has_attr(tag_attr)&&
tag_attr ==IMPORTANT_MESSAGE)));
//注册重要的日志sink
logging :: core :: get() - > add_sink(sink);
//添加属性
logging :: add_common_attributes();


解决方案

这里是一些使用Boost-Log的全局记录器。我调用 init_term()
来初始化我的终端记录器和 init_logfile() / p>

注意 auto_flush(true)调用

  //记录宏
#define LOG(level)BOOST_LOG_SEV(global_logger :: get(),level)
//初始化全局boost :: log logger
typedef boost :: log :: sources :: severity_channel_logger_mt<
severity_level,std :: string> global_logger_type;

BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(global_logger,global_logger_type)
{
return global_logger_type(boost :: log :: keywords :: channel =global_logger);
}

//初始化终端记录器
void init_term()
{
//创建sink到stdout
boost :: shared_ptr< text_sink> sink = boost :: make_shared< text_sink>();
sink-> locked_backend() - > add_stream(
boost :: shared_ptr< std :: ostream>(& out,boost :: empty_deleter

// flush
sink-> locked_backend() - > auto_flush(true);

//格式sink
sink-> set_formatter

/// TODO添加所需的格式化
);

// filter
// TODO添加任何过滤器

//寄存器槽
bl :: core :: get() - > add_sink (水槽);
}

//初始化日志文件
void init_logfile(const std :: string& logfilename)
{
//创建sink到日志文件
boost :: shared_ptr< text_sink> sink = boost :: make_shared< text_sink>();
sink-> locked_backend() - > add_stream(
boost :: make_shared< std :: ofstream>(logfilename.c_str

// flush
sink-> locked_backend() - > auto_flush(true);

//格式槽
sink-> set_formatter

/// TODO添加所需的格式化
);

// filter
// TODO添加任何过滤器

//寄存器槽
bl :: core :: get() - > add_sink (水槽);
}


I need help to initialize the boost logging framework to simultaneously log to both a named log file and also the console - (the named log file will not require periodic rotation or any of that fancy setup per many of the boost tutorials).

The logging text should go to both sinks (file and console) simultaneously, however I need to format the console output slightly differently as it will be viewed by a user. I was able to get the basics of logging to 2 separate sinks working using the boost example code. It is way overly complex for what I need to do and it is really confusing as far as accessing the appropriate logger is concerned. All I need to do is have time stamped messages sent to the log file and have the same information without the times-stamps or newlines send to the console log (putting in new lines explicitly only as I would typically do with << std::endl streaming operations). I would really like to stick with boost's logging framework as it gives the flexibility to expand in the future.

With the example, I tried tail -f the log files - however the log output does not appear to get auto flushed after each log entry. Although this is not very important for the file logs, this would be critical for the console output stream as it represents live activity that a user will be monitoring.

Any help or even better, some really simple sample code to get the basics working be much appreciated.

The way I setup my logging (per the link above) is as shown below, I would like to replace one of these registered sinks with a console logger - but I am not sure how. I expect that a console logger will have auto flush.

// Setup the common formatter for all sinks
logging::formatter fmt = expr::stream
    << std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
    << ": <" << severity << ">\t"
    << expr::if_(expr::has_attr(tag_attr))
    [
        expr::stream << "[" << tag_attr << "] "
    ]
<< expr::smessage;

// Initialize sinks
typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
boost::shared_ptr<text_sink> sink = 
    boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(
    boost::make_shared<std::ofstream>(
        "full.log"));
sink->set_formatter(fmt);
// register the full log sink
logging::core::get()->add_sink(sink);

sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(
    boost::make_shared<std::ofstream>(
        "important.log"));
//    sink->set_formatter(fmt); (I removed this to not have any special formatting hopefully)
sink->set_filter(severity >= warning || 
    (expr::has_attr(tag_attr) && 
    tag_attr == "IMPORTANT_MESSAGE"));
// register the important log sink
logging::core::get()->add_sink(sink);
// Add attributes
logging::add_common_attributes();

解决方案

Here is some sample code that utilizes Boost-Log's global logger. I call init_term() to initialize my terminal logger and init_logfile() to initialize my logfile.

Note the auto_flush(true) call

// Logging macro
#define LOG(level) BOOST_LOG_SEV(global_logger::get(), level)
// Initializing global boost::log logger
typedef boost::log::sources::severity_channel_logger_mt<
    severity_level, std::string> global_logger_type;

BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(global_logger, global_logger_type)
{
    return global_logger_type(boost::log::keywords::channel = "global_logger");
}

// Initialize terminal logger
void init_term()
{
    // create sink to stdout
    boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
    sink->locked_backend()->add_stream(
        boost::shared_ptr<std::ostream>(&out, boost::empty_deleter()));

    // flush
    sink->locked_backend()->auto_flush(true);

    // format sink
    sink->set_formatter
    (
        /// TODO add your desired formatting
    );

    // filter
    // TODO add any filters

    // register sink
    bl::core::get()->add_sink(sink);
}

// Initialize logfile
void init_logfile(const std::string& logfilename)
{
    // create sink to logfile
    boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
    sink->locked_backend()->add_stream(
        boost::make_shared<std::ofstream>(logfilename.c_str()));

    // flush
    sink->locked_backend()->auto_flush(true);

    // format sink
    sink->set_formatter
    (
        /// TODO add your desired formatting
    );

    // filter
    // TODO add any filters

    // register sink
    bl::core::get()->add_sink(sink);
}

这篇关于使用Boost同时记录到控制台和文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆