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)
8 * \file init_from_settings.cpp
9 * \author Andrey Semashev
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.
16 #ifndef BOOST_LOG_WITHOUT_SETTINGS_PARSERS
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"
26 #include <boost/log/detail/setup_config.hpp>
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>
67 #if !defined(BOOST_LOG_NO_THREADS)
68 #include <boost/log/detail/locks.hpp>
69 #include <boost/log/detail/light_rw_mutex.hpp>
71 #include "parser_utils.hpp"
72 #include "spirit_encoding.hpp"
73 #include <boost/log/detail/header.hpp>
75 namespace qi
= boost::spirit::qi
;
79 BOOST_LOG_OPEN_NAMESPACE
81 BOOST_LOG_ANONYMOUS_NAMESPACE
{
83 //! Throws an exception when a parameter value is not valid
84 BOOST_LOG_NORETURN
void throw_invalid_value(const char* param_name
)
86 std::string descr
= std::string("Invalid parameter \"")
89 BOOST_LOG_THROW_DESCR(invalid_value
, descr
);
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
)
97 typedef typename
mpl::if_
<
99 qi::extract_uint
< IntT
, 10, 1, -1 >,
100 qi::extract_int
< IntT
, 10, 1, -1 >
102 const CharT
* begin
= value
.c_str(), *end
= begin
+ value
.size();
103 if (extract::call(begin
, end
, res
) && begin
== end
)
106 throw_invalid_value(param_name
);
109 //! Case-insensitive character comparison predicate
110 struct is_case_insensitive_equal
112 typedef bool result_type
;
114 template< typename CharT
>
115 result_type
operator() (CharT left
, CharT right
) const BOOST_NOEXCEPT
117 typedef typename
boost::log::aux::encoding
< CharT
>::type encoding
;
118 return encoding::tolower(left
) == encoding::tolower(right
);
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
)
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
;
130 const char_type
* begin
= value
.c_str(), *end
= begin
+ value
.size();
131 std::size_t len
= end
- begin
;
133 literal_type keyword
= constants::true_keyword();
134 if (keyword
.size() == len
&& std::equal(begin
, end
, keyword
.c_str(), is_case_insensitive_equal()))
140 keyword
= constants::false_keyword();
141 if (keyword
.size() == len
&& std::equal(begin
, end
, keyword
.c_str(), is_case_insensitive_equal()))
147 return param_cast_to_int
< unsigned int >(param_name
, value
) != 0;
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
)
157 return log::aux::to_narrow(value
);
159 #endif // !defined(BOOST_LOG_NO_ASIO)
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
)
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
));
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
)
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
;
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();
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
);
187 const char_type
* p
= begin
+ 1;
188 if (encoding::isalpha(*begin
))
190 // This must be a weekday
191 while (encoding::isalpha(*p
))
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
;
210 throw_invalid_value(param_name
);
214 // This may be either a month day or an hour
215 while (encoding::isdigit(*p
))
218 if (encoding::isspace(*p
))
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
);
228 else if (*p
== colon
)
230 // This is an hour, reset the pointer
234 throw_invalid_value(param_name
);
238 while (encoding::isspace(*p
))
242 if (!time_component_extract::call(p
, end
, hour
) || *p
!= colon
)
243 throw_invalid_value(param_name
);
247 if (!time_component_extract::call(p
, end
, minute
) || *p
!= colon
)
248 throw_invalid_value(param_name
);
252 if (!time_component_extract::call(p
, end
, second
) || p
!= end
)
253 throw_invalid_value(param_name
);
255 // Construct the predicate
257 return sinks::file::rotation_at_time_point(weekday
.get(), hour
, minute
, second
);
259 return sinks::file::rotation_at_time_point(gregorian::greg_day(day
.get()), hour
, minute
, second
);
261 return sinks::file::rotation_at_time_point(hour
, minute
, second
);
264 //! Base class for default sink factories
265 template< typename CharT
>
266 class basic_default_sink_factory
:
267 public sink_factory
< CharT
>
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
;
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
)
281 #if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
282 if (optional
< string_type
> wide_param
= params
["Wide"])
284 if (param_cast_to_bool("Wide", wide_param
.get()))
285 return initializer(params
, type
< wchar_t >());
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 >());
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
)
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
;
308 if (optional
< string_type
> filter_param
= params
["Filter"])
310 filt
= parse_filter(filter_param
.get());
313 shared_ptr
< sinks::basic_sink_frontend
> p
;
315 #if !defined(BOOST_LOG_NO_THREADS)
316 // Asynchronous. TODO: make it more flexible.
318 if (optional
< string_type
> async_param
= params
["Asynchronous"])
320 async
= param_cast_to_bool("Asynchronous", async_param
.get());
323 // Construct the frontend, considering Asynchronous parameter
326 p
= init_formatter(boost::make_shared
< sinks::synchronous_sink
< backend_t
> >(backend
), params
, is_formatting_t());
330 p
= init_formatter(boost::make_shared
< sinks::asynchronous_sink
< backend_t
> >(backend
), params
, is_formatting_t());
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());
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());
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_
)
353 if (optional
< string_type
> format_param
= params
["Format"])
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
));
362 template< typename SinkT
>
363 static shared_ptr
< SinkT
> init_formatter(shared_ptr
< SinkT
> const& sink
, settings_section
const& params
, mpl::false_
)
369 //! Default console sink factory
370 template< typename CharT
>
371 class default_console_sink_factory
:
372 public basic_default_sink_factory
< CharT
>
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
;
386 typedef shared_ptr
< sinks::sink
> result_type
;
388 template< typename BackendCharT
>
389 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
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()));
398 if (optional
< string_type
> auto_flush_param
= params
["AutoFlush"])
400 backend
->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param
.get()));
403 return base_type::init_sink(backend
, params
);
408 //! The function constructs a sink that writes log records to the console
409 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
411 return base_type::select_backend_character_type(params
, impl());
415 //! Default text file sink factory
416 template< typename CharT
>
417 class default_text_file_sink_factory
:
418 public basic_default_sink_factory
< CharT
>
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
;
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
)
431 typedef sinks::text_file_backend backend_t
;
432 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
435 if (optional
< string_type
> file_name_param
= params
["FileName"])
437 backend
->set_file_name_pattern(filesystem::path(file_name_param
.get()));
440 BOOST_LOG_THROW_DESCR(missing_value
, "File name is not specified");
442 // File rotation size
443 if (optional
< string_type
> rotation_size_param
= params
["RotationSize"])
445 backend
->set_rotation_size(param_cast_to_int
< uintmax_t >("RotationSize", rotation_size_param
.get()));
448 // File rotation interval
449 if (optional
< string_type
> rotation_interval_param
= params
["RotationInterval"])
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()))));
454 else if (optional
< string_type
> rotation_time_point_param
= params
["RotationTimePoint"])
456 // File rotation time point
457 backend
->set_time_based_rotation(param_cast_to_rotation_time_point("RotationTimePoint", rotation_time_point_param
.get()));
461 if (optional
< string_type
> auto_flush_param
= params
["AutoFlush"])
463 backend
->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param
.get()));
467 if (optional
< string_type
> append_param
= params
["Append"])
469 if (param_cast_to_bool("Append", append_param
.get()))
470 backend
->set_open_mode(std::ios_base::out
| std::ios_base::app
);
473 // File collector parameters
475 if (optional
< string_type
> target_param
= params
["Target"])
477 filesystem::path
target_dir(target_param
.get());
480 uintmax_t max_size
= (std::numeric_limits
< uintmax_t >::max
)();
481 if (optional
< string_type
> max_size_param
= params
["MaxSize"])
482 max_size
= param_cast_to_int
< uintmax_t >("MaxSize", max_size_param
.get());
486 if (optional
< string_type
> min_space_param
= params
["MinFreeSpace"])
487 space
= param_cast_to_int
< uintmax_t >("MinFreeSpace", min_space_param
.get());
489 // Max number of files
490 uintmax_t max_files
= (std::numeric_limits
< uintmax_t >::max
)();
491 if (optional
< string_type
> max_files_param
= params
["MaxFiles"])
492 max_files
= param_cast_to_int
< uintmax_t >("MaxFiles", max_files_param
.get());
494 backend
->set_file_collector(sinks::file::make_collector(
495 keywords::target
= target_dir
,
496 keywords::max_size
= max_size
,
497 keywords::min_free_space
= space
,
498 keywords::max_files
= max_files
));
500 // Scan for log files
501 if (optional
< string_type
> scan_param
= params
["ScanForFiles"])
503 string_type
const& value
= scan_param
.get();
504 if (value
== constants::scan_method_all())
505 backend
->scan_for_files(sinks::file::scan_all
);
506 else if (value
== constants::scan_method_matching())
507 backend
->scan_for_files(sinks::file::scan_matching
);
510 BOOST_LOG_THROW_DESCR(invalid_value
,
511 "File scan method \"" + boost::log::aux::to_narrow(value
) + "\" is not supported");
516 return base_type::init_sink(backend
, params
);
520 #ifndef BOOST_LOG_WITHOUT_SYSLOG
522 //! Default syslog sink factory
523 template< typename CharT
>
524 class default_syslog_sink_factory
:
525 public basic_default_sink_factory
< CharT
>
528 typedef basic_default_sink_factory
< CharT
> base_type
;
529 typedef typename
base_type::char_type char_type
;
530 typedef typename
base_type::string_type string_type
;
531 typedef typename
base_type::settings_section settings_section
;
532 typedef typename
base_type::constants constants
;
535 //! The function constructs a sink that writes log records to syslog
536 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
538 // Construct the backend
539 typedef sinks::syslog_backend backend_t
;
540 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
542 // For now we use only the default level mapping. Will add support for configuration later.
543 backend
->set_severity_mapper(sinks::syslog::direct_severity_mapping
< >(log::aux::default_attribute_names::severity()));
545 #if !defined(BOOST_LOG_NO_ASIO)
546 // Setup local and remote addresses
547 if (optional
< string_type
> local_address_param
= params
["LocalAddress"])
548 backend
->set_local_address(param_cast_to_address("LocalAddress", local_address_param
.get()));
550 if (optional
< string_type
> target_address_param
= params
["TargetAddress"])
551 backend
->set_target_address(param_cast_to_address("TargetAddress", target_address_param
.get()));
552 #endif // !defined(BOOST_LOG_NO_ASIO)
554 return base_type::init_sink(backend
, params
);
558 #endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
560 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
562 //! Default debugger sink factory
563 template< typename CharT
>
564 class default_debugger_sink_factory
:
565 public basic_default_sink_factory
< CharT
>
568 typedef basic_default_sink_factory
< CharT
> base_type
;
569 typedef typename
base_type::char_type char_type
;
570 typedef typename
base_type::string_type string_type
;
571 typedef typename
base_type::settings_section settings_section
;
572 typedef typename
base_type::constants constants
;
579 typedef shared_ptr
< sinks::sink
> result_type
;
581 template< typename BackendCharT
>
582 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
584 // Construct the backend
585 typedef sinks::basic_debug_output_backend
< BackendCharT
> backend_t
;
586 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
588 return base_type::init_sink(backend
, params
);
593 //! The function constructs a sink that writes log records to the debugger
594 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
596 return base_type::select_backend_character_type(params
, impl());
600 #endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)
602 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
604 //! Default simple event log sink factory
605 template< typename CharT
>
606 class default_simple_event_log_sink_factory
:
607 public basic_default_sink_factory
< CharT
>
610 typedef basic_default_sink_factory
< CharT
> base_type
;
611 typedef typename
base_type::char_type char_type
;
612 typedef typename
base_type::string_type string_type
;
613 typedef typename
base_type::settings_section settings_section
;
614 typedef typename
base_type::constants constants
;
621 typedef shared_ptr
< sinks::sink
> result_type
;
623 template< typename BackendCharT
>
624 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
626 typedef sinks::basic_simple_event_log_backend
< BackendCharT
> backend_t
;
627 typedef typename
backend_t::string_type backend_string_type
;
629 // Determine the log name
630 backend_string_type log_name
;
631 if (optional
< string_type
> log_name_param
= params
["LogName"])
632 log::aux::code_convert(log_name_param
.get(), log_name
);
634 log_name
= backend_t::get_default_log_name();
636 // Determine the log source name
637 backend_string_type source_name
;
638 if (optional
< string_type
> log_source_param
= params
["LogSource"])
639 log::aux::code_convert(log_source_param
.get(), source_name
);
641 source_name
= backend_t::get_default_source_name();
643 // Determine the registration mode
644 sinks::event_log::registration_mode reg_mode
= sinks::event_log::on_demand
;
645 if (optional
< string_type
> registration_param
= params
["Registration"])
647 string_type
const& value
= registration_param
.get();
648 if (value
== constants::registration_never())
649 reg_mode
= sinks::event_log::never
;
650 else if (value
== constants::registration_on_demand())
651 reg_mode
= sinks::event_log::on_demand
;
652 else if (value
== constants::registration_forced())
653 reg_mode
= sinks::event_log::forced
;
656 BOOST_LOG_THROW_DESCR(invalid_value
,
657 "The registration mode \"" + log::aux::to_narrow(value
) + "\" is not supported");
661 // Construct the backend
662 shared_ptr
< backend_t
> backend(boost::make_shared
< backend_t
>((
663 keywords::log_name
= log_name
,
664 keywords::log_source
= source_name
,
665 keywords::registration
= reg_mode
)));
667 // For now we use only the default event type mapping. Will add support for configuration later.
668 backend
->set_event_type_mapper(sinks::event_log::direct_event_type_mapping
< >(log::aux::default_attribute_names::severity()));
670 return base_type::init_sink(backend
, params
);
675 //! The function constructs a sink that writes log records to the Windows NT Event Log
676 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
678 return base_type::select_backend_character_type(params
, impl());
682 #endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)
685 //! The supported sinks repository
686 template< typename CharT
>
687 struct sinks_repository
:
688 public log::aux::lazy_singleton
< sinks_repository
< CharT
> >
690 typedef log::aux::lazy_singleton
< sinks_repository
< CharT
> > base_type
;
692 #if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS)
693 friend class log::aux::lazy_singleton
< sinks_repository
< CharT
> >;
695 friend class base_type
;
698 typedef CharT char_type
;
699 typedef std::basic_string
< char_type
> string_type
;
700 typedef basic_settings_section
< char_type
> settings_section
;
701 typedef boost::log::aux::char_constants
< char_type
> constants
;
702 typedef boost::shared_ptr
< sink_factory
< char_type
> > sink_factory_ptr
;
703 typedef std::map
< std::string
, sink_factory_ptr
> sink_factories
;
705 #if !defined(BOOST_LOG_NO_THREADS)
706 //! Synchronization mutex
707 log::aux::light_rw_mutex m_Mutex
;
709 //! Map of the sink factories
710 sink_factories m_Factories
;
712 //! The function constructs a sink from the settings
713 shared_ptr
< sinks::sink
> construct_sink_from_settings(settings_section
const& params
)
715 typedef typename
settings_section::const_reference param_const_reference
;
716 if (param_const_reference dest_node
= params
["Destination"])
718 std::string dest
= log::aux::to_narrow(dest_node
.get().get());
720 BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard
< log::aux::light_rw_mutex
> lock(m_Mutex
);)
721 typename
sink_factories::const_iterator it
= m_Factories
.find(dest
);
722 if (it
!= m_Factories
.end())
724 return it
->second
->create_sink(params
);
728 BOOST_LOG_THROW_DESCR(invalid_value
, "The sink destination is not supported: " + dest
);
733 BOOST_LOG_THROW_DESCR(missing_value
, "The sink destination is not set");
737 static void init_instance()
739 sinks_repository
& instance
= base_type::get_instance();
740 instance
.m_Factories
["TextFile"] = boost::make_shared
< default_text_file_sink_factory
< char_type
> >();
741 instance
.m_Factories
["Console"] = boost::make_shared
< default_console_sink_factory
< char_type
> >();
742 #ifndef BOOST_LOG_WITHOUT_SYSLOG
743 instance
.m_Factories
["Syslog"] = boost::make_shared
< default_syslog_sink_factory
< char_type
> >();
745 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
746 instance
.m_Factories
["Debugger"] = boost::make_shared
< default_debugger_sink_factory
< char_type
> >();
748 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
749 instance
.m_Factories
["SimpleEventLog"] = boost::make_shared
< default_simple_event_log_sink_factory
< char_type
> >();
754 sinks_repository() {}
757 //! The function applies the settings to the logging core
758 template< typename CharT
>
759 void apply_core_settings(basic_settings_section
< CharT
> const& params
)
761 typedef CharT char_type
;
762 typedef std::basic_string
< char_type
> string_type
;
764 core_ptr core
= boost::log::core::get();
767 if (optional
< string_type
> filter_param
= params
["Filter"])
768 core
->set_filter(parse_filter(filter_param
.get()));
770 core
->reset_filter();
773 if (optional
< string_type
> disable_logging_param
= params
["DisableLogging"])
774 core
->set_logging_enabled(!param_cast_to_bool("DisableLogging", disable_logging_param
.get()));
776 core
->set_logging_enabled(true);
782 //! The function initializes the logging library from a settings container
783 template< typename CharT
>
784 BOOST_LOG_SETUP_API
void init_from_settings(basic_settings_section
< CharT
> const& setts
)
786 typedef basic_settings_section
< CharT
> section
;
787 typedef typename
section::char_type char_type
;
788 typedef sinks_repository
< char_type
> sinks_repo_t
;
790 // Apply core settings
791 if (section core_params
= setts
["Core"])
792 apply_core_settings(core_params
);
794 // Construct and initialize sinks
795 if (section sink_params
= setts
["Sinks"])
797 sinks_repo_t
& sinks_repo
= sinks_repo_t::get();
798 std::vector
< shared_ptr
< sinks::sink
> > new_sinks
;
800 for (typename
section::const_iterator it
= sink_params
.begin(), end
= sink_params
.end(); it
!= end
; ++it
)
802 section sink_params
= *it
;
804 // Ignore empty sections as they are most likely individual parameters (which should not be here anyway)
805 if (!sink_params
.empty())
807 new_sinks
.push_back(sinks_repo
.construct_sink_from_settings(sink_params
));
811 std::for_each(new_sinks
.begin(), new_sinks
.end(), boost::bind(&core::add_sink
, core::get(), _1
));
816 //! The function registers a factory for a sink
817 template< typename CharT
>
818 BOOST_LOG_SETUP_API
void register_sink_factory(const char* sink_name
, shared_ptr
< sink_factory
< CharT
> > const& factory
)
820 sinks_repository
< CharT
>& repo
= sinks_repository
< CharT
>::get();
821 BOOST_LOG_EXPR_IF_MT(lock_guard
< log::aux::light_rw_mutex
> lock(repo
.m_Mutex
);)
822 repo
.m_Factories
[sink_name
] = factory
;
825 #ifdef BOOST_LOG_USE_CHAR
826 template BOOST_LOG_SETUP_API
void register_sink_factory
< char >(const char* sink_name
, shared_ptr
< sink_factory
< char > > const& factory
);
827 template BOOST_LOG_SETUP_API
void init_from_settings
< char >(basic_settings_section
< char > const& setts
);
830 #ifdef BOOST_LOG_USE_WCHAR_T
831 template BOOST_LOG_SETUP_API
void register_sink_factory
< wchar_t >(const char* sink_name
, shared_ptr
< sink_factory
< wchar_t > > const& factory
);
832 template BOOST_LOG_SETUP_API
void init_from_settings
< wchar_t >(basic_settings_section
< wchar_t > const& setts
);
835 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
839 #include <boost/log/detail/footer.hpp>
841 #endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS