Boost logo

Boost :

Subject: Re: [boost] [Log] Pre-review questions
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2010-03-14 15:00:42


On 03/14/2010 06:29 PM, Christian Holmquist wrote:
>
> Simple task 1
> I've two source level attributes, System and Severity. I wish to create a
> log macro that takes these two arguments.

[snip]

> The above is not a complicated scenario and I should be able to quickly find
> an answer. Maybe I've just missed it..:)

Well, depending on how you use the "System" attribute, you can take
either of the following approaches:

1. Use the severity_channel_logger. The severity attribute will handle
your severity levels, and the "System" attribute will be represented as
a channel. This means that you would have to have a logger per "System".

   typedef src::severity_channel_logger<
     SeverityLevel,
     System
> my_logger_t;

   my_logger_t lg_SYSTEM_A(keywords::channel = SYSTEM_A);
   my_logger_t lg_SYSTEM_B(keywords::channel = SYSTEM_B);

   BOOST_LOG_SEV(lg_SYSTEM_A, INFO) << "Hello";

If you want to, you can define your macro like this:

   #define LOG(x, y, z) BOOST_LOG_SEV(lg_ ## x, y) << z

   LOG(SYSTEM_A, INFO, "Hello");

2. If having several loggers is not an option, but the system attribute
is needed occasionally, you can add the attribute as a tag. The
technique is described here:

http://tinyurl.com/y8a2gfv

3. If the system attribute is needed all the time, then I might suggest
to develop a logger feature, pretty much like it is described in the
docs by the link I posted, but with one minor difference. The attribute
should be added to the logger on its constructor, and only modified on
the open_record call. Altering the example at the link, it should look
something like that:

   template< typename BaseT >
   class system_feature :
     public BaseT
   {
   public:
     typedef typename BaseT::string_type string_type;
     typedef typename BaseT::attribute_set_type attribute_set_type;
     typedef typename BaseT::threading_model threading_model;
     typedef typename BaseT::record_type record_type;

     shared_ptr< attrs::mutable_constant< System > > m_pSystem;

   public:
     system_feature() :
       m_pSystem(new attrs::mutable_constant< System >(SYSTEM_A))
     {
       this->add_attribute_unlocked("System", m_pSystem);
     }
     system_feature(record_tagger_feature const& that) :
       BaseT(static_cast< BaseT const& >(that)),
       m_pSystem(new attrs::mutable_constant< System >(SYSTEM_A))
     {
       this->add_attribute_unlocked("System", m_pSystem);
     }
     template< typename ArgsT >
     system_feature(ArgsT const& args) :
       BaseT(args),
       m_pSystem(new attrs::mutable_constant<
         System
>(args[keywords::system]))
     {
       this->add_attribute_unlocked("System", m_pSystem);
     }

     typedef typename src::strictest_lock<
       boost::lock_guard< threading_model >,
       typename BaseT::open_record_lock
>::type open_record_lock;

   protected:
     template< typename ArgsT >
     record_type open_record_unlocked(ArgsT const& args)
     {
       m_pSystem->set_value(args[keywords::system]);
       return BaseT::open_record_unlocked(args);
     }
   };

> Simple task 2
> Create a custom filter without using any Lambda magic.
>
> struct Filter
> {
> System sys;
> SeverityLevel sev;
>
> bool operator()(???)
> {
> // pseudo-code, since I don't know how to write this
> return Attributes["System"] == sys&& Attributes["SeverityLevel"]>=
> sev;
> }
> };

Well, if you want to develop a filter from ground, here you go:

   struct Filter
   {
     typedef bool result_type;

     System m_sys;
     SeverityLevel m_sev;

     result_type operator() (attribute_values_view const& attrs) const
     {
       shared_ptr< logging::attribute > attr = attrs["System"];
       if (attr)
       {
         optional< System > sys = attr->get< System >();
         if (!sys)
           throw runtime_error("The System attribute has invalid type");

         if (sys.get() != m_sys)
           return false;
       }
       else
         throw runtime_error("The System attribute not found");

       attr = attrs["Severity"];
       if (attr)
       {
         optional< SeverityLevel > sev = attr->get< SeverityLevel >();
         if (!sev)
           throw runtime_error(
             "The Severity attribute has invalid type");

         if (sev.get() != m_sev)
           return false;
       }
       else
         throw runtime_error("The Severity attribute not found");

       return true;
     }
   };

But honestly, it would be much simpler if you used the tools provided by
the library.


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