libs/log/example/doc/extension_filter_parser.cpp
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/phoenix.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/utility/value_ref.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/filter_parser.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;
//[ example_extension_filter_parser_point_definition
struct point
{
float m_x, m_y;
point() : m_x(0.0f), m_y(0.0f) {}
point(float x, float y) : m_x(x), m_y(y) {}
};
bool operator== (point const& left, point const& right);
bool operator!= (point const& left, point const& right);
template< typename CharT, typename TraitsT >
std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p);
template< typename CharT, typename TraitsT >
std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p);
//]
const float epsilon = 0.0001f;
bool operator== (point const& left, point const& right)
{
return (left.m_x - epsilon <= right.m_x && left.m_x + epsilon >= right.m_x) &&
(left.m_y - epsilon <= right.m_y && left.m_y + epsilon >= right.m_y);
}
bool operator!= (point const& left, point const& right)
{
return !(left == right);
}
template< typename CharT, typename TraitsT >
std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p)
{
if (strm.good())
strm << "(" << p.m_x << ", " << p.m_y << ")";
return strm;
}
template< typename CharT, typename TraitsT >
std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p)
{
if (strm.good())
{
CharT left_brace = static_cast< CharT >(0), comma = static_cast< CharT >(0), right_brace = static_cast< CharT >(0);
strm.setf(std::ios_base::skipws);
strm >> left_brace >> p.m_x >> comma >> p.m_y >> right_brace;
if (left_brace != '(' || comma != ',' || right_brace != ')')
strm.setstate(std::ios_base::failbit);
}
return strm;
}
#if 0
//[ example_extension_simple_filter_factory
void init_factories()
{
//<-
logging::register_simple_formatter_factory< point, char >("Coordinates");
//->
logging::register_simple_filter_factory< point, char >("Coordinates");
}
//]
#endif
//[ example_extension_custom_filter_factory
// Custom point filter factory
class point_filter_factory :
public logging::filter_factory< char >
{
public:
logging::filter on_exists_test(logging::attribute_name const& name)
{
return expr::has_attr< point >(name);
}
logging::filter on_equality_relation(logging::attribute_name const& name, string_type const& arg)
{
return expr::attr< point >(name) == parse_argument(arg);
}
logging::filter on_inequality_relation(logging::attribute_name const& name, string_type const& arg)
{
return expr::attr< point >(name) != parse_argument(arg);
}
private:
static point parse_argument(string_type const& arg)
{
std::istringstream strm(arg);
point val;
strm >> val;
if (strm.fail() || strm.bad())
throw std::runtime_error("Failed to parse point from \"" + arg + "\"");
return val;
}
};
void init_factories()
{
//<-
logging::register_simple_formatter_factory< point, char >("Coordinates");
//->
logging::register_filter_factory("Coordinates", boost::make_shared< point_filter_factory >());
}
//]
void init_logging()
{
init_factories();
logging::add_console_log
(
std::clog,
keywords::filter = "%Coordinates% = \"(10, 10)\"",
keywords::format = "%TimeStamp% %Coordinates% %Message%"
);
logging::add_common_attributes();
}
int main(int, char*[])
{
init_logging();
src::logger lg;
// We have to use scoped attributes in order coordinates to be passed to filters
{
BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(10, 10));
BOOST_LOG(lg) << "Hello, world with coordinates (10, 10)!";
}
{
BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(20, 20));
BOOST_LOG(lg) << "Hello, world with coordinates (20, 20)!"; // this message will be suppressed by filter
}
return 0;
}