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 <stdexcept>
9 #include <string>
10 #include <iostream>
11 #include <boost/smart_ptr/shared_ptr.hpp>
12 #include <boost/lambda/lambda.hpp>
13 #include <boost/date_time/posix_time/posix_time.hpp>
14 
15 #include <boost/log/common.hpp>
16 #include <boost/log/expressions.hpp>
17 #include <boost/log/attributes.hpp>
18 #include <boost/log/sinks.hpp>
19 #include <boost/log/sources/logger.hpp>
20 
21 namespace logging = boost::log;
22 namespace attrs = boost::log::attributes;
23 namespace src = boost::log::sources;
24 namespace sinks = boost::log::sinks;
25 namespace expr = boost::log::expressions;
26 namespace keywords = boost::log::keywords;
27 
28 typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
29 
30 //[ example_sinks_xml_file_collecting
init_file_collecting(boost::shared_ptr<file_sink> sink)31 void init_file_collecting(boost::shared_ptr< file_sink > sink)
32 {
33     sink->locked_backend()->set_file_collector(sinks::file::make_collector(
34         keywords::target = "logs",                      /*< the target directory >*/
35         keywords::max_size = 16 * 1024 * 1024,          /*< maximum total size of the stored files, in bytes >*/
36         keywords::min_free_space = 100 * 1024 * 1024,   /*< minimum free space on the drive, in bytes >*/
37         keywords::max_files = 512                       /*< maximum number of stored files >*/
38     ));
39 }
40 //]
41 
42 #if 0
43 //[ example_sinks_xml_file
44 // Complete file sink type
45 typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
46 
47 void write_header(sinks::text_file_backend::stream_type& file)
48 {
49     file << "<?xml version=\"1.0\"?>\n<log>\n";
50 }
51 
52 void write_footer(sinks::text_file_backend::stream_type& file)
53 {
54     file << "</log>\n";
55 }
56 
57 void init_logging()
58 {
59     // Create a text file sink
60     boost::shared_ptr< file_sink > sink(new file_sink(
61         keywords::file_name = "%Y%m%d_%H%M%S_%5N.xml",  /*< the resulting file name pattern >*/
62         keywords::rotation_size = 16384                 /*< rotation size, in characters >*/
63     ));
64 
65     sink->set_formatter
66     (
67         expr::format("\t<record id=\"%1%\" timestamp=\"%2%\">%3%</record>")
68             % expr::attr< unsigned int >("RecordID")
69             % expr::attr< boost::posix_time::ptime >("TimeStamp")
70             % expr::xml_decor[ expr::stream << expr::smessage ]            /*< the log message has to be decorated, if it contains special characters >*/
71     );
72 
73     // Set header and footer writing functors
74     sink->locked_backend()->set_open_handler(&write_header);
75     sink->locked_backend()->set_close_handler(&write_footer);
76 
77     // Add the sink to the core
78     logging::core::get()->add_sink(sink);
79 }
80 //]
81 #endif
82 
83 //[ example_sinks_xml_file_final
init_logging()84 void init_logging()
85 {
86     // Create a text file sink
87     boost::shared_ptr< file_sink > sink(new file_sink(
88         keywords::file_name = "%Y%m%d_%H%M%S_%5N.xml",
89         keywords::rotation_size = 16384
90     ));
91 
92     // Set up where the rotated files will be stored
93     init_file_collecting(sink);
94 
95     // Upon restart, scan the directory for files matching the file_name pattern
96     sink->locked_backend()->scan_for_files();
97 
98     sink->set_formatter
99     (
100         expr::format("\t<record id=\"%1%\" timestamp=\"%2%\">%3%</record>")
101             % expr::attr< unsigned int >("RecordID")
102             % expr::attr< boost::posix_time::ptime >("TimeStamp")
103             % expr::xml_decor[ expr::stream << expr::smessage ]
104     );
105 
106     // Set header and footer writing functors
107     namespace bll = boost::lambda;
108 
109     sink->locked_backend()->set_open_handler
110     (
111         bll::_1 << "<?xml version=\"1.0\"?>\n<log>\n"
112     );
113     sink->locked_backend()->set_close_handler
114     (
115         bll::_1 << "</log>\n"
116     );
117 
118     // Add the sink to the core
119     logging::core::get()->add_sink(sink);
120 }
121 //]
122 
123 enum { LOG_RECORDS_TO_WRITE = 2000 };
124 
main(int argc,char * argv[])125 int main(int argc, char* argv[])
126 {
127     try
128     {
129         // Initialize logging library
130         init_logging();
131 
132         // And also add some attributes
133         logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
134         logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
135 
136         // Do some logging
137         src::logger lg;
138         for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
139         {
140             BOOST_LOG(lg) << "XML log record " << i;
141         }
142 
143         // Test that XML character decoration works
144         BOOST_LOG(lg) << "Special XML characters: &, <, >, \", '";
145 
146         return 0;
147     }
148     catch (std::exception& e)
149     {
150         std::cout << "FAILURE: " << e.what() << std::endl;
151         return 1;
152     }
153 }
154