
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.