Boost logo

Boost :

Subject: [boost] [log][phoenix] Questions on porting to phoenix
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2012-01-22 12:13:36


Hi,

[My apologies for the long post]

I'm trying to port filters and formatters of Boost.Log to Boost.Phoenix and
I'm not sure I understand what's the best way to go. Hope someone can help me
out.

A short introduction of the terms and what is currently available.

* An attribute value is a type-erased value, something similar to boost::any
but with more advanced interface to allow visitation and extraction of the
stored value.

* A log record is an object which contains a set of named attribute values.
For simplicity, let's say:

  class attribute_value;
  typedef map< string, attribute_value > attribute_values_view;
  class record
  {
  public:
    attribute_values_view const& attribute_values() const;
    string const& message() const;
  };

* A filter is a function that accepts attribute values and returns a bool:

  typedef function< bool (attribute_values_view const&) > filter;

The filter is assumed to pass the log record if it returns true.

* A formatter is a function that accepts a log record and a stream and outputs
strings or attribute values to the stream:

  typedef function< void (ostream&, record const&) > formatter;

* I already have the code that extracts attribute values from log records.

What I'm trying to achieve is something along these lines (this is not a
finalized interface yet):

  enum my_severity { info, warning, error };

  BOOST_LOG_REGISTER_ATTRIBUTE("Severity", severity, my_severity)

  filter flt = severity >= warning;
  formatter fmt = stream << "[" << severity << "] " << message;

Here, "stream" and "message" are keywords provided by Boost.Log, the former is
a placeholder for the stream argument of the formatter function, and the
latter returns the result of the record::message() method.

Now, the BOOST_LOG_REGISTER_ATTRIBUTE macro is what I'm struggling on. It
should create a new keyword (severity) which should:

1. Be a POD object to be statically initialized.
2. Contain the information on the type (my_severity) and name ("Severity") of
the attribute to be able to extract it from the log record.
3. Be a Phoenix object to initiate lazy expression generation.

>From what I gathered from the docs and examples, the generated keyword should
be a terminal, in terms of Proto. Am I correct? In order to produce the value,
during the evaluation the keyword should receive either a log record or a
attribute_values_view and I can't quite understand how do I do that.
Basically, I don't quite understand how do I declare and implement a terminal
so that it works with Phoenix. This question also applies to the "stream" and
"message" keywords but I suspect the solution will be similar.

Maybe there is an example of doing this in the docs or elsewhere. I'll be glad
if someone provides a link or example of doing this. Thanks in advance.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk