2016-07-28 96 views
0

我正在尝试使用Boost.Log自定义格式化程序。我知道如何做到这一点的方法是调用汇给它一个本地函数的地址set_formatter方法,其中本地函数的签名必须是:如何在自定义格式化函数中使用Boost.Log格式表达式

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm) 

my_formatter我可以使用Boost .Log抽取API以获取我需要的属性值。一旦我得到的值,我可以输出他们到strm。我想这样做,这样我可以轻松地格式化存储在记录中的一些自定义属性。但对于其他更传统的Boost.Log属性,我想继续使用简单的格式化表达式,这些表达式被记录为set_formatter方法的关键字参数。有没有办法在my_formatter自定义函数中使用关键字表达式?

例如:

void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm) 
{ 
    // here I can get the timestamp attribute and format its ticks value to the stream 
    boost::log::value_ref<boost::posix_time::ptime> tstamp_ref = 
     boost::log::extract<boost::posix_time::ptime>("TimeStamp", rec); 
    const boost::posix_time::ptime& timestamp = tstamp_ref.get(); 

    strm << timestamp.time_of_day().ticks(); 
} 

然后给一个接收器,我可以打电话给

sink->set_formatter(&my_formatter) 

但Boost.Log给我一个优雅的(几乎是不可思议的)的表达,我可以用它来设置格式:

boost::log::formatter formatter = 
    expr::stream 
    << expr::format_date_time<boost::posix_time::ptime>(
     "TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, "); 

sink->set_formatter(formatter) 

我的问题是:有没有办法在我的自定义中使用formatter表达式my_formatter功能?

谢谢!

回答

1

您可能想要做的是将格式化程序的自定义部分注入到使用Boost.Log创建的格式化表达式中,而不是用其他方式。 This答案描述了一种通过使用phoenix::bind来实现这一点的方法。

+0

谢谢!这是一个很长的答案,所以我将不得不稍稍研究一下,但这似乎也是一个很好的方法。在使用格式化表达式时,您可以多讨论一下性能下降吗?您在文档中提到,代码中的格式化表达式的执行速度要比从配置文件创建的快。我的观察是我的非表达式格式化程序比基于表达式的表达式执行得更快。 (在我的临时基准测试中,唯一正在做的工作就是日志记录,所以我对速度变慢了,但有时性能确实很重要。) – Phil

+0

必须检查代码和生成的程序集才能发现绩效回归的原因。格式化表达式(无论如何涉及'expr :: stream')比解析格式化器更有效率,因为编译器有更多优化方法。特别是它可以更积极地内联函数。手写格式化程序可能会胜过格式化表达式,因为它可以更加专业化。它通常是一个扁平函数,所以它不依赖内联,而编译器可能由于某种原因无法优化模板表达式。 –

+0

另外,如果你的格式化程序涉及日期/时间,那么确保你使用'expr :: format_date_time'而不是Boost.DateTime中的'operator <<',因为后者被认为比较慢。 –

0

经过一番工作,我找到了一些Boost.Log测试代码,form_date_time.cpp,它显示了如何做到这一点。以下是如何在自定义格式函数中以编程方式使用表达式格式程序。

void my_formatter(boost::log::record_view const& rec, 
        boost::log::formatting_ostream& strm) 
{ 
    typedef boost::log::formatter formatter; 
    formatter f = expr::stream << expr::format_date_time<boost::posix_time::ptime>(
         "TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, "); 
    f(rec, strm); 
} 

虽然我已经给出了答案,但应该小心使用它。在我的基准测试中,正确实现的自定义格式化函数将优于表达式格式化程序。但对于不想为其编写代码的复杂表达式(例如专用Named scope formatter),此方法允许在自定义格式化函数中利用表达式格式化程序。

相关问题