| 1 | #include <boost/log/sources/record_ostream.hpp>
|
|---|
| 2 | #include <boost/log/attributes.hpp>
|
|---|
| 3 | #include <boost/log/expressions.hpp>
|
|---|
| 4 | #include <boost/log/sinks/async_frontend.hpp>
|
|---|
| 5 | #include <boost/log/sinks/text_ostream_backend.hpp>
|
|---|
| 6 | #include <boost/log/sources/severity_channel_logger.hpp>
|
|---|
| 7 | #include <boost/log/core.hpp>
|
|---|
| 8 | #include <boost/core/null_deleter.hpp>
|
|---|
| 9 | #include <boost/make_shared.hpp>
|
|---|
| 10 |
|
|---|
| 11 | #include <iostream>
|
|---|
| 12 | #include <fstream>
|
|---|
| 13 |
|
|---|
| 14 | enum Level {
|
|---|
| 15 | A, B, C
|
|---|
| 16 | };
|
|---|
| 17 |
|
|---|
| 18 | enum Group {
|
|---|
| 19 | G0, G1, G2
|
|---|
| 20 | };
|
|---|
| 21 |
|
|---|
| 22 | std::ostream& operator<<(
|
|---|
| 23 | std::ostream& stream,
|
|---|
| 24 | const Level& level
|
|---|
| 25 | ) {
|
|---|
| 26 | static const std::array<std::string, 3> strings = {
|
|---|
| 27 | "A", "B", "C"
|
|---|
| 28 | };
|
|---|
| 29 | const auto levelIndex =
|
|---|
| 30 | static_cast<int>(level)-static_cast<int>(Level::A);
|
|---|
| 31 | assert(levelIndex >= 0);
|
|---|
| 32 | assert(levelIndex < strings.size());
|
|---|
| 33 |
|
|---|
| 34 | return stream << strings[levelIndex];
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | std::ostream& operator<<(
|
|---|
| 38 | std::ostream& stream,
|
|---|
| 39 | const Group& group
|
|---|
| 40 | ) {
|
|---|
| 41 | static const std::array<std::string, 3> strings = {
|
|---|
| 42 | "G0", "G1", "G2"
|
|---|
| 43 | };
|
|---|
| 44 | const auto groupIndex =
|
|---|
| 45 | static_cast<int>(group) - static_cast<int>(Group::G0);
|
|---|
| 46 | assert(groupIndex >= 0);
|
|---|
| 47 | assert(groupIndex < strings.size());
|
|---|
| 48 |
|
|---|
| 49 | return stream << strings[groupIndex];
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | namespace
|
|---|
| 53 | {
|
|---|
| 54 | BOOST_LOG_ATTRIBUTE_KEYWORD(level, "Severity", Level)
|
|---|
| 55 | BOOST_LOG_ATTRIBUTE_KEYWORD(group, "Channel", Group)
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 | namespace blog = boost::log;
|
|---|
| 59 | namespace expr = blog::expressions;
|
|---|
| 60 |
|
|---|
| 61 | void formatter(
|
|---|
| 62 | blog::record_view const& record,
|
|---|
| 63 | blog::formatting_ostream& stream
|
|---|
| 64 | ) {
|
|---|
| 65 | stream << "[" << record[level] << "]";
|
|---|
| 66 | stream << "[" << record[group] << "]";
|
|---|
| 67 | stream << " " << record[expr::smessage];
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | typedef blog::sinks::asynchronous_sink<
|
|---|
| 71 | boost::log::sinks::text_ostream_backend
|
|---|
| 72 | > async_sink_t;
|
|---|
| 73 |
|
|---|
| 74 | auto async_sink0 = boost::make_shared<async_sink_t>();
|
|---|
| 75 | auto async_sink1 = boost::make_shared<async_sink_t>();
|
|---|
| 76 |
|
|---|
| 77 | void init()
|
|---|
| 78 | {
|
|---|
| 79 | async_sink0->locked_backend()->add_stream(
|
|---|
| 80 | boost::shared_ptr<std::ostream>(&std::cout, boost::null_deleter{})
|
|---|
| 81 | );
|
|---|
| 82 | async_sink0->set_formatter(&formatter);
|
|---|
| 83 | blog::core::get()->add_sink(async_sink0);
|
|---|
| 84 |
|
|---|
| 85 | async_sink1->locked_backend()->add_stream(
|
|---|
| 86 | boost::make_shared<std::ofstream>("xxx.log")
|
|---|
| 87 | );
|
|---|
| 88 | async_sink1->set_formatter(&formatter);
|
|---|
| 89 | blog::core::get()->add_sink(async_sink1);
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | void deinit()
|
|---|
| 93 | {
|
|---|
| 94 | blog::core::get()->remove_sink(async_sink0); // No logs going into sink
|
|---|
| 95 | async_sink0->stop(); // Stop the feed loop
|
|---|
| 96 | async_sink0->flush(); // All the waiting records are flushed to sink
|
|---|
| 97 |
|
|---|
| 98 | blog::core::get()->remove_sink(async_sink1); // No logs going into sink
|
|---|
| 99 | async_sink1->stop(); // Stop the feed loop
|
|---|
| 100 | async_sink1->flush(); // All the waiting records are flushed to sink
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 | // Run this program several times. From time to time (timing issue?) you will see:
|
|---|
| 104 | // [][G0] Foo bar
|
|---|
| 105 | // [B][] Foo bar
|
|---|
| 106 | int main()
|
|---|
| 107 | {
|
|---|
| 108 | init();
|
|---|
| 109 | blog::sources::severity_channel_logger_mt<Level, Group> log;
|
|---|
| 110 |
|
|---|
| 111 | BOOST_LOG_CHANNEL_SEV(log, Group::G0, Level::B) << "Foo bar";
|
|---|
| 112 |
|
|---|
| 113 | deinit();
|
|---|
| 114 |
|
|---|
| 115 | std::cin.get();
|
|---|
| 116 |
|
|---|
| 117 | return 0;
|
|---|
| 118 | }
|
|---|