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)
13 #include <boost/smart_ptr/shared_ptr.hpp>
14 #include <boost/smart_ptr/make_shared_object.hpp>
15 #include <boost/log/sinks.hpp>
16 #include <boost/log/expressions.hpp>
17 #include <boost/log/attributes/scoped_attribute.hpp>
18 #include <boost/log/sources/logger.hpp>
19 #include <boost/log/sources/record_ostream.hpp>
20 #include <boost/log/utility/value_ref.hpp>
21 #include <boost/log/utility/manipulators/add_value.hpp>
23 namespace logging
= boost::log
;
24 namespace src
= boost::log::sources
;
25 namespace expr
= boost::log::expressions
;
26 namespace sinks
= boost::log::sinks
;
27 namespace keywords
= boost::log::keywords
;
29 //[ example_expressions_has_attr_stat_accumulator
30 // Declare attribute keywords
31 BOOST_LOG_ATTRIBUTE_KEYWORD(stat_stream
, "StatisticStream", std::string
)
32 BOOST_LOG_ATTRIBUTE_KEYWORD(change
, "Change", int)
34 // A simple sink backend to accumulate statistic information
35 class my_stat_accumulator
:
36 public sinks::basic_sink_backend
< sinks::synchronized_feeding
>
38 // A map of accumulated statistic values,
39 // ordered by the statistic information stream name
40 typedef std::map
< std::string
, int > stat_info_map
;
41 stat_info_map m_stat_info
;
45 ~my_stat_accumulator()
47 // Display the accumulated data
48 stat_info_map::const_iterator it
= m_stat_info
.begin(), end
= m_stat_info
.end();
49 for (; it
!= end
; ++it
)
51 std::cout
<< "Statistic stream: " << it
->first
52 << ", accumulated value: " << it
->second
<< "\n";
57 // The method is called for every log record being put into the sink backend
58 void consume(logging::record_view
const& rec
)
60 // First, acquire statistic information stream name
61 logging::value_ref
< std::string
, tag::stat_stream
> name
= rec
[stat_stream
];
64 // Next, get the statistic value change
65 logging::value_ref
< int, tag::change
> change_amount
= rec
[change
];
68 // Accumulate the statistic data
69 m_stat_info
[name
.get()] += change_amount
.get();
75 // The function registers two sinks - one for statistic information,
76 // and another one for other records
79 boost::shared_ptr
< logging::core
> core
= logging::core::get();
81 // Create a backend and attach a stream to it
82 boost::shared_ptr
< sinks::text_ostream_backend
> backend
=
83 boost::make_shared
< sinks::text_ostream_backend
>();
85 boost::shared_ptr
< std::ostream
>(new std::ofstream("test.log")));
87 // Create a frontend and setup filtering
88 typedef sinks::synchronous_sink
< sinks::text_ostream_backend
> log_sink_type
;
89 boost::shared_ptr
< log_sink_type
> log_sink(new log_sink_type(backend
));
90 // All records that don't have a "StatisticStream" attribute attached
91 // will go to the "test.log" file
92 log_sink
->set_filter(!expr::has_attr(stat_stream
));
94 core
->add_sink(log_sink
);
96 // Create another sink that will receive all statistic data
97 typedef sinks::synchronous_sink
< my_stat_accumulator
> stat_sink_type
;
98 boost::shared_ptr
< stat_sink_type
> stat_sink(new stat_sink_type());
99 // All records with a "StatisticStream" string attribute attached
100 // will go to the my_stat_accumulator sink
101 stat_sink
->set_filter(expr::has_attr(stat_stream
));
103 core
->add_sink(stat_sink
);
106 // This simple macro will simplify putting statistic data into a logger
107 #define PUT_STAT(lg, stat_stream_name, change)\
109 BOOST_LOG_SCOPED_LOGGER_TAG(lg, "StatisticStream", stat_stream_name);\
110 BOOST_LOG(lg) << logging::add_value("Change", (int)(change));\
113 void logging_function()
117 // Put a regular log record, it will go to the "test.log" file
118 BOOST_LOG(lg
) << "A regular log record";
120 // Put some statistic data
121 PUT_STAT(lg
, "StreamOne", 10);
122 PUT_STAT(lg
, "StreamTwo", 20);
123 PUT_STAT(lg
, "StreamOne", -5);
127 int main(int, char*[])