c++ - boost 日志 : Support file name and line number

标签 c++ boost log4cxx boost-log

我试图让我的团队远离 log4cxx 并尝试使用 Boost.Log v2。我们目前的log4cxx pattern很简单:

log4cxx::helpers::Properties prop;
prop.setProperty("log4j.rootLogger","DEBUG, A1");
prop.setProperty("log4j.appender.A1","org.apache.log4j.ConsoleAppender");
prop.setProperty("log4j.appender.A1.layout","org.apache.log4j.PatternLayout");
prop.setProperty("log4j.appender.A1.layout.ConversionPattern","%d{ABSOLUTE} %-5p [%c] %m%n");
log4cxx::PropertyConfigurator::configure(prop);

但是我没有找到支持文件名和行号打印的解决方案。到目前为止我发现了一个 old post ,但没有明确的解决方案(没有公认的解决方案)。我研究过使用那些 BOOST_LOG_NAMED_SCOPE 但它们感觉非常难看,因为当在同一函数中使用多个这些时,它们无法打印正确的行号。

我还找到了一个更简单的直接解决方案,here .但这也让人感觉很丑陋,因为它会打印完整路径,而不仅仅是基本名称(它是不可配置的)。所以完整路径和行号总是打印在固定位置(在 expr::smessage 之前)。

我也找到了这个 post ,这看起来像是一个旧的解决方案。

最后,我发现最有希望的解决方案是 here .但是它甚至不为我编译。

所以我的问题很简单:我如何使用 Boost.Log v2 以最小的 formatter flexibility 打印文件名(不是完整路径)和行号(请不要接受 MACRO__FILE__/__LINE__ 的解决方案)。我希望有一个不涉及 BOOST_LOG_NAMED_SCOPE 的解决方案,如 here 所述:

If instead you want to see line numbers of particular log records then the best way is to define a custom macro which you will use to write logs. In that macro, you can add the file name and line number as attributes to the record (you can use manipulators for that). Note that in this case you won't be able to use these attributes in filters, but you probably don't need that.

最佳答案

我终于找到了一个基于 add_value 的简单解决方案.这是完整的源代码:

#include <ostream>
#include <fstream>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/filesystem.hpp>

namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;

void my_formatter(logging::record_view const& rec, logging::formatting_ostream& strm)
{
    // Get the LineID attribute value and put it into the stream
    strm << logging::extract< unsigned int >("LineID", rec) << ": ";
    strm << logging::extract< int >("Line", rec) << ": ";
    logging::value_ref< std::string > fullpath = logging::extract< std::string >("File", rec);
    strm << boost::filesystem::path(fullpath.get()).filename().string() << ": ";

    // The same for the severity level.
    // The simplified syntax is possible if attribute keywords are used.
    strm << "<" << rec[logging::trivial::severity] << "> ";

    // Finally, put the record message to the stream
    strm << rec[expr::smessage];
}

void init()
{
    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 >("sample.log"));

    sink->set_formatter(&my_formatter);

    logging::core::get()->add_sink(sink);
}

#define MY_GLOBAL_LOGGER(log_,sv) BOOST_LOG_SEV( log_, sv) \
  << boost::log::add_value("Line", __LINE__)      \
  << boost::log::add_value("File", __FILE__)       \
  << boost::log::add_value("Function", BOOST_CURRENT_FUNCTION)

int main(int, char*[])
{
    init();
    logging::add_common_attributes();

    using namespace logging::trivial;
    src::severity_logger< severity_level > lg;

    MY_GLOBAL_LOGGER(lg,debug) << "Keep";
    MY_GLOBAL_LOGGER(lg,info) << "It";
    MY_GLOBAL_LOGGER(lg,warning) << "Simple";
    MY_GLOBAL_LOGGER(lg,error) << "Stupid";

    return 0;
}

在我的 Linux 机器上,我使用以下方法编译它:

$ c++ -otutorial_fmt_custom -DBOOST_LOG_DYN_LINK tutorial_fmt_custom.cpp -lboost_log -lboost_log_setup -lboost_thread -lpthread -lboost_filesystem

如果你运行并检查这里生成的日志文件是你得到的:

$ ./tutorial_fmt_custom && cat sample.log 
1: 61: tutorial_fmt_custom.cpp: <debug> Keep
2: 62: tutorial_fmt_custom.cpp: <info> It
3: 63: tutorial_fmt_custom.cpp: <warning> Simple
4: 64: tutorial_fmt_custom.cpp: <error> Stupid

我的解决方案基于两个输入(谢谢!):

关于c++ - boost 日志 : Support file name and line number,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31154429/

相关文章:

c++ - 无法正确写入和更新二进制文件

c++ - 使用 TBB 进行线程安全的惰性创建?

c++ - wxWidgets:对 wxURL 的 undefined reference

c++ - 共享指针在循环中超出范围时出错(堆损坏?)

c++ - 创建自己的 Boost::Archive 实现

logging - 在 Ubuntu12 中编译 log4cxx 失败。错误是四月

log4j - 日志框架中重要但非致命的日志消息(log4j、log4net、log4php、log4cxx、NLog)

c++ - 如何解析 HTTP POST(文件上传)流?

Boost Spirit 将表达式标记化为向量

log4net - 混合 log4cxx 和 log4net