134 lines
4.4 KiB
C++
134 lines
4.4 KiB
C++
/*
|
|
* 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 <cstddef>
|
|
#include <string>
|
|
#include <map>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
|
#include <boost/smart_ptr/make_shared_object.hpp>
|
|
#include <boost/log/sinks.hpp>
|
|
#include <boost/log/expressions.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/manipulators/add_value.hpp>
|
|
|
|
namespace logging = boost::log;
|
|
namespace src = boost::log::sources;
|
|
namespace expr = boost::log::expressions;
|
|
namespace sinks = boost::log::sinks;
|
|
namespace keywords = boost::log::keywords;
|
|
|
|
//[ example_expressions_has_attr_stat_accumulator
|
|
// Declare attribute keywords
|
|
BOOST_LOG_ATTRIBUTE_KEYWORD(stat_stream, "StatisticStream", std::string)
|
|
BOOST_LOG_ATTRIBUTE_KEYWORD(change, "Change", int)
|
|
|
|
// A simple sink backend to accumulate statistic information
|
|
class my_stat_accumulator :
|
|
public sinks::basic_sink_backend< sinks::synchronized_feeding >
|
|
{
|
|
// A map of accumulated statistic values,
|
|
// ordered by the statistic information stream name
|
|
typedef std::map< std::string, int > stat_info_map;
|
|
stat_info_map m_stat_info;
|
|
|
|
public:
|
|
// Destructor
|
|
~my_stat_accumulator()
|
|
{
|
|
// Display the accumulated data
|
|
stat_info_map::const_iterator it = m_stat_info.begin(), end = m_stat_info.end();
|
|
for (; it != end; ++it)
|
|
{
|
|
std::cout << "Statistic stream: " << it->first
|
|
<< ", accumulated value: " << it->second << "\n";
|
|
}
|
|
std::cout.flush();
|
|
}
|
|
|
|
// The method is called for every log record being put into the sink backend
|
|
void consume(logging::record_view const& rec)
|
|
{
|
|
// First, acquire statistic information stream name
|
|
logging::value_ref< std::string, tag::stat_stream > name = rec[stat_stream];
|
|
if (name)
|
|
{
|
|
// Next, get the statistic value change
|
|
logging::value_ref< int, tag::change > change_amount = rec[change];
|
|
if (change_amount)
|
|
{
|
|
// Accumulate the statistic data
|
|
m_stat_info[name.get()] += change_amount.get();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// The function registers two sinks - one for statistic information,
|
|
// and another one for other records
|
|
void init()
|
|
{
|
|
boost::shared_ptr< logging::core > core = logging::core::get();
|
|
|
|
// Create a backend and attach a stream to it
|
|
boost::shared_ptr< sinks::text_ostream_backend > backend =
|
|
boost::make_shared< sinks::text_ostream_backend >();
|
|
backend->add_stream(
|
|
boost::shared_ptr< std::ostream >(new std::ofstream("test.log")));
|
|
|
|
// Create a frontend and setup filtering
|
|
typedef sinks::synchronous_sink< sinks::text_ostream_backend > log_sink_type;
|
|
boost::shared_ptr< log_sink_type > log_sink(new log_sink_type(backend));
|
|
// All records that don't have a "StatisticStream" attribute attached
|
|
// will go to the "test.log" file
|
|
log_sink->set_filter(!expr::has_attr(stat_stream));
|
|
|
|
core->add_sink(log_sink);
|
|
|
|
// Create another sink that will receive all statistic data
|
|
typedef sinks::synchronous_sink< my_stat_accumulator > stat_sink_type;
|
|
boost::shared_ptr< stat_sink_type > stat_sink(new stat_sink_type());
|
|
// All records with a "StatisticStream" string attribute attached
|
|
// will go to the my_stat_accumulator sink
|
|
stat_sink->set_filter(expr::has_attr(stat_stream));
|
|
|
|
core->add_sink(stat_sink);
|
|
}
|
|
|
|
// This simple macro will simplify putting statistic data into a logger
|
|
#define PUT_STAT(lg, stat_stream_name, change)\
|
|
if (true) {\
|
|
BOOST_LOG_SCOPED_LOGGER_TAG(lg, "StatisticStream", stat_stream_name);\
|
|
BOOST_LOG(lg) << logging::add_value("Change", (int)(change));\
|
|
} else ((void)0)
|
|
|
|
void logging_function()
|
|
{
|
|
src::logger lg;
|
|
|
|
// Put a regular log record, it will go to the "test.log" file
|
|
BOOST_LOG(lg) << "A regular log record";
|
|
|
|
// Put some statistic data
|
|
PUT_STAT(lg, "StreamOne", 10);
|
|
PUT_STAT(lg, "StreamTwo", 20);
|
|
PUT_STAT(lg, "StreamOne", -5);
|
|
}
|
|
//]
|
|
|
|
int main(int, char*[])
|
|
{
|
|
init();
|
|
logging_function();
|
|
|
|
return 0;
|
|
}
|