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
> enable_final_rotation_param
= params
["EnableFinalRotation"])
463 backend
->enable_final_rotation(param_cast_to_bool("EnableFinalRotation", enable_final_rotation_param
.get()));
467 if (optional
< string_type
> auto_flush_param
= params
["AutoFlush"])
469 backend
->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param
.get()));
473 if (optional
< string_type
> append_param
= params
["Append"])
475 if (param_cast_to_bool("Append", append_param
.get()))
476 backend
->set_open_mode(std::ios_base::out
| std::ios_base::app
);
479 // File collector parameters
481 if (optional
< string_type
> target_param
= params
["Target"])
483 filesystem::path
target_dir(target_param
.get());
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());
492 if (optional
< string_type
> min_space_param
= params
["MinFreeSpace"])
493 space
= param_cast_to_int
< uintmax_t >("MinFreeSpace", min_space_param
.get());
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());
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
));
506 // Scan for log files
507 if (optional
< string_type
> scan_param
= params
["ScanForFiles"])
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
);
516 BOOST_LOG_THROW_DESCR(invalid_value
,
517 "File scan method \"" + boost::log::aux::to_narrow(value
) + "\" is not supported");
522 return base_type::init_sink(backend
, params
);
526 #ifndef BOOST_LOG_WITHOUT_SYSLOG
528 //! Default syslog sink factory
529 template< typename CharT
>
530 class default_syslog_sink_factory
:
531 public basic_default_sink_factory
< CharT
>
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
;
541 //! The function constructs a sink that writes log records to syslog
542 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
544 // Construct the backend
545 typedef sinks::syslog_backend backend_t
;
546 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
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()));
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()));
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)
560 return base_type::init_sink(backend
, params
);
564 #endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
566 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
568 //! Default debugger sink factory
569 template< typename CharT
>
570 class default_debugger_sink_factory
:
571 public basic_default_sink_factory
< CharT
>
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
;
585 typedef shared_ptr
< sinks::sink
> result_type
;
587 template< typename BackendCharT
>
588 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
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
>();
594 return base_type::init_sink(backend
, params
);
599 //! The function constructs a sink that writes log records to the debugger
600 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
602 return base_type::select_backend_character_type(params
, impl());
606 #endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)
608 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
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
>
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
;
627 typedef shared_ptr
< sinks::sink
> result_type
;
629 template< typename BackendCharT
>
630 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
632 typedef sinks::basic_simple_event_log_backend
< BackendCharT
> backend_t
;
633 typedef typename
backend_t::string_type backend_string_type
;
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
);
640 log_name
= backend_t::get_default_log_name();
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
);
647 source_name
= backend_t::get_default_source_name();
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"])
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
;
662 BOOST_LOG_THROW_DESCR(invalid_value
,
663 "The registration mode \"" + log::aux::to_narrow(value
) + "\" is not supported");
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
)));
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()));
676 return base_type::init_sink(backend
, params
);
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
)
684 return base_type::select_backend_character_type(params
, impl());
688 #endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)
691 //! The supported sinks repository
692 template< typename CharT
>
693 struct sinks_repository
:
694 public log::aux::lazy_singleton
< sinks_repository
< CharT
> >
696 typedef log::aux::lazy_singleton
< sinks_repository
< CharT
> > base_type
;
698 #if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS)
699 friend class log::aux::lazy_singleton
< sinks_repository
< CharT
> >;
701 friend class base_type
;
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
;
711 #if !defined(BOOST_LOG_NO_THREADS)
712 //! Synchronization mutex
713 log::aux::light_rw_mutex m_Mutex
;
715 //! Map of the sink factories
716 sink_factories m_Factories
;
718 //! The function constructs a sink from the settings
719 shared_ptr
< sinks::sink
> construct_sink_from_settings(settings_section
const& params
)
721 typedef typename
settings_section::const_reference param_const_reference
;
722 if (param_const_reference dest_node
= params
["Destination"])
724 std::string dest
= log::aux::to_narrow(dest_node
.get().get());
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())
730 return it
->second
->create_sink(params
);
734 BOOST_LOG_THROW_DESCR(invalid_value
, "The sink destination is not supported: " + dest
);
739 BOOST_LOG_THROW_DESCR(missing_value
, "The sink destination is not set");
743 static void init_instance()
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
> >();
751 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
752 instance
.m_Factories
["Debugger"] = boost::make_shared
< default_debugger_sink_factory
< char_type
> >();
754 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
755 instance
.m_Factories
["SimpleEventLog"] = boost::make_shared
< default_simple_event_log_sink_factory
< char_type
> >();
760 sinks_repository() {}
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
)
767 typedef CharT char_type
;
768 typedef std::basic_string
< char_type
> string_type
;
770 core_ptr core
= boost::log::core::get();
773 if (optional
< string_type
> filter_param
= params
["Filter"])
774 core
->set_filter(parse_filter(filter_param
.get()));
776 core
->reset_filter();
779 if (optional
< string_type
> disable_logging_param
= params
["DisableLogging"])
780 core
->set_logging_enabled(!param_cast_to_bool("DisableLogging", disable_logging_param
.get()));
782 core
->set_logging_enabled(true);
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
)
792 typedef basic_settings_section
< CharT
> section
;
793 typedef typename
section::char_type char_type
;
794 typedef sinks_repository
< char_type
> sinks_repo_t
;
796 // Apply core settings
797 if (section core_params
= setts
["Core"])
798 apply_core_settings(core_params
);
800 // Construct and initialize sinks
801 if (section sink_params
= setts
["Sinks"])
803 sinks_repo_t
& sinks_repo
= sinks_repo_t::get();
804 std::vector
< shared_ptr
< sinks::sink
> > new_sinks
;
806 for (typename
section::const_iterator it
= sink_params
.begin(), end
= sink_params
.end(); it
!= end
; ++it
)
808 section sink_params
= *it
;
810 // Ignore empty sections as they are most likely individual parameters (which should not be here anyway)
811 if (!sink_params
.empty())
813 new_sinks
.push_back(sinks_repo
.construct_sink_from_settings(sink_params
));
817 std::for_each(new_sinks
.begin(), new_sinks
.end(), boost::bind(&core::add_sink
, core::get(), _1
));
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
)
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
;
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
);
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
);
841 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
845 #include <boost/log/detail/footer.hpp>
847 #endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS