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/limits.hpp>
39 #include <boost/cstdint.hpp>
40 #include <boost/bind/bind.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/type_traits/conditional.hpp>
48 #include <boost/type_traits/is_unsigned.hpp>
49 #include <boost/type_traits/integral_constant.hpp>
50 #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
51 #include <boost/log/detail/code_conversion.hpp>
52 #include <boost/log/detail/singleton.hpp>
53 #include <boost/log/detail/default_attribute_names.hpp>
54 #include <boost/log/core.hpp>
55 #include <boost/log/sinks.hpp>
56 #include <boost/log/exceptions.hpp>
57 #include <boost/log/sinks/auto_newline_mode.hpp>
58 #include <boost/log/sinks/frontend_requirements.hpp>
59 #include <boost/log/expressions/filter.hpp>
60 #include <boost/log/expressions/formatter.hpp>
61 #include <boost/log/utility/string_literal.hpp>
62 #include <boost/log/utility/functional/nop.hpp>
63 #include <boost/log/utility/setup/from_settings.hpp>
64 #include <boost/log/utility/setup/filter_parser.hpp>
65 #include <boost/log/utility/setup/formatter_parser.hpp>
66 #if !defined(BOOST_LOG_NO_ASIO)
67 #include <boost/asio/ip/address.hpp>
69 #if !defined(BOOST_LOG_NO_THREADS)
70 #include <boost/log/detail/locks.hpp>
71 #include <boost/log/detail/light_rw_mutex.hpp>
73 #include "parser_utils.hpp"
74 #include "spirit_encoding.hpp"
75 #include <boost/log/detail/header.hpp>
77 namespace qi
= boost::spirit::qi
;
81 BOOST_LOG_OPEN_NAMESPACE
83 BOOST_LOG_ANONYMOUS_NAMESPACE
{
85 //! Throws an exception when a parameter value is not valid
86 BOOST_LOG_NORETURN
void throw_invalid_value(const char* param_name
)
88 std::string descr
= std::string("Invalid parameter \"")
91 BOOST_LOG_THROW_DESCR(invalid_value
, descr
);
94 //! Extracts an integral value from parameter value
95 template< typename IntT
, typename CharT
>
96 inline IntT
param_cast_to_int(const char* param_name
, std::basic_string
< CharT
> const& value
)
99 typedef typename conditional
<
100 is_unsigned
< IntT
>::value
,
101 qi::extract_uint
< IntT
, 10, 1, -1 >,
102 qi::extract_int
< IntT
, 10, 1, -1 >
104 const CharT
* begin
= value
.c_str(), *end
= begin
+ value
.size();
105 if (extract::call(begin
, end
, res
) && begin
== end
)
108 throw_invalid_value(param_name
);
111 //! Case-insensitive character comparison predicate
112 struct is_case_insensitive_equal
114 typedef bool result_type
;
116 template< typename CharT
>
117 result_type
operator() (CharT left
, CharT right
) const BOOST_NOEXCEPT
119 typedef typename
boost::log::aux::encoding
< CharT
>::type encoding
;
120 return encoding::tolower(left
) == encoding::tolower(right
);
124 //! Extracts a boolean value from parameter value
125 template< typename CharT
>
126 inline bool param_cast_to_bool(const char* param_name
, std::basic_string
< CharT
> const& value
)
128 typedef CharT char_type
;
129 typedef boost::log::aux::char_constants
< char_type
> constants
;
130 typedef boost::log::basic_string_literal
< char_type
> literal_type
;
132 const char_type
* begin
= value
.c_str(), *end
= begin
+ value
.size();
133 std::size_t len
= end
- begin
;
135 literal_type keyword
= constants::true_keyword();
136 if (keyword
.size() == len
&& std::equal(begin
, end
, keyword
.c_str(), is_case_insensitive_equal()))
142 keyword
= constants::false_keyword();
143 if (keyword
.size() == len
&& std::equal(begin
, end
, keyword
.c_str(), is_case_insensitive_equal()))
149 return param_cast_to_int
< unsigned int >(param_name
, value
) != 0;
154 //! Extracts an \c auto_newline_mode value from parameter value
155 template< typename CharT
>
156 inline sinks::auto_newline_mode
param_cast_to_auto_newline_mode(const char* param_name
, std::basic_string
< CharT
> const& value
)
158 typedef CharT char_type
;
159 typedef boost::log::aux::char_constants
< char_type
> constants
;
161 if (value
== constants::auto_newline_mode_disabled())
162 return sinks::disabled_auto_newline
;
163 else if (value
== constants::auto_newline_mode_always_insert())
164 return sinks::always_insert
;
165 else if (value
== constants::auto_newline_mode_insert_if_missing())
166 return sinks::insert_if_missing
;
169 BOOST_LOG_THROW_DESCR(invalid_value
,
170 "Auto newline mode \"" + boost::log::aux::to_narrow(value
) + "\" is not supported");
174 #if !defined(BOOST_LOG_NO_ASIO)
175 //! Extracts a network address from parameter value
176 template< typename CharT
>
177 inline std::string
param_cast_to_address(const char* param_name
, std::basic_string
< CharT
> const& value
)
179 return log::aux::to_narrow(value
);
181 #endif // !defined(BOOST_LOG_NO_ASIO)
183 template< typename CharT
>
184 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
)
186 return (len
== weekday
.size() && std::equal(weekday
.begin(), weekday
.end(), str
)) ||
187 (len
== short_weekday
.size() && std::equal(short_weekday
.begin(), short_weekday
.end(), str
));
190 //! The function extracts the file rotation time point predicate from the parameter
191 template< typename CharT
>
192 sinks::file::rotation_at_time_point
param_cast_to_rotation_time_point(const char* param_name
, std::basic_string
< CharT
> const& value
)
194 typedef CharT char_type
;
195 typedef boost::log::aux::char_constants
< char_type
> constants
;
196 typedef typename
boost::log::aux::encoding
< char_type
>::type encoding
;
197 typedef qi::extract_uint
< unsigned short, 10, 1, 2 > day_extract
;
198 typedef qi::extract_uint
< unsigned char, 10, 2, 2 > time_component_extract
;
200 const char_type colon
= static_cast< char_type
>(':');
201 optional
< date_time::weekdays
> weekday
;
202 optional
< unsigned short > day
;
203 unsigned char hour
= 0, minute
= 0, second
= 0;
204 const char_type
* begin
= value
.c_str(), *end
= begin
+ value
.size();
206 if (!encoding::isalnum(*begin
)) // begin is null-terminated, so we also check that the string is not empty here
207 throw_invalid_value(param_name
);
209 const char_type
* p
= begin
+ 1;
210 if (encoding::isalpha(*begin
))
212 // This must be a weekday
213 while (encoding::isalpha(*p
))
216 std::size_t len
= p
- begin
;
217 if (is_weekday(begin
, len
, constants::monday_keyword(), constants::short_monday_keyword()))
218 weekday
= date_time::Monday
;
219 else if (is_weekday(begin
, len
, constants::tuesday_keyword(), constants::short_tuesday_keyword()))
220 weekday
= date_time::Tuesday
;
221 else if (is_weekday(begin
, len
, constants::wednesday_keyword(), constants::short_wednesday_keyword()))
222 weekday
= date_time::Wednesday
;
223 else if (is_weekday(begin
, len
, constants::thursday_keyword(), constants::short_thursday_keyword()))
224 weekday
= date_time::Thursday
;
225 else if (is_weekday(begin
, len
, constants::friday_keyword(), constants::short_friday_keyword()))
226 weekday
= date_time::Friday
;
227 else if (is_weekday(begin
, len
, constants::saturday_keyword(), constants::short_saturday_keyword()))
228 weekday
= date_time::Saturday
;
229 else if (is_weekday(begin
, len
, constants::sunday_keyword(), constants::short_sunday_keyword()))
230 weekday
= date_time::Sunday
;
232 throw_invalid_value(param_name
);
236 // This may be either a month day or an hour
237 while (encoding::isdigit(*p
))
240 if (encoding::isspace(*p
))
242 // This is a month day
243 unsigned short mday
= 0;
244 const char_type
* b
= begin
;
245 if (!day_extract::call(b
, p
, mday
) || b
!= p
)
246 throw_invalid_value(param_name
);
250 else if (*p
== colon
)
252 // This is an hour, reset the pointer
256 throw_invalid_value(param_name
);
260 while (encoding::isspace(*p
))
264 if (!time_component_extract::call(p
, end
, hour
) || *p
!= colon
)
265 throw_invalid_value(param_name
);
269 if (!time_component_extract::call(p
, end
, minute
) || *p
!= colon
)
270 throw_invalid_value(param_name
);
274 if (!time_component_extract::call(p
, end
, second
) || p
!= end
)
275 throw_invalid_value(param_name
);
277 // Construct the predicate
279 return sinks::file::rotation_at_time_point(weekday
.get(), hour
, minute
, second
);
281 return sinks::file::rotation_at_time_point(gregorian::greg_day(day
.get()), hour
, minute
, second
);
283 return sinks::file::rotation_at_time_point(hour
, minute
, second
);
286 //! Base class for default sink factories
287 template< typename CharT
>
288 class basic_default_sink_factory
:
289 public sink_factory
< CharT
>
292 typedef sink_factory
< CharT
> base_type
;
293 typedef typename
base_type::char_type char_type
;
294 typedef typename
base_type::string_type string_type
;
295 typedef typename
base_type::settings_section settings_section
;
296 typedef boost::log::aux::char_constants
< char_type
> constants
;
299 //! Sink backend character selection function
300 template< typename InitializerT
>
301 static shared_ptr
< sinks::sink
> select_backend_character_type(settings_section
const& params
, InitializerT initializer
)
303 #if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
304 if (optional
< string_type
> wide_param
= params
["Wide"])
306 if (param_cast_to_bool("Wide", wide_param
.get()))
307 return initializer(params
, type
< wchar_t >());
310 return initializer(params
, type
< char >());
311 #elif defined(BOOST_LOG_USE_CHAR)
312 return initializer(params
, type
< char >());
313 #elif defined(BOOST_LOG_USE_WCHAR_T)
314 return initializer(params
, type
< wchar_t >());
318 //! The function initializes common parameters of a formatting sink and returns the constructed sink
319 template< typename BackendT
>
320 static shared_ptr
< sinks::sink
> init_sink(shared_ptr
< BackendT
> const& backend
, settings_section
const& params
)
322 typedef BackendT backend_t
;
323 typedef typename
sinks::has_requirement
<
324 typename
backend_t::frontend_requirements
,
325 sinks::formatted_records
326 >::type is_formatting_t
;
330 if (optional
< string_type
> filter_param
= params
["Filter"])
332 filt
= parse_filter(filter_param
.get());
335 shared_ptr
< sinks::basic_sink_frontend
> p
;
337 #if !defined(BOOST_LOG_NO_THREADS)
338 // Asynchronous. TODO: make it more flexible.
340 if (optional
< string_type
> async_param
= params
["Asynchronous"])
342 async
= param_cast_to_bool("Asynchronous", async_param
.get());
345 // Construct the frontend, considering Asynchronous parameter
348 p
= init_formatter(boost::make_shared
< sinks::synchronous_sink
< backend_t
> >(backend
), params
, is_formatting_t());
352 p
= init_formatter(boost::make_shared
< sinks::asynchronous_sink
< backend_t
> >(backend
), params
, is_formatting_t());
354 // https://svn.boost.org/trac/boost/ticket/10638
355 // The user doesn't have a way to process excaptions from the dedicated thread anyway, so just suppress them instead of
356 // terminating the application.
357 p
->set_exception_handler(nop());
360 // When multithreading is disabled we always use the unlocked sink frontend
361 p
= init_formatter(boost::make_shared
< sinks::unlocked_sink
< backend_t
> >(backend
), params
, is_formatting_t());
370 //! The function initializes formatter for the sinks that support formatting
371 template< typename SinkT
>
372 static shared_ptr
< SinkT
> init_formatter(shared_ptr
< SinkT
> const& sink
, settings_section
const& params
, true_type
)
375 if (optional
< string_type
> format_param
= params
["Format"])
377 typedef typename
SinkT::char_type sink_char_type
;
378 std::basic_string
< sink_char_type
> format_str
;
379 log::aux::code_convert(format_param
.get(), format_str
);
380 sink
->set_formatter(parse_formatter(format_str
));
384 template< typename SinkT
>
385 static shared_ptr
< SinkT
> init_formatter(shared_ptr
< SinkT
> const& sink
, settings_section
const& params
, false_type
)
391 //! Default console sink factory
392 template< typename CharT
>
393 class default_console_sink_factory
:
394 public basic_default_sink_factory
< CharT
>
397 typedef basic_default_sink_factory
< CharT
> base_type
;
398 typedef typename
base_type::char_type char_type
;
399 typedef typename
base_type::string_type string_type
;
400 typedef typename
base_type::settings_section settings_section
;
401 typedef typename
base_type::constants constants
;
408 typedef shared_ptr
< sinks::sink
> result_type
;
410 template< typename BackendCharT
>
411 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
413 // Construct the backend
414 typedef boost::log::aux::char_constants
< BackendCharT
> constants
;
415 typedef sinks::basic_text_ostream_backend
< BackendCharT
> backend_t
;
416 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
417 backend
->add_stream(shared_ptr
< typename
backend_t::stream_type
>(&constants::get_console_log_stream(), boost::null_deleter()));
420 if (optional
< string_type
> auto_newline_param
= params
["AutoNewline"])
422 backend
->set_auto_newline_mode(param_cast_to_auto_newline_mode("AutoNewline", auto_newline_param
.get()));
426 if (optional
< string_type
> auto_flush_param
= params
["AutoFlush"])
428 backend
->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param
.get()));
431 return base_type::init_sink(backend
, params
);
436 //! The function constructs a sink that writes log records to the console
437 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
) BOOST_OVERRIDE
439 return base_type::select_backend_character_type(params
, impl());
443 //! Default text file sink factory
444 template< typename CharT
>
445 class default_text_file_sink_factory
:
446 public basic_default_sink_factory
< CharT
>
449 typedef basic_default_sink_factory
< CharT
> base_type
;
450 typedef typename
base_type::char_type char_type
;
451 typedef typename
base_type::string_type string_type
;
452 typedef typename
base_type::settings_section settings_section
;
453 typedef typename
base_type::constants constants
;
456 //! The function constructs a sink that writes log records to a text file
457 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
) BOOST_OVERRIDE
459 typedef sinks::text_file_backend backend_t
;
460 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
463 if (optional
< string_type
> file_name_param
= params
["FileName"])
465 backend
->set_file_name_pattern(filesystem::path(file_name_param
.get()));
468 BOOST_LOG_THROW_DESCR(missing_value
, "File name is not specified");
471 if (optional
< string_type
> target_file_name_param
= params
["TargetFileName"])
473 backend
->set_target_file_name_pattern(filesystem::path(target_file_name_param
.get()));
476 // File rotation size
477 if (optional
< string_type
> rotation_size_param
= params
["RotationSize"])
479 backend
->set_rotation_size(param_cast_to_int
< uintmax_t >("RotationSize", rotation_size_param
.get()));
482 // File rotation interval
483 if (optional
< string_type
> rotation_interval_param
= params
["RotationInterval"])
485 backend
->set_time_based_rotation(sinks::file::rotation_at_time_interval(
486 posix_time::seconds(param_cast_to_int
< unsigned int >("RotationInterval", rotation_interval_param
.get()))));
488 else if (optional
< string_type
> rotation_time_point_param
= params
["RotationTimePoint"])
490 // File rotation time point
491 backend
->set_time_based_rotation(param_cast_to_rotation_time_point("RotationTimePoint", rotation_time_point_param
.get()));
495 if (optional
< string_type
> enable_final_rotation_param
= params
["EnableFinalRotation"])
497 backend
->enable_final_rotation(param_cast_to_bool("EnableFinalRotation", enable_final_rotation_param
.get()));
501 if (optional
< string_type
> auto_newline_param
= params
["AutoNewline"])
503 backend
->set_auto_newline_mode(param_cast_to_auto_newline_mode("AutoNewline", auto_newline_param
.get()));
507 if (optional
< string_type
> auto_flush_param
= params
["AutoFlush"])
509 backend
->auto_flush(param_cast_to_bool("AutoFlush", auto_flush_param
.get()));
513 if (optional
< string_type
> append_param
= params
["Append"])
515 if (param_cast_to_bool("Append", append_param
.get()))
516 backend
->set_open_mode(std::ios_base::out
| std::ios_base::app
);
519 // File collector parameters
521 if (optional
< string_type
> target_param
= params
["Target"])
523 filesystem::path
target_dir(target_param
.get());
526 uintmax_t max_size
= (std::numeric_limits
< uintmax_t >::max
)();
527 if (optional
< string_type
> max_size_param
= params
["MaxSize"])
528 max_size
= param_cast_to_int
< uintmax_t >("MaxSize", max_size_param
.get());
532 if (optional
< string_type
> min_space_param
= params
["MinFreeSpace"])
533 space
= param_cast_to_int
< uintmax_t >("MinFreeSpace", min_space_param
.get());
535 // Max number of files
536 uintmax_t max_files
= (std::numeric_limits
< uintmax_t >::max
)();
537 if (optional
< string_type
> max_files_param
= params
["MaxFiles"])
538 max_files
= param_cast_to_int
< uintmax_t >("MaxFiles", max_files_param
.get());
540 backend
->set_file_collector(sinks::file::make_collector(
541 keywords::target
= target_dir
,
542 keywords::max_size
= max_size
,
543 keywords::min_free_space
= space
,
544 keywords::max_files
= max_files
));
546 // Scan for log files
547 if (optional
< string_type
> scan_param
= params
["ScanForFiles"])
549 string_type
const& value
= scan_param
.get();
550 if (value
== constants::scan_method_all())
551 backend
->scan_for_files(sinks::file::scan_all
);
552 else if (value
== constants::scan_method_matching())
553 backend
->scan_for_files(sinks::file::scan_matching
);
556 BOOST_LOG_THROW_DESCR(invalid_value
,
557 "File scan method \"" + boost::log::aux::to_narrow(value
) + "\" is not supported");
562 return base_type::init_sink(backend
, params
);
566 #ifndef BOOST_LOG_WITHOUT_SYSLOG
568 //! Default syslog sink factory
569 template< typename CharT
>
570 class default_syslog_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
;
581 //! The function constructs a sink that writes log records to syslog
582 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
) BOOST_OVERRIDE
584 // Construct the backend
585 typedef sinks::syslog_backend backend_t
;
586 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
588 // For now we use only the default level mapping. Will add support for configuration later.
589 backend
->set_severity_mapper(sinks::syslog::direct_severity_mapping
< >(log::aux::default_attribute_names::severity()));
591 #if !defined(BOOST_LOG_NO_ASIO)
592 // Setup local and remote addresses
593 if (optional
< string_type
> local_address_param
= params
["LocalAddress"])
594 backend
->set_local_address(param_cast_to_address("LocalAddress", local_address_param
.get()));
596 if (optional
< string_type
> target_address_param
= params
["TargetAddress"])
597 backend
->set_target_address(param_cast_to_address("TargetAddress", target_address_param
.get()));
598 #endif // !defined(BOOST_LOG_NO_ASIO)
600 return base_type::init_sink(backend
, params
);
604 #endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
606 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
608 //! Default debugger sink factory
609 template< typename CharT
>
610 class default_debugger_sink_factory
:
611 public basic_default_sink_factory
< CharT
>
614 typedef basic_default_sink_factory
< CharT
> base_type
;
615 typedef typename
base_type::char_type char_type
;
616 typedef typename
base_type::string_type string_type
;
617 typedef typename
base_type::settings_section settings_section
;
618 typedef typename
base_type::constants constants
;
625 typedef shared_ptr
< sinks::sink
> result_type
;
627 template< typename BackendCharT
>
628 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
630 // Construct the backend
631 typedef sinks::basic_debug_output_backend
< BackendCharT
> backend_t
;
632 shared_ptr
< backend_t
> backend
= boost::make_shared
< backend_t
>();
634 return base_type::init_sink(backend
, params
);
639 //! The function constructs a sink that writes log records to the debugger
640 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
642 return base_type::select_backend_character_type(params
, impl());
646 #endif // !defined(BOOST_LOG_WITHOUT_DEBUG_OUTPUT)
648 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
650 //! Default simple event log sink factory
651 template< typename CharT
>
652 class default_simple_event_log_sink_factory
:
653 public basic_default_sink_factory
< CharT
>
656 typedef basic_default_sink_factory
< CharT
> base_type
;
657 typedef typename
base_type::char_type char_type
;
658 typedef typename
base_type::string_type string_type
;
659 typedef typename
base_type::settings_section settings_section
;
660 typedef typename
base_type::constants constants
;
667 typedef shared_ptr
< sinks::sink
> result_type
;
669 template< typename BackendCharT
>
670 result_type
operator() (settings_section
const& params
, type
< BackendCharT
>) const
672 typedef sinks::basic_simple_event_log_backend
< BackendCharT
> backend_t
;
673 typedef typename
backend_t::string_type backend_string_type
;
675 // Determine the log name
676 backend_string_type log_name
;
677 if (optional
< string_type
> log_name_param
= params
["LogName"])
678 log::aux::code_convert(log_name_param
.get(), log_name
);
680 log_name
= backend_t::get_default_log_name();
682 // Determine the log source name
683 backend_string_type source_name
;
684 if (optional
< string_type
> log_source_param
= params
["LogSource"])
685 log::aux::code_convert(log_source_param
.get(), source_name
);
687 source_name
= backend_t::get_default_source_name();
689 // Determine the registration mode
690 sinks::event_log::registration_mode reg_mode
= sinks::event_log::on_demand
;
691 if (optional
< string_type
> registration_param
= params
["Registration"])
693 string_type
const& value
= registration_param
.get();
694 if (value
== constants::registration_never())
695 reg_mode
= sinks::event_log::never
;
696 else if (value
== constants::registration_on_demand())
697 reg_mode
= sinks::event_log::on_demand
;
698 else if (value
== constants::registration_forced())
699 reg_mode
= sinks::event_log::forced
;
702 BOOST_LOG_THROW_DESCR(invalid_value
,
703 "The registration mode \"" + log::aux::to_narrow(value
) + "\" is not supported");
707 // Construct the backend
708 shared_ptr
< backend_t
> backend(boost::make_shared
< backend_t
>((
709 keywords::log_name
= log_name
,
710 keywords::log_source
= source_name
,
711 keywords::registration
= reg_mode
)));
713 // For now we use only the default event type mapping. Will add support for configuration later.
714 backend
->set_event_type_mapper(sinks::event_log::direct_event_type_mapping
< >(log::aux::default_attribute_names::severity()));
716 return base_type::init_sink(backend
, params
);
721 //! The function constructs a sink that writes log records to the Windows NT Event Log
722 shared_ptr
< sinks::sink
> create_sink(settings_section
const& params
)
724 return base_type::select_backend_character_type(params
, impl());
728 #endif // !defined(BOOST_LOG_WITHOUT_EVENT_LOG)
731 //! The supported sinks repository
732 template< typename CharT
>
733 struct sinks_repository
:
734 public log::aux::lazy_singleton
< sinks_repository
< CharT
> >
736 typedef log::aux::lazy_singleton
< sinks_repository
< CharT
> > base_type
;
738 #if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS)
739 friend class log::aux::lazy_singleton
< sinks_repository
< CharT
> >;
741 friend class base_type
;
744 typedef CharT char_type
;
745 typedef std::basic_string
< char_type
> string_type
;
746 typedef basic_settings_section
< char_type
> settings_section
;
747 typedef boost::log::aux::char_constants
< char_type
> constants
;
748 typedef boost::shared_ptr
< sink_factory
< char_type
> > sink_factory_ptr
;
749 typedef std::map
< std::string
, sink_factory_ptr
> sink_factories
;
751 #if !defined(BOOST_LOG_NO_THREADS)
752 //! Synchronization mutex
753 log::aux::light_rw_mutex m_Mutex
;
755 //! Map of the sink factories
756 sink_factories m_Factories
;
758 //! The function constructs a sink from the settings
759 shared_ptr
< sinks::sink
> construct_sink_from_settings(settings_section
const& params
)
761 typedef typename
settings_section::const_reference param_const_reference
;
762 if (param_const_reference dest_node
= params
["Destination"])
764 std::string dest
= log::aux::to_narrow(dest_node
.get().get());
766 BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard
< log::aux::light_rw_mutex
> lock(m_Mutex
);)
767 typename
sink_factories::const_iterator it
= m_Factories
.find(dest
);
768 if (it
!= m_Factories
.end())
770 return it
->second
->create_sink(params
);
774 BOOST_LOG_THROW_DESCR(invalid_value
, "The sink destination is not supported: " + dest
);
779 BOOST_LOG_THROW_DESCR(missing_value
, "The sink destination is not set");
783 static void init_instance()
785 sinks_repository
& instance
= base_type::get_instance();
786 instance
.m_Factories
["TextFile"] = boost::make_shared
< default_text_file_sink_factory
< char_type
> >();
787 instance
.m_Factories
["Console"] = boost::make_shared
< default_console_sink_factory
< char_type
> >();
788 #ifndef BOOST_LOG_WITHOUT_SYSLOG
789 instance
.m_Factories
["Syslog"] = boost::make_shared
< default_syslog_sink_factory
< char_type
> >();
791 #ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT
792 instance
.m_Factories
["Debugger"] = boost::make_shared
< default_debugger_sink_factory
< char_type
> >();
794 #ifndef BOOST_LOG_WITHOUT_EVENT_LOG
795 instance
.m_Factories
["SimpleEventLog"] = boost::make_shared
< default_simple_event_log_sink_factory
< char_type
> >();
800 sinks_repository() {}
803 //! The function applies the settings to the logging core
804 template< typename CharT
>
805 void apply_core_settings(basic_settings_section
< CharT
> const& params
)
807 typedef CharT char_type
;
808 typedef std::basic_string
< char_type
> string_type
;
810 core_ptr core
= boost::log::core::get();
813 if (optional
< string_type
> filter_param
= params
["Filter"])
814 core
->set_filter(parse_filter(filter_param
.get()));
816 core
->reset_filter();
819 if (optional
< string_type
> disable_logging_param
= params
["DisableLogging"])
820 core
->set_logging_enabled(!param_cast_to_bool("DisableLogging", disable_logging_param
.get()));
822 core
->set_logging_enabled(true);
828 //! The function initializes the logging library from a settings container
829 template< typename CharT
>
830 BOOST_LOG_SETUP_API
void init_from_settings(basic_settings_section
< CharT
> const& setts
)
832 typedef basic_settings_section
< CharT
> section
;
833 typedef typename
section::char_type char_type
;
834 typedef sinks_repository
< char_type
> sinks_repo_t
;
836 // Apply core settings
837 if (section core_params
= setts
["Core"])
838 apply_core_settings(core_params
);
840 // Construct and initialize sinks
841 if (section sink_params
= setts
["Sinks"])
843 sinks_repo_t
& sinks_repo
= sinks_repo_t::get();
844 std::vector
< shared_ptr
< sinks::sink
> > new_sinks
;
846 for (typename
section::const_iterator it
= sink_params
.begin(), end
= sink_params
.end(); it
!= end
; ++it
)
848 section sink_params
= *it
;
850 // Ignore empty sections as they are most likely individual parameters (which should not be here anyway)
851 if (!sink_params
.empty())
853 new_sinks
.push_back(sinks_repo
.construct_sink_from_settings(sink_params
));
857 std::for_each(new_sinks
.begin(), new_sinks
.end(), boost::bind(&core::add_sink
, core::get(), boost::placeholders::_1
));
862 //! The function registers a factory for a sink
863 template< typename CharT
>
864 BOOST_LOG_SETUP_API
void register_sink_factory(const char* sink_name
, shared_ptr
< sink_factory
< CharT
> > const& factory
)
866 sinks_repository
< CharT
>& repo
= sinks_repository
< CharT
>::get();
867 BOOST_LOG_EXPR_IF_MT(lock_guard
< log::aux::light_rw_mutex
> lock(repo
.m_Mutex
);)
868 repo
.m_Factories
[sink_name
] = factory
;
871 #ifdef BOOST_LOG_USE_CHAR
872 template BOOST_LOG_SETUP_API
void register_sink_factory
< char >(const char* sink_name
, shared_ptr
< sink_factory
< char > > const& factory
);
873 template BOOST_LOG_SETUP_API
void init_from_settings
< char >(basic_settings_section
< char > const& setts
);
876 #ifdef BOOST_LOG_USE_WCHAR_T
877 template BOOST_LOG_SETUP_API
void register_sink_factory
< wchar_t >(const char* sink_name
, shared_ptr
< sink_factory
< wchar_t > > const& factory
);
878 template BOOST_LOG_SETUP_API
void init_from_settings
< wchar_t >(basic_settings_section
< wchar_t > const& setts
);
881 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
885 #include <boost/log/detail/footer.hpp>
887 #endif // BOOST_LOG_WITHOUT_SETTINGS_PARSERS