#include "test_boost_log.hpp"
#include <cassert>
#include <iostream>
#include <fstream>
#include <boost/shared_ptr.hpp>
#include <boost/log/common.hpp>
#include <boost/log/filters.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/empty_deleter.hpp>
#include <boost/log/utility/scoped_attribute.hpp>
namespace logging = boost::log;
namespace fmt = boost::log::formatters;
namespace flt = boost::log::filters;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace keywords = boost::log::keywords;
using boost::shared_ptr;
// Here we define our application severity levels.
enum severity_level
{
normal,
notification,
warning,
error,
critical
};
// The formatting logic for the severity level
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (
std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
{
static const char* const str[] =
{
"normal",
"notification",
"warning",
"error",
"critical"
};
if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
strm << str[lvl];
else
strm << static_cast< int >(lvl);
return strm;
}
int foo(src::logger& lg)
{
BOOST_LOG_FUNCTION();
BOOST_LOG(lg) << "foo is being called";
return 10;
}
test_boost_log::test_boost_log()
{
// For now we only create a text output sink:
typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
shared_ptr< text_sink > pSink(new text_sink);
{
text_sink::locked_backend_ptr pBackend = pSink->locked_backend();
shared_ptr< std::ostream > pStream(&std::clog, logging::empty_deleter());
pBackend->add_stream(pStream);
shared_ptr< std::ofstream > pStream2(new std::ofstream("sample.log"));
assert(pStream2->is_open());
pBackend->add_stream(pStream2);
}
logging::core::get()->add_sink(pSink);
src::logger lg;
BOOST_LOG(lg) << "Hello, World!";
pSink->locked_backend()->set_formatter(fmt::stream
<< fmt::attr("LineID") // First an attribute "LineID" is written to the log
<< " [" << fmt::date_time< boost::posix_time::ptime >("TimeStamp", "%d.%m.%Y %H:%M:%S.%f")
<< "] [" << fmt::attr< severity_level >("Severity", std::nothrow)
<< "] [" << fmt::time_duration< boost::posix_time::time_duration >("Uptime")
<< "] [" // then this delimiter separates it from the rest of the line
<< fmt::if_(flt::has_attr("Tag"))
[
fmt::stream << fmt::attr< std::string >("Tag")
<< "] [" // yet another delimiter
]
<< fmt::named_scope("Scope", keywords::iteration = fmt::reverse) << "] "
<< fmt::message()); // here goes the log record text
shared_ptr< logging::attribute > pCounter(new attrs::counter< unsigned int >(1));
// Since we intend to count all logging records ever made by the application,
// this attribute should clearly be global.
logging::core::get()->add_global_attribute("LineID", pCounter);
// And similarly add a time stamp
shared_ptr< logging::attribute > pTimeStamp(new attrs::local_clock());
logging::core::get()->add_global_attribute("TimeStamp", pTimeStamp);
// And an up time stopwatch
BOOST_LOG_SCOPED_THREAD_ATTR("Uptime", attrs::timer);
// Let's also track the execution scope from which the records are made
boost::shared_ptr< logging::attribute > pNamedScope(new attrs::named_scope());
logging::core::get()->add_thread_attribute("Scope", pNamedScope);
// We can mark the current execution scope now - it's the 'main' function
BOOST_LOG_FUNCTION();
// Let's try out the counter attribute and formatting
BOOST_LOG(lg) << "Some log line with a counter";
BOOST_LOG(lg) << "Another log line with the counter";
{
BOOST_LOG_NAMED_SCOPE("Tagging scope");
// Now these lines will be highlighted with the tag
BOOST_LOG(lg) << "Some tagged log line";
BOOST_LOG(lg) << "Another tagged log line";
}
// And this line is not highlighted anymore
BOOST_LOG(lg) << "Now the tag is removed";
pSink->set_filter(
flt::attr< severity_level >("Severity", std::nothrow) >= warning // Write all records with "warning" severity or higher
|| flt::attr< std::string >("Tag", std::nothrow).begins_with("IMPORTANT")); // ...or specifically tagged
src::severity_logger< severity_level > slg;
// These two lines test filtering based on severity
BOOST_LOG_SEV(slg, normal) << "A normal severity message, will not pass to the output";
BOOST_LOG_SEV(slg, error) << "An error severity message, will pass to the output";
{
// Next we try if the second condition of the filter works
// We mark following lines with a tag
BOOST_LOG_SCOPED_THREAD_TAG("Tag", std::string, "IMPORTANT MESSAGES");
BOOST_LOG(slg) << "Some really urgent line";
}
pSink->reset_filter();
// And moreover, it is possible to nest logging records. For example, this will
// be processed in the order of evaluation:
BOOST_LOG(lg) << "The result of foo is " << foo(lg);
} |