]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/src/setup/init_from_settings.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / log / src / setup / init_from_settings.cpp
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 * \file init_from_settings.cpp
9 * \author Andrey Semashev
10 * \date 11.10.2009
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16 #ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
17
18 #if defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \
19 && (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
20 // This warning is caused by a compiler bug which is exposed when boost::optional is used: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47679
21 // It has to be disabled here, before any code is included, since otherwise it doesn't help and the warning is still emitted.
22 // '*((void*)& foo +2)' may be used uninitialized in this function
23 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
24 #endif
25
26 #include <boost/log/detail/setup_config.hpp>
27 #include <cstddef>
28 #include <ios>
29 #include <map>
30 #include <vector>
31 #include <string>
32 #include <utility>
33 #include <iostream>
34 #include <typeinfo>
35 #include <stdexcept>
36 #include <algorithm>
37 #include <boost/type.hpp>
38 #include <boost/bind.hpp>
39 #include <boost/limits.hpp>
40 #include <boost/cstdint.hpp>
41 #include <boost/smart_ptr/make_shared_object.hpp>
42 #include <boost/core/null_deleter.hpp>
43 #include <boost/optional/optional.hpp>
44 #include <boost/filesystem/path.hpp>
45 #include <boost/date_time/date_defs.hpp>
46 #include <boost/property_tree/ptree.hpp>
47 #include <boost/mpl/if.hpp>
48 #include <boost/type_traits/is_unsigned.hpp>
49 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
50 #include <boost/log/detail/code_conversion.hpp>
51 #include <boost/log/detail/singleton.hpp>
52 #include <boost/log/detail/default_attribute_names.hpp>
53 #include <boost/log/core.hpp>
54 #include <boost/log/sinks.hpp>
55 #include <boost/log/exceptions.hpp>
56 #include <boost/log/sinks/frontend_requirements.hpp>
57 #include <boost/log/expressions/filter.hpp>
58 #include <boost/log/expressions/formatter.hpp>
59 #include <boost/log/utility/string_literal.hpp>
60 #include <boost/log/utility/functional/nop.hpp>
61 #include <boost/log/utility/setup/from_settings.hpp>
62 #include <boost/log/utility/setup/filter_parser.hpp>
63 #include <boost/log/utility/setup/formatter_parser.hpp>
64 #if !defined(BOOST_LOG_NO_ASIO)
65 #include <boost/asio/ip/address.hpp>
66 #endif
67 #if !defined(BOOST_LOG_NO_THREADS)
68 #include <boost/log/detail/locks.hpp>
69 #include <boost/log/detail/light_rw_mutex.hpp>
70 #endif
71 #include "parser_utils.hpp"
72 #include "spirit_encoding.hpp"
73 #include <boost/log/detail/header.hpp>
74
75 namespace qi = boost::spirit::qi;
76
77 namespace boost {
78
79 BOOST_LOG_OPEN_NAMESPACE
80
81 BOOST_LOG_ANONYMOUS_NAMESPACE {
82
83 //! Throws an exception when a parameter value is not valid
84 BOOST_LOG_NORETURN void throw_invalid_value(const char* param_name)
85 {
86 std::string descr = std::string("Invalid parameter \"")
87 + param_name
88 + "\" value";
89 BOOST_LOG_THROW_DESCR(invalid_value, descr);
90 }
91
92 //! Extracts an integral value from parameter value
93 template< typename IntT, typename CharT >
94 inline IntT param_cast_to_int(const char* param_name, std::basic_string< CharT > const& value)
95 {
96 IntT res = 0;
97 typedef typename mpl::if_<
98 is_unsigned< IntT >,
99 qi::extract_uint< IntT, 10, 1, -1 >,
100 qi::extract_int< IntT, 10, 1, -1 >
101 >::type extract;
102 const CharT* begin = value.c_str(), *end = begin + value.size();
103 if (extract::call(begin, end, res) && begin == end)
104 return res;
105 else
106 throw_invalid_value(param_name);
107 }
108
109 //! Case-insensitive character comparison predicate
110 struct is_case_insensitive_equal
111 {
112 typedef bool result_type;
113
114 template< typename CharT >
115 result_type operator() (CharT left, CharT right) const BOOST_NOEXCEPT
116 {
117 typedef typename boost::log::aux::encoding< CharT >::type encoding;
118 return encoding::tolower(left) == encoding::tolower(right);
119 }
120 };
121
122 //! Extracts a boolean value from parameter value
123 template< typename CharT >
124 inline bool param_cast_to_bool(const char* param_name, std::basic_string< CharT > const& value)
125 {
126 typedef CharT char_type;
127 typedef boost::log::aux::char_constants< char_type > constants;
128 typedef boost::log::basic_string_literal< char_type > literal_type;
129
130 const char_type* begin = value.c_str(), *end = begin + value.size();
131 std::size_t len = end - begin;
132
133 literal_type keyword = constants::true_keyword();
134 if (keyword.size() == len && std::equal(begin, end, keyword.c_str(), is_case_insensitive_equal()))
135 {
136 return true;
137 }
138 else
139 {
140 keyword = constants::false_keyword();
141 if (keyword.size() == len && std::equal(begin, end, keyword.c_str(), is_case_insensitive_equal()))
142 {
143 return false;
144 }
145 else
146 {
147 return param_cast_to_int< unsigned int >(param_name, value) != 0;
148 }
149 }
150 }
151
152 #if !defined(BOOST_LOG_NO_ASIO)
153 //! Extracts a network address from parameter value
154 template< typename CharT >
155 inline std::string param_cast_to_address(const char* param_name, std::basic_string< CharT > const& value)
156 {
157 return log::aux::to_narrow(value);
158 }
159 #endif // !defined(BOOST_LOG_NO_ASIO)
160
161 template< typename CharT >
162 inline bool is_weekday(const CharT* str, std::size_t len, boost::log::basic_string_literal< CharT > const& weekday, boost::log::basic_string_literal< CharT > const& short_weekday)
163 {
164 return (len == weekday.size() && std::equal(weekday.begin(), weekday.end(), str)) ||
165 (len == short_weekday.size() && std::equal(short_weekday.begin(), short_weekday.end(), str));
166 }
167
168 //! The function extracts the file rotation time point predicate from the parameter
169 template< typename CharT >
170 sinks::file::rotation_at_time_point param_cast_to_rotation_time_point(const char* param_name, std::basic_string< CharT > const& value)
171 {
172 typedef CharT char_type;
173 typedef boost::log::aux::char_constants< char_type > constants;
174 typedef typename boost::log::aux::encoding< char_type >::type encoding;
175 typedef qi::extract_uint< unsigned short, 10, 1, 2 > day_extract;
176 typedef qi::extract_uint< unsigned char, 10, 2, 2 > time_component_extract;
177
178 const char_type colon = static_cast< char_type >(':');
179 optional< date_time::weekdays > weekday;
180 optional< unsigned short > day;
181 unsigned char hour = 0, minute = 0, second = 0;
182 const char_type* begin = value.c_str(), *end = begin + value.size();
183
184 if (!encoding::isalnum(*begin)) // begin is null-terminated, so we also check that the string is not empty here
185 throw_invalid_value(param_name);
186
187 const char_type* p = begin + 1;
188 if (encoding::isalpha(*begin))
189 {
190 // This must be a weekday
191 while (encoding::isalpha(*p))
192 ++p;
193
194 std::size_t len = p - begin;
195 if (is_weekday(begin, len, constants::monday_keyword(), constants::short_monday_keyword()))
196 weekday = date_time::Monday;
197 else if (is_weekday(begin, len, constants::tuesday_keyword(), constants::short_tuesday_keyword()))
198 weekday = date_time::Tuesday;
199 else if (is_weekday(begin, len, constants::wednesday_keyword(), constants::short_wednesday_keyword()))
200 weekday = date_time::Wednesday;
201 else if (is_weekday(begin, len, constants::thursday_keyword(), constants::short_thursday_keyword()))
202 weekday = date_time::Thursday;
203 else if (is_weekday(begin, len, constants::friday_keyword(), constants::short_friday_keyword()))
204 weekday = date_time::Friday;
205 else if (is_weekday(begin, len, constants::saturday_keyword(), constants::short_saturday_keyword()))
206 weekday = date_time::Saturday;
207 else if (is_weekday(begin, len, constants::sunday_keyword(), constants::short_sunday_keyword()))
208 weekday = date_time::Sunday;
209 else
210 throw_invalid_value(param_name);
211 }
212 else
213 {
214 // This may be either a month day or an hour
215 while (encoding::isdigit(*p))
216 ++p;
217
218 if (encoding::isspace(*p))
219 {
220 // This is a month day
221 unsigned short mday = 0;
222 const char_type* b = begin;
223 if (!day_extract::call(b, p, mday) || b != p)
224 throw_invalid_value(param_name);
225
226 day = mday;
227 }
228 else if (*p == colon)
229 {
230 // This is an hour, reset the pointer
231 p = begin;
232 }
233 else
234 throw_invalid_value(param_name);
235 }
236
237 // Skip spaces
238 while (encoding::isspace(*p))
239 ++p;
240
241 // Parse hour
242 if (!time_component_extract::call(p, end, hour) || *p != colon)
243 throw_invalid_value(param_name);
244 ++p;
245
246 // Parse minute
247 if (!time_component_extract::call(p, end, minute) || *p != colon)
248 throw_invalid_value(param_name);
249 ++p;
250
251 // Parse second
252 if (!time_component_extract::call(p, end, second) || p != end)
253 throw_invalid_value(param_name);
254
255 // Construct the predicate
256 if (weekday)
257 return sinks::file::rotation_at_time_point(weekday.get(), hour, minute, second);
258 else if (day)
259 return sinks::file::rotation_at_time_point(gregorian::greg_day(day.get()), hour, minute, second);
260 else
261 return sinks::file::rotation_at_time_point(hour, minute, second);
262 }
263
264 //! Base class for default sink factories
265 template< typename CharT >
266 class basic_default_sink_factory :
267 public sink_factory< CharT >
268 {
269 public:
270 typedef sink_factory< CharT > base_type;
271 typedef typename base_type::char_type char_type;
272 typedef typename base_type::string_type string_type;
273 typedef typename base_type::settings_section settings_section;
274 typedef boost::log::aux::char_constants< char_type > constants;
275
276 protected:
277 //! Sink backend character selection function
278 template< typename InitializerT >
279 static shared_ptr< sinks::sink > select_backend_character_type(settings_section const& params, InitializerT initializer)
280 {
281 #if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
282 if (optional< string_type > wide_param = params["Wide"])
283 {
284 if (param_cast_to_bool("Wide", wide_param.get()))
285 return initializer(params, type< wchar_t >());
286 }
287
288 return initializer(params, type< char >());
289 #elif defined(BOOST_LOG_USE_CHAR)
290 return initializer(params, type< char >());
291 #elif defined(BOOST_LOG_USE_WCHAR_T)
292 return initializer(params, type< wchar_t >());
293 #endif
294 }
295
296 //! The function initializes common parameters of a formatting sink and returns the constructed sink
297 template< typename BackendT >
298 static shared_ptr< sinks::sink > init_sink(shared_ptr< BackendT > const& backend, settings_section const& params)
299 {
300 typedef BackendT backend_t;
301 typedef typename sinks::has_requirement<
302 typename backend_t::frontend_requirements,
303 sinks::formatted_records
304 >::type is_formatting_t;
305
306 // Filter
307 filter filt;
308 if (optional< string_type > filter_param = params["Filter"])
309 {
310 filt = parse_filter(filter_param.get());
311 }
312
313 shared_ptr< sinks::basic_sink_frontend > p;
314
315 #if !defined(BOOST_LOG_NO_THREADS)
316 // Asynchronous. TODO: make it more flexible.
317 bool async = false;
318 if (optional< string_type > async_param = params["Asynchronous"])
319 {
320 async = param_cast_to_bool("Asynchronous", async_param.get());
321 }
322
323 // Construct the frontend, considering Asynchronous parameter
324 if (!async)
325 {
326 p = init_formatter(boost::make_shared< sinks::synchronous_sink< backend_t > >(backend), params, is_formatting_t());
327 }
328 else
329 {
330 p = init_formatter(boost::make_shared< sinks::asynchronous_sink< backend_t > >(backend), params, is_formatting_t());
331
332 // https://svn.boost.org/trac/boost/ticket/10638
333 // The user doesn't have a way to process excaptions from the dedicated thread anyway, so just suppress them instead of
334 // terminating the application.
335 p->set_exception_handler(nop());
336 }
337 #else
338 // When multithreading is disabled we always use the unlocked sink frontend
339 p = init_formatter(boost::make_shared< sinks::unlocked_sink< backend_t > >(backend), params, is_formatting_t());
340 #endif
341
342 p->set_filter(filt);
343
344 return p;
345 }
346
347 private:
348 //! The function initializes formatter for the sinks that support formatting
349 template< typename SinkT >
350 static shared_ptr< SinkT > init_formatter(shared_ptr< SinkT > const& sink, settings_section const& params, mpl::true_)
351 {
352 // Formatter
353 if (optional< string_type > format_param = params["Format"])
354 {
355 typedef typename SinkT::char_type sink_char_type;
356 std::basic_string< sink_char_type > format_str;
357 log::aux::code_convert(format_param.get(), format_str);
358 sink->set_formatter(parse_formatter(format_str));
359 }
360 return sink;
361 }
362 template< typename SinkT >
363 static shared_ptr< SinkT > init_formatter(shared_ptr< SinkT > const& sink, settings_section const& params, mpl::false_)
364 {
365 return sink;
366 }
367 };
368
369 //! Default console sink factory
370 template< typename CharT >
371 class default_console_sink_factory :
372 public basic_default_sink_factory< CharT >
373 {
374 public:
375 typedef basic_default_sink_factory< CharT > base_type;
376 typedef typename base_type::char_type char_type;
377 typedef typename base_type::string_type string_type;
378 typedef typename base_type::settings_section settings_section;
379 typedef typename base_type::constants constants;
380
381 private:
382 struct impl;
383 friend struct impl;
384 struct impl
385 {
386 typedef shared_ptr< sinks::sink > result_type;
387
388 template< typename BackendCharT >
389 result_type operator() (settings_section const& params, type< BackendCharT >) const
390 {
391 // Construct the backend
392 typedef boost::log::aux::char_constants< BackendCharT > constants;
393 typedef sinks::basic_text_ostream_backend< BackendCharT > backend_t;
394 shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
395 backend->add_stream(shared_ptr< typename backend_t::stream_type >(&constants::get_console_log_stream(), boost::null_deleter()));
396
397 // Auto flush
398 if (optional< string_type > auto_flush_param = params["AutoFlush"])
399 {
400 backend->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param.get()));
401 }
402
403 return base_type::init_sink(backend, params);
404 }
405 };
406
407 public:
408 //! The function constructs a sink that writes log records to the console
409 shared_ptr< sinks::sink > create_sink(settings_section const& params)
410 {
411 return base_type::select_backend_character_type(params, impl());
412 }
413 };
414
415 //! Default text file sink factory
416 template< typename CharT >
417 class default_text_file_sink_factory :
418 public basic_default_sink_factory< CharT >
419 {
420 public:
421 typedef basic_default_sink_factory< CharT > base_type;
422 typedef typename base_type::char_type char_type;
423 typedef typename base_type::string_type string_type;
424 typedef typename base_type::settings_section settings_section;
425 typedef typename base_type::constants constants;
426
427 public:
428 //! The function constructs a sink that writes log records to a text file
429 shared_ptr< sinks::sink > create_sink(settings_section const& params)
430 {
431 typedef sinks::text_file_backend backend_t;
432 shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
433
434 // FileName
435 if (optional< string_type > file_name_param = params["FileName"])
436 {
437 backend->set_file_name_pattern(filesystem::path(file_name_param.get()));
438 }
439 else
440 BOOST_LOG_THROW_DESCR(missing_value, "File name is not specified");
441
442 // File rotation size
443 if (optional< string_type > rotation_size_param = params["RotationSize"])
444 {
445 backend->set_rotation_size(param_cast_to_int< uintmax_t >("RotationSize", rotation_size_param.get()));
446 }
447
448 // File rotation interval
449 if (optional< string_type > rotation_interval_param = params["RotationInterval"])
450 {
451 backend->set_time_based_rotation(sinks::file::rotation_at_time_interval(
452 posix_time::seconds(param_cast_to_int< unsigned int >("RotationInterval", rotation_interval_param.get()))));
453 }
454 else if (optional< string_type > rotation_time_point_param = params["RotationTimePoint"])
455 {
456 // File rotation time point
457 backend->set_time_based_rotation(param_cast_to_rotation_time_point("RotationTimePoint", rotation_time_point_param.get()));
458 }
459
460 // Final rotation
461 if (optional< string_type > enable_final_rotation_param = params["EnableFinalRotation"])
462 {
463 backend->enable_final_rotation(param_cast_to_bool("EnableFinalRotation", enable_final_rotation_param.get()));
464 }
465
466 // Auto flush
467 if (optional< string_type > auto_flush_param = params["AutoFlush"])
468 {
469 backend->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param.get()));
470 }
471
472 // Append
473 if (optional< string_type > append_param = params["Append"])
474 {
475 if (param_cast_to_bool("Append", append_param.get()))
476 backend->set_open_mode(std::ios_base::out | std::ios_base::app);
477 }
478
479 // File collector parameters
480 // Target directory
481 if (optional< string_type > target_param = params["Target"])
482 {
483 filesystem::path target_dir(target_param.get());
484
485 // Max total size
486 uintmax_t max_size = (std::numeric_limits< uintmax_t >::max)();
487 if (optional< string_type > max_size_param = params["MaxSize"])
488 max_size = param_cast_to_int< uintmax_t >("MaxSize", max_size_param.get());
489
490 // Min free space
491 uintmax_t space = 0;
492 if (optional< string_type > min_space_param = params["MinFreeSpace"])
493 space = param_cast_to_int< uintmax_t >("MinFreeSpace", min_space_param.get());
494
495 // Max number of files
496 uintmax_t max_files = (std::numeric_limits< uintmax_t >::max)();
497 if (optional< string_type > max_files_param = params["MaxFiles"])
498 max_files = param_cast_to_int< uintmax_t >("MaxFiles", max_files_param.get());
499
500 backend->set_file_collector(sinks::file::make_collector(
501 keywords::target = target_dir,
502 keywords::max_size = max_size,
503 keywords::min_free_space = space,
504 keywords::max_files = max_files));
505
506 // Scan for log files
507 if (optional< string_type > scan_param = params["ScanForFiles"])
508 {
509 string_type const& value = scan_param.get();
510 if (value == constants::scan_method_all())
511 backend->scan_for_files(sinks::file::scan_all);
512 else if (value == constants::scan_method_matching())
513 backend->scan_for_files(sinks::file::scan_matching);
514 else
515 {
516 BOOST_LOG_THROW_DESCR(invalid_value,
517 "File scan method \"" + boost::log::aux::to_narrow(value) + "\" is not supported");
518 }
519 }
520 }
521
522 return base_type::init_sink(backend, params);
523 }
524 };
525
526 #ifndef BOOST_LOG_WITHOUT_SYSLOG
527
528 //! Default syslog sink factory
529 template< typename CharT >
530 class default_syslog_sink_factory :
531 public basic_default_sink_factory< CharT >
532 {
533 public:
534 typedef basic_default_sink_factory< CharT > base_type;
535 typedef typename base_type::char_type char_type;
536 typedef typename base_type::string_type string_type;
537 typedef typename base_type::settings_section settings_section;
538 typedef typename base_type::constants constants;
539
540 public:
541 //! The function constructs a sink that writes log records to syslog
542 shared_ptr< sinks::sink > create_sink(settings_section const& params)
543 {
544 // Construct the backend
545 typedef sinks::syslog_backend backend_t;
546 shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
547
548 // For now we use only the default level mapping. Will add support for configuration later.
549 backend->set_severity_mapper(sinks::syslog::direct_severity_mapping< >(log::aux::default_attribute_names::severity()));
550
551 #if !defined(BOOST_LOG_NO_ASIO)
552 // Setup local and remote addresses
553 if (optional< string_type > local_address_param = params["LocalAddress"])
554 backend->set_local_address(param_cast_to_address("LocalAddress", local_address_param.get()));
555
556 if (optional< string_type > target_address_param = params["TargetAddress"])
557 backend->set_target_address(param_cast_to_address("TargetAddress", target_address_param.get()));
558 #endif // !defined(BOOST_LOG_NO_ASIO)
559
560 return base_type::init_sink(backend, params);
561 }
562 };
563
564 #endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
565
566 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
567
568 //! Default debugger sink factory
569 template< typename CharT >
570 class default_debugger_sink_factory :
571 public basic_default_sink_factory< CharT >
572 {
573 public:
574 typedef basic_default_sink_factory< CharT > base_type;
575 typedef typename base_type::char_type char_type;
576 typedef typename base_type::string_type string_type;
577 typedef typename base_type::settings_section settings_section;
578 typedef typename base_type::constants constants;
579
580 private:
581 struct impl;
582 friend struct impl;
583 struct impl
584 {
585 typedef shared_ptr< sinks::sink > result_type;
586
587 template< typename BackendCharT >
588 result_type operator() (settings_section const& params, type< BackendCharT >) const
589 {
590 // Construct the backend
591 typedef sinks::basic_debug_output_backend< BackendCharT > backend_t;
592 shared_ptr< backend_t > backend = boost::make_shared< backend_t >();
593
594 return base_type::init_sink(backend, params);
595 }
596 };
597
598 public:
599 //! The function constructs a sink that writes log records to the debugger
600 shared_ptr< sinks::sink > create_sink(settings_section const& params)
601 {
602 return base_type::select_backend_character_type(params, impl());
603 }
604 };
605
606 #endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)
607
608 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
609
610 //! Default simple event log sink factory
611 template< typename CharT >
612 class default_simple_event_log_sink_factory :
613 public basic_default_sink_factory< CharT >
614 {
615 public:
616 typedef basic_default_sink_factory< CharT > base_type;
617 typedef typename base_type::char_type char_type;
618 typedef typename base_type::string_type string_type;
619 typedef typename base_type::settings_section settings_section;
620 typedef typename base_type::constants constants;
621
622 private:
623 struct impl;
624 friend struct impl;
625 struct impl
626 {
627 typedef shared_ptr< sinks::sink > result_type;
628
629 template< typename BackendCharT >
630 result_type operator() (settings_section const& params, type< BackendCharT >) const
631 {
632 typedef sinks::basic_simple_event_log_backend< BackendCharT > backend_t;
633 typedef typename backend_t::string_type backend_string_type;
634
635 // Determine the log name
636 backend_string_type log_name;
637 if (optional< string_type > log_name_param = params["LogName"])
638 log::aux::code_convert(log_name_param.get(), log_name);
639 else
640 log_name = backend_t::get_default_log_name();
641
642 // Determine the log source name
643 backend_string_type source_name;
644 if (optional< string_type > log_source_param = params["LogSource"])
645 log::aux::code_convert(log_source_param.get(), source_name);
646 else
647 source_name = backend_t::get_default_source_name();
648
649 // Determine the registration mode
650 sinks::event_log::registration_mode reg_mode = sinks::event_log::on_demand;
651 if (optional< string_type > registration_param = params["Registration"])
652 {
653 string_type const& value = registration_param.get();
654 if (value == constants::registration_never())
655 reg_mode = sinks::event_log::never;
656 else if (value == constants::registration_on_demand())
657 reg_mode = sinks::event_log::on_demand;
658 else if (value == constants::registration_forced())
659 reg_mode = sinks::event_log::forced;
660 else
661 {
662 BOOST_LOG_THROW_DESCR(invalid_value,
663 "The registration mode \"" + log::aux::to_narrow(value) + "\" is not supported");
664 }
665 }
666
667 // Construct the backend
668 shared_ptr< backend_t > backend(boost::make_shared< backend_t >((
669 keywords::log_name = log_name,
670 keywords::log_source = source_name,
671 keywords::registration = reg_mode)));
672
673 // For now we use only the default event type mapping. Will add support for configuration later.
674 backend->set_event_type_mapper(sinks::event_log::direct_event_type_mapping< >(log::aux::default_attribute_names::severity()));
675
676 return base_type::init_sink(backend, params);
677 }
678 };
679
680 public:
681 //! The function constructs a sink that writes log records to the Windows NT Event Log
682 shared_ptr< sinks::sink > create_sink(settings_section const& params)
683 {
684 return base_type::select_backend_character_type(params, impl());
685 }
686 };
687
688 #endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)
689
690
691 //! The supported sinks repository
692 template< typename CharT >
693 struct sinks_repository :
694 public log::aux::lazy_singleton< sinks_repository< CharT > >
695 {
696 typedef log::aux::lazy_singleton< sinks_repository< CharT > > base_type;
697
698 #if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS)
699 friend class log::aux::lazy_singleton< sinks_repository< CharT > >;
700 #else
701 friend class base_type;
702 #endif
703
704 typedef CharT char_type;
705 typedef std::basic_string< char_type > string_type;
706 typedef basic_settings_section< char_type > settings_section;
707 typedef boost::log::aux::char_constants< char_type > constants;
708 typedef boost::shared_ptr< sink_factory< char_type > > sink_factory_ptr;
709 typedef std::map< std::string, sink_factory_ptr > sink_factories;
710
711 #if !defined(BOOST_LOG_NO_THREADS)
712 //! Synchronization mutex
713 log::aux::light_rw_mutex m_Mutex;
714 #endif
715 //! Map of the sink factories
716 sink_factories m_Factories;
717
718 //! The function constructs a sink from the settings
719 shared_ptr< sinks::sink > construct_sink_from_settings(settings_section const& params)
720 {
721 typedef typename settings_section::const_reference param_const_reference;
722 if (param_const_reference dest_node = params["Destination"])
723 {
724 std::string dest = log::aux::to_narrow(dest_node.get().get());
725
726 BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard< log::aux::light_rw_mutex > lock(m_Mutex);)
727 typename sink_factories::const_iterator it = m_Factories.find(dest);
728 if (it != m_Factories.end())
729 {
730 return it->second->create_sink(params);
731 }
732 else
733 {
734 BOOST_LOG_THROW_DESCR(invalid_value, "The sink destination is not supported: " + dest);
735 }
736 }
737 else
738 {
739 BOOST_LOG_THROW_DESCR(missing_value, "The sink destination is not set");
740 }
741 }
742
743 static void init_instance()
744 {
745 sinks_repository& instance = base_type::get_instance();
746 instance.m_Factories["TextFile"] = boost::make_shared< default_text_file_sink_factory< char_type > >();
747 instance.m_Factories["Console"] = boost::make_shared< default_console_sink_factory< char_type > >();
748 #ifndef BOOST_LOG_WITHOUT_SYSLOG
749 instance.m_Factories["Syslog"] = boost::make_shared< default_syslog_sink_factory< char_type > >();
750 #endif
751 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
752 instance.m_Factories["Debugger"] = boost::make_shared< default_debugger_sink_factory< char_type > >();
753 #endif
754 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
755 instance.m_Factories["SimpleEventLog"] = boost::make_shared< default_simple_event_log_sink_factory< char_type > >();
756 #endif
757 }
758
759 private:
760 sinks_repository() {}
761 };
762
763 //! The function applies the settings to the logging core
764 template< typename CharT >
765 void apply_core_settings(basic_settings_section< CharT > const& params)
766 {
767 typedef CharT char_type;
768 typedef std::basic_string< char_type > string_type;
769
770 core_ptr core = boost::log::core::get();
771
772 // Filter
773 if (optional< string_type > filter_param = params["Filter"])
774 core->set_filter(parse_filter(filter_param.get()));
775 else
776 core->reset_filter();
777
778 // DisableLogging
779 if (optional< string_type > disable_logging_param = params["DisableLogging"])
780 core->set_logging_enabled(!param_cast_to_bool("DisableLogging", disable_logging_param.get()));
781 else
782 core->set_logging_enabled(true);
783 }
784
785 } // namespace
786
787
788 //! The function initializes the logging library from a settings container
789 template< typename CharT >
790 BOOST_LOG_SETUP_API void init_from_settings(basic_settings_section< CharT > const& setts)
791 {
792 typedef basic_settings_section< CharT > section;
793 typedef typename section::char_type char_type;
794 typedef sinks_repository< char_type > sinks_repo_t;
795
796 // Apply core settings
797 if (section core_params = setts["Core"])
798 apply_core_settings(core_params);
799
800 // Construct and initialize sinks
801 if (section sink_params = setts["Sinks"])
802 {
803 sinks_repo_t& sinks_repo = sinks_repo_t::get();
804 std::vector< shared_ptr< sinks::sink > > new_sinks;
805
806 for (typename section::const_iterator it = sink_params.begin(), end = sink_params.end(); it != end; ++it)
807 {
808 section sink_params = *it;
809
810 // Ignore empty sections as they are most likely individual parameters (which should not be here anyway)
811 if (!sink_params.empty())
812 {
813 new_sinks.push_back(sinks_repo.construct_sink_from_settings(sink_params));
814 }
815 }
816
817 std::for_each(new_sinks.begin(), new_sinks.end(), boost::bind(&core::add_sink, core::get(), _1));
818 }
819 }
820
821
822 //! The function registers a factory for a sink
823 template< typename CharT >
824 BOOST_LOG_SETUP_API void register_sink_factory(const char* sink_name, shared_ptr< sink_factory< CharT > > const& factory)
825 {
826 sinks_repository< CharT >& repo = sinks_repository< CharT >::get();
827 BOOST_LOG_EXPR_IF_MT(lock_guard< log::aux::light_rw_mutex > lock(repo.m_Mutex);)
828 repo.m_Factories[sink_name] = factory;
829 }
830
831 #ifdef BOOST_LOG_USE_CHAR
832 template BOOST_LOG_SETUP_API void register_sink_factory< char >(const char* sink_name, shared_ptr< sink_factory< char > > const& factory);
833 template BOOST_LOG_SETUP_API void init_from_settings< char >(basic_settings_section< char > const& setts);
834 #endif
835
836 #ifdef BOOST_LOG_USE_WCHAR_T
837 template BOOST_LOG_SETUP_API void register_sink_factory< wchar_t >(const char* sink_name, shared_ptr< sink_factory< wchar_t > > const& factory);
838 template BOOST_LOG_SETUP_API void init_from_settings< wchar_t >(basic_settings_section< wchar_t > const& setts);
839 #endif
840
841 BOOST_LOG_CLOSE_NAMESPACE // namespace log
842
843 } // namespace boost
844
845 #include <boost/log/detail/footer.hpp>
846
847 #endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS