2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
11 #include <boost/smart_ptr/shared_ptr.hpp>
12 #include <boost/smart_ptr/make_shared_object.hpp>
13 #include <boost/lexical_cast.hpp>
14 #include <boost/phoenix.hpp>
15 #include <boost/log/core.hpp>
16 #include <boost/log/expressions.hpp>
17 #include <boost/log/attributes/attribute_name.hpp>
18 #include <boost/log/attributes/scoped_attribute.hpp>
19 #include <boost/log/sources/logger.hpp>
20 #include <boost/log/sources/record_ostream.hpp>
21 #include <boost/log/utility/value_ref.hpp>
22 #include <boost/log/utility/formatting_ostream.hpp>
23 #include <boost/log/utility/manipulators/add_value.hpp>
24 #include <boost/log/utility/setup/filter_parser.hpp>
25 #include <boost/log/utility/setup/common_attributes.hpp>
26 #include <boost/log/utility/setup/console.hpp>
28 namespace logging
= boost::log
;
29 namespace attrs
= boost::log::attributes
;
30 namespace src
= boost::log::sources
;
31 namespace expr
= boost::log::expressions
;
32 namespace sinks
= boost::log::sinks
;
33 namespace keywords
= boost::log::keywords
;
39 point() : m_x(0.0f
), m_y(0.0f
) {}
40 point(float x
, float y
) : m_x(x
), m_y(y
) {}
43 bool operator== (point
const& left
, point
const& right
);
44 bool operator!= (point
const& left
, point
const& right
);
46 template< typename CharT
, typename TraitsT
>
47 std::basic_ostream
< CharT
, TraitsT
>& operator<< (std::basic_ostream
< CharT
, TraitsT
>& strm
, point
const& p
);
48 template< typename CharT
, typename TraitsT
>
49 std::basic_istream
< CharT
, TraitsT
>& operator>> (std::basic_istream
< CharT
, TraitsT
>& strm
, point
& p
);
51 const float epsilon
= 0.0001f
;
53 bool operator== (point
const& left
, point
const& right
)
55 return (left
.m_x
- epsilon
<= right
.m_x
&& left
.m_x
+ epsilon
>= right
.m_x
) &&
56 (left
.m_y
- epsilon
<= right
.m_y
&& left
.m_y
+ epsilon
>= right
.m_y
);
59 bool operator!= (point
const& left
, point
const& right
)
61 return !(left
== right
);
64 template< typename CharT
, typename TraitsT
>
65 std::basic_ostream
< CharT
, TraitsT
>& operator<< (std::basic_ostream
< CharT
, TraitsT
>& strm
, point
const& p
)
68 strm
<< "(" << p
.m_x
<< ", " << p
.m_y
<< ")";
72 template< typename CharT
, typename TraitsT
>
73 std::basic_istream
< CharT
, TraitsT
>& operator>> (std::basic_istream
< CharT
, TraitsT
>& strm
, point
& p
)
77 CharT left_brace
= static_cast< CharT
>(0), comma
= static_cast< CharT
>(0), right_brace
= static_cast< CharT
>(0);
78 strm
.setf(std::ios_base::skipws
);
79 strm
>> left_brace
>> p
.m_x
>> comma
>> p
.m_y
>> right_brace
;
80 if (left_brace
!= '(' || comma
!= ',' || right_brace
!= ')')
81 strm
.setstate(std::ios_base::failbit
);
86 //[ example_extension_filter_parser_rectangle_definition
89 point m_top_left
, m_bottom_right
;
92 template< typename CharT
, typename TraitsT
>
93 std::basic_ostream
< CharT
, TraitsT
>& operator<< (std::basic_ostream
< CharT
, TraitsT
>& strm
, rectangle
const& r
);
94 template< typename CharT
, typename TraitsT
>
95 std::basic_istream
< CharT
, TraitsT
>& operator>> (std::basic_istream
< CharT
, TraitsT
>& strm
, rectangle
& r
);
98 template< typename CharT
, typename TraitsT
>
99 std::basic_ostream
< CharT
, TraitsT
>& operator<< (std::basic_ostream
< CharT
, TraitsT
>& strm
, rectangle
const& r
)
102 strm
<< "{" << r
.m_top_left
<< " - " << r
.m_bottom_right
<< "}";
106 template< typename CharT
, typename TraitsT
>
107 std::basic_istream
< CharT
, TraitsT
>& operator>> (std::basic_istream
< CharT
, TraitsT
>& strm
, rectangle
& r
)
111 CharT left_brace
= static_cast< CharT
>(0), dash
= static_cast< CharT
>(0), right_brace
= static_cast< CharT
>(0);
112 strm
.setf(std::ios_base::skipws
);
113 strm
>> left_brace
>> r
.m_top_left
>> dash
>> r
.m_bottom_right
>> right_brace
;
114 if (left_brace
!= '{' || dash
!= '-' || right_brace
!= '}')
115 strm
.setstate(std::ios_base::failbit
);
121 //[ example_extension_custom_filter_factory_with_custom_rel
122 // The function checks if the point is inside the rectangle
123 bool is_in_rectangle(logging::value_ref
< point
> const& p
, rectangle
const& r
)
127 return p
->m_x
>= r
.m_top_left
.m_x
&& p
->m_x
<= r
.m_bottom_right
.m_x
&&
128 p
->m_y
>= r
.m_top_left
.m_y
&& p
->m_y
<= r
.m_bottom_right
.m_y
;
133 // Custom point filter factory
134 class point_filter_factory
:
135 public logging::filter_factory
< char >
138 logging::filter
on_exists_test(logging::attribute_name
const& name
)
140 return expr::has_attr
< point
>(name
);
143 logging::filter
on_equality_relation(logging::attribute_name
const& name
, string_type
const& arg
)
145 return expr::attr
< point
>(name
) == boost::lexical_cast
< point
>(arg
);
148 logging::filter
on_inequality_relation(logging::attribute_name
const& name
, string_type
const& arg
)
150 return expr::attr
< point
>(name
) != boost::lexical_cast
< point
>(arg
);
153 logging::filter
on_custom_relation(logging::attribute_name
const& name
, string_type
const& rel
, string_type
const& arg
)
155 if (rel
== "is_in_rectangle")
157 return boost::phoenix::bind(&is_in_rectangle
, expr::attr
< point
>(name
), boost::lexical_cast
< rectangle
>(arg
));
159 throw std::runtime_error("Unsupported filter relation: " + rel
);
163 void init_factories()
166 logging::register_simple_formatter_factory
< point
, char >("Coordinates");
168 logging::register_filter_factory("Coordinates", boost::make_shared
< point_filter_factory
>());
176 logging::add_console_log
179 keywords::filter
= "%Coordinates% is_in_rectangle \"{(0, 0) - (20, 20)}\"",
180 keywords::format
= "%TimeStamp% %Coordinates% %Message%"
183 logging::add_common_attributes();
186 int main(int, char*[])
192 // We have to use scoped attributes in order coordinates to be passed to filters
194 BOOST_LOG_SCOPED_LOGGER_TAG(lg
, "Coordinates", point(10, 10));
195 BOOST_LOG(lg
) << "Hello, world with coordinates (10, 10)!";
198 BOOST_LOG_SCOPED_LOGGER_TAG(lg
, "Coordinates", point(50, 50));
199 BOOST_LOG(lg
) << "Hello, world with coordinates (50, 50)!"; // this message will be suppressed by filter