• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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)
6  */
7 
8 #include <cstdlib>
9 #include <string>
10 #include <utility>
11 #include <stdexcept>
12 #include <boost/smart_ptr/shared_ptr.hpp>
13 #include <boost/phoenix.hpp>
14 #include <boost/log/trivial.hpp>
15 #include <boost/log/core.hpp>
16 #include <boost/log/expressions.hpp>
17 #include <boost/log/attributes/current_process_name.hpp>
18 #include <boost/log/sinks/sync_frontend.hpp>
19 #include <boost/log/sinks/basic_sink_backend.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 
25 namespace logging = boost::log;
26 namespace attrs = boost::log::attributes;
27 namespace src = boost::log::sources;
28 namespace expr = boost::log::expressions;
29 namespace sinks = boost::log::sinks;
30 namespace keywords = boost::log::keywords;
31 
32 //[ example_extension_app_launcher_definition
33 // The backend starts an external application to display notifications
34 class app_launcher :
35     public sinks::basic_formatted_sink_backend<
36         char,                                                                   /*< target character type >*/
37         sinks::synchronized_feeding                                             /*< in order not to spawn too many application instances we require records to be processed serial >*/
38     >
39 {
40 public:
41     // The function consumes the log records that come from the frontend
42     void consume(logging::record_view const& rec, string_type const& command_line);
43 };
44 //]
45 
46 //[ example_extension_app_launcher_consume
47 // The function consumes the log records that come from the frontend
consume(logging::record_view const & rec,string_type const & command_line)48 void app_launcher::consume(logging::record_view const& rec, string_type const& command_line)
49 {
50     std::system(command_line.c_str());
51 }
52 //]
53 
54 //[ example_extension_app_launcher_formatting
55 BOOST_LOG_ATTRIBUTE_KEYWORD(process_name, "ProcessName", std::string)
56 BOOST_LOG_ATTRIBUTE_KEYWORD(caption, "Caption", std::string)
57 
58 // Custom severity level formatting function
severity_level_as_urgency(logging::value_ref<logging::trivial::severity_level,logging::trivial::tag::severity> const & level)59 std::string severity_level_as_urgency(
60     logging::value_ref< logging::trivial::severity_level, logging::trivial::tag::severity > const& level)
61 {
62     if (!level || level.get() == logging::trivial::info)
63         return "normal";
64     logging::trivial::severity_level lvl = level.get();
65     if (lvl < logging::trivial::info)
66         return "low";
67     else
68         return "critical";
69 }
70 
71 // The function initializes the logging library
init_logging()72 void init_logging()
73 {
74     boost::shared_ptr< logging::core > core = logging::core::get();
75 
76     typedef sinks::synchronous_sink< app_launcher > sink_t;
77     boost::shared_ptr< sink_t > sink(new sink_t());
78 
79     const std::pair< const char*, const char* > shell_decorations[] =
80     {
81         std::pair< const char*, const char* >("\"", "\\\""),
82         std::pair< const char*, const char* >("$", "\\$"),
83         std::pair< const char*, const char* >("!", "\\!")
84     };
85 
86     // Make the formatter generate the command line for notify-send
87     sink->set_formatter
88     (
89         expr::stream << "notify-send -t 2000 -u "
90             << boost::phoenix::bind(&severity_level_as_urgency, logging::trivial::severity.or_none())
91             << expr::if_(expr::has_attr(process_name))
92                [
93                     expr::stream << " -a '" << process_name << "'"
94                ]
95             << expr::if_(expr::has_attr(caption))
96                [
97                     expr::stream << " \"" << expr::char_decor(shell_decorations)[ expr::stream << caption ] << "\""
98                ]
99             << " \"" << expr::char_decor(shell_decorations)[ expr::stream << expr::message ] << "\""
100     );
101 
102     core->add_sink(sink);
103 
104     // Add attributes that we will use
105     core->add_global_attribute("ProcessName", attrs::current_process_name());
106 }
107 //]
108 
109 //[ example_extension_app_launcher_logging
test_notifications()110 void test_notifications()
111 {
112     BOOST_LOG_TRIVIAL(debug) << "Hello, it's a simple notification";
113     BOOST_LOG_TRIVIAL(info) << logging::add_value(caption, "Caption text") << "And this notification has caption as well";
114 }
115 //]
116 
main(int,char * [])117 int main(int, char*[])
118 {
119     init_logging();
120     test_notifications();
121 
122     return 0;
123 }
124