1[/ 2 Copyright Andrey Semashev 2007 - 2016. 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 This document is a part of Boost.Log library documentation. 8/] 9 10[section:utilities Utilities] 11 12[section:string_literal String literals] 13 14 #include <``[boost_log_utility_string_literal_hpp]``> 15 16String literals are used in several places throughout the library. However, this component can be successfully used outside of the library in users' code. It is header-only and does not require linking with the library binary. String literals can improve performance significantly if there is no need to modify stored strings. What is also important, since string literals do not dynamically allocate memory, it is easier to maintain exception safety when using string literals instead of regular strings. 17 18The functionality is implemented in the [class_log_basic_string_literal] class template, which is parametrized with the character and character traits, similar to `std::basic_string`. There are also two convenience typedefs provided: `string_literal` and `wstring_literal`, for narrow and wide character types, respectively. In order to ease string literal construction in generic code there is also a `str_literal` function template that accepts a string literal and returns a [class_log_basic_string_literal] instance for the appropriate character type. 19 20String literals support interface similar to STL strings, except for string modification functions. However, it is possible to assign to or clear string literals, as long as only string literals involved. Relational and stream output operators are also supported. 21 22[endsect] 23 24[section:type_dispatch Type dispatchers] 25 26 #include <``[boost_log_utility_type_dispatch_type_dispatcher_hpp]``> 27 28Type dispatchers are used throughout the library in order to work with attribute values. Dispatchers allow acquiring the stored attribute value using the Visitor concept. The most notable places where the functionality is used are filters and formatters. However, this mechanism is orthogonal to attributes and can be used for other purposes as well. Most of the time users won't need to dig into the details of type dispatchers, but this information may be useful for those who intend to extend the library and wants to understand what's under the hood. 29 30Every type dispatcher supports the [class_log_type_dispatcher] interface. When an attribute value needs to be extracted, this interface is passed to the attribute value object, which then tries to acquire the callback for the actual type of the value. All callbacks are objects of the [class_type_dispatcher_callback] class template, instantiated on the actual type of the value. If the dispatcher is able to consume the value of the requested type, it must return a non-empty callback object. When (and if) the corresponding callback is acquired, the attribute value object only has to pass the contained value to its `operator ()`. 31 32Happily, there is no need to write type dispatchers from scratch. The library provides two kinds of type dispatchers that implement the [class_log_type_dispatcher] and [class_type_dispatcher_callback] interfaces and encapsulate the callback lookup. 33 34[heading Static type dispatcher] 35 36 #include <``[boost_log_utility_type_dispatch_static_type_dispatcher_hpp]``> 37 38Static type dispatchers are used when the set of types that needs to be supported for extraction is known at compile time. The [class_log_static_type_dispatcher] class template is parametrized with an MPL type sequence of types that need to be supported. The dispatcher inherits from the [class_log_type_dispatcher] interface which provides the `get_callback` method for acquiring the function object to invoke on the stored value. All you need to do is provide a visitor function object to the dispatcher at construction point and invoke the callback when dispatching the stored value: 39 40[example_util_static_type_dispatcher] 41 42[@boost:/libs/log/example/doc/util_static_type_disp.cpp See the complete code]. 43 44[heading Dynamic type dispatcher] 45 46 #include <``[boost_log_utility_type_dispatch_dynamic_type_dispatcher_hpp]``> 47 48If the set of types that have to be supported is not available at compile time, the [class_log_dynamic_type_dispatcher] class is there to help. One can use its `register_type` method to add support for a particular type. The user has to pass a function object along with the type, this functor will be called when a visitor for the specified type is invoked. Considering the `my_value` from the code sample for static type dispatcher is intact, the code can be rewritten as follows: 49 50[example_util_dynamic_type_dispatcher] 51 52[@boost:/libs/log/example/doc/util_dynamic_type_disp.cpp See the complete code]. 53 54Of course, complex function objects, like those provided by __boost_bind__, are also supported. 55 56[endsect] 57 58[section:predef_types Predefined type sequences] 59 60 #include <``[boost_log_utility_type_dispatch_standard_types_hpp]``> 61 #include <``[boost_log_utility_type_dispatch_date_time_types_hpp]``> 62 63One may notice that when using type dispatchers and defining filters and formatters it may be convenient to have some predefined type sequences to designate frequently used sets of types. The library provides several such sets. 64 65[table Standard types (standard_types.hpp) 66 [[Type sequence] [Meaning]] 67 [[`integral_types`] [All integral types, including `bool`, character and 64 bit integral types, if available]] 68 [[`floating_point_types`] [Floating point types]] 69 [[`numeric_types`] [Includes `integral_types` and `floating_point_types`]] 70 [[`string_types`] [Narrow and wide string types. Currently only includes STL string types and [link log.detailed.utilities.string_literal string literals].]] 71] 72 73There are also a number of time-related type sequences available: 74 75[table Time-related types (date_time_types.hpp) 76 [[Type sequence] [Meaning]] 77 [[`native_date_time_types`] [All types defined in C/C++ standard that have both date and time portions]] 78 [[`boost_date_time_types`] [All types defined in __boost_date_time__ that have both date and time portions]] 79 [[`date_time_types`] [Includes `native_date_time_types` and `boost_date_time_types`]] 80 [[`native_date_types`] [All types defined in C/C++ standard that have date portion. Currently equivalent to `native_date_time_types`.]] 81 [[`boost_date_types`] [All types defined in __boost_date_time__ that have date portion]] 82 [[`date_types`] [Includes `native_date_types` and `boost_date_types`]] 83 [[`native_time_types`] [All types defined in C/C++ standard that have time portion. Currently equivalent to `native_date_time_types`.]] 84 [[`boost_time_types`] [All types defined in __boost_date_time__ that have time portion. Currently equivalent to `boost_date_time_types`.]] 85 [[`time_types`] [Includes `native_time_types` and `boost_time_types`]] 86 [[`native_time_duration_types`] [All types defined in C/C++ standard that are used to represent time duration. Currently only includes `double`, as the result type of the `difftime` standard function.]] 87 [[`boost_time_duration_types`] [All time duration types defined in __boost_date_time__]] 88 [[`time_duration_types`] [Includes `native_time_duration_types` and `boost_time_duration_types`]] 89 [[`boost_time_period_types`] [All time period types defined in __boost_date_time__]] 90 [[`time_period_types`] [Currently equivalent to `boost_time_period_types`]] 91] 92 93[endsect] 94 95[section:value_ref Value reference wrapper] 96 97 #include <``[boost_log_utility_value_ref_hpp]``> 98 99The [class_log_value_ref] class template is an optional reference wrapper which is used by the library to refer to the stored attribute values. To a certain degree it shares features of __boost_optional__ and __boost_variant__ components. 100 101The template has two type parameters. The first is the referred type. It can also be specified as a __boost_mpl__ type sequence, in which case the [class_log_value_ref] wrapper may refer to either type in the sequence. In this case, the `which` method will return the index of the referred type within the sequence. The second template parameter is an optional tag type which can be used to customize formatting behavior. This tag is forwarded to the [link log.detailed.utilities.manipulators.to_log `to_log`] manipulator when the wrapper is put to a [class_log_basic_formatting_ostream] stream, which is used by the library for record formatting. For an example see how attribute value extraction is implemented: 102 103[example_attr_value_extraction_multiple_types] 104 105[@boost:/libs/log/example/doc/attr_value_extraction.cpp See the complete code]. 106 107The [class_log_value_ref] wrapper also supports applying a visitor function object to the referred object. This can be done by calling one of the following methods: 108 109* `apply_visitor`. This method should only be used on a valid (non-empty) reference. The method returns the visitor result. 110* `apply_visitor_optional`. The method checks if the reference is valid and applies the visitor to the referred value if it is. The method returns the visitor result wrapped into `boost::optional` which will be filled only if the reference is valid. 111* `apply_visitor_or_default`. If the reference is valid, the method applies the visitor on the referred value and returns its result. Otherwise the method returns a default value passed as the second argument. 112 113[note Regardless of the method used, the visitor function object [_must] define the `result_type` typedef. Polymorphic visitors are not supported as this would complicate the [class_log_value_ref] interface too much. This requirement also precludes free functions and C++11 lambda functions from being used as visitors. Please, use __boost_bind__ or similar wrappers in such cases.] 114 115Here is an example of applying a visitor: 116 117[example_attr_value_extraction_visitor] 118 119[endsect] 120 121[section:record_ordering Log record ordering] 122 123 #include <``[boost_log_utility_record_ordering_hpp]``> 124 125There are cases when log records need to be ordered. One possible use case is storing records in a container or a priority queue. The library provides two types of record ordering predicates out of the box: 126 127[heading Abstract record ordering] 128 129The [class_log_abstract_ordering] class allows application of a quick opaque ordering. The result of this ordering is not stable between different runs of the application and in general cannot be predicted before the predicate is applied, however it provides the best performance. The [class_log_abstract_ordering] class is a template that is specialized with an optional predicate function that will be able to compare `const void*` pointers. By default an `std::less` equivalent is used. 130 131 // A set of unique records 132 std::set< logging::record_view, logging::abstract_ordering< > > m_Records; 133 134This kind of ordering can be useful if the particular order of log records is not important but nevertheless some order is required. 135 136[heading Attribute value based ordering] 137 138This kind of ordering is implemented with the [class_log_attribute_value_ordering] class and is based on the attribute values attached to the record. The predicate will seek for an attribute value with the specified name in both records being ordered and attempt to compare the attribute values. 139 140 // Ordering type definition 141 typedef logging::attribute_value_ordering< 142 int // attribute value type 143 > ordering; 144 145 // Records organized into a queue based on the "Severity" attribute value 146 std::priority_queue< 147 logging::record_view, 148 std::vector< logging::record_view >, 149 ordering 150 > m_Records(ordering("Severity")); 151 152Like the [class_log_abstract_ordering], [class_log_attribute_value_ordering] also accepts the second optional template parameter, which should be the predicate to compare attribute values (`int`s in the example above). By default, an `std::less` equivalent is used. 153 154You can also use the [funcref boost::log::make_attr_ordering `make_attr_ordering`] generator function to automatically generate the [class_log_attribute_value_ordering] instance based on the attribute value name and the ordering function. This might be useful if the ordering function has a non-trivial type, like the ones __boost_bind__ provides. 155 156[endsect] 157 158[section:exception_handlers Exception handlers] 159 160 #include <``[boost_log_utility_exception_handler_hpp]``> 161 162The library provides exception handling hooks in different places. Tools, defined in this header, provide an easy way of implementing function objects suitable for such hooks. 163 164An exception handler is a function object that accepts no arguments. The result of the exception handler is ignored and thus should generally be `void`. Exception handlers are called from within `catch` sections by the library, therefore in order to reacquire the exception object it has to rethrow it. The header defines an [class_log_exception_handler] template functor that does just that and then forwards the exception object to a unary user-defined functional object. The [funcref boost::log::make_exception_handler `make_exception_handler`] function can be used to simplify the handler construction. All expected exception types should be specified explicitly in the call, in the order they would appear in the `catch` sections (i.e. from most specific ones to the most general ones). 165 166[example_utility_exception_handler] 167 168As you can see, you can either suppress the exception by returning normally from `operator()` in the user-defined handler functor, or rethrow the exception, in which case it will propagate further. If it appears that the exception handler is invoked for an exception type that cannot be caught by any of the specified types, the exception will be propagated without any processing. In order to catch such situations, there exists the [class_log_nothrow_exception_handler] class. It invokes the user-defined functor with no arguments if it cannot determine the exception type. 169 170[example_utility_exception_handler_nothrow] 171 172It is sometimes convenient to completely suppress all exceptions at a certain library level. The [funcref boost::log::make_exception_suppressor `make_exception_suppressor`] function creates an exception handler that simply does nothing upon exception being caught. For example, this way we can disable all exceptions from the logging library: 173 174 void init_logging() 175 { 176 boost::shared_ptr< logging::core > core = logging::core::get(); 177 178 // Disable all exceptions 179 core->set_exception_handler(logging::make_exception_suppressor()); 180 } 181 182[endsect] 183 184[section:manipulators Output manipulators] 185 186The library provides a number of stream manipulators that may be useful in some contexts. 187 188[section:to_log Customized logging manipulator] 189 190 #include <``[boost_log_utility_manipulators_to_log_hpp]``> 191 192The [funcref boost::log::to_log `to_log`] function creates a stream manipulator that simply outputs the adopted value to the stream. By default its behavior is equivalent to simply putting the value to the stream. However, the user is able to overload the `operator<<` for the adopted value to override formatting behavior when values are formatted for logging purposes. This is typically desired when the regular `operator<<` is employed for other tasks (such as serialization) and its behavior is neither suitable for logging nor can be easily changed. For example: 193 194[example_utility_manipulators_to_log] 195 196The second streaming statement in the `test_manip` function will invoke our custom stream insertion operator which defines special formatting rules. 197 198It is also possible to define different formatting rules for different value contexts as well. The library uses this feature to allow different formatting ruled for different attribute values, even if the stored value type is the same. To do so one has to specify an explicit template argument for [funcref boost::log::to_log `to_log`], a tag type, which will be embedded into the manipulator type and thus will allow to define different insertion operators: 199 200[example_utility_manipulators_to_log_with_tag] 201 202[@boost:/libs/log/example/doc/util_manip_to_log.cpp See the complete code]. 203 204[note The library uses [class_log_basic_formatting_ostream] stream type for record formatting, so when customizing attribute value formatting rules the `operator<<` must use [class_log_basic_formatting_ostream] instead of `std::ostream`.] 205 206[endsect] 207 208[section:add_value Attribute value attaching manipulator] 209 210 #include <``[boost_log_utility_manipulators_add_value_hpp]``> 211 212The [funcref boost::log::add_value `add_value`] function creates a manipulator that attaches an attribute value to a log record. This manipulator can only be used in streaming expressions with the [class_log_basic_record_ostream] stream type (which is the case when log record message is formatted). Since the message text is only formatted after filtering, attribute values attached with this manipulator do not affect filtering and can only be used in formatters and sinks themselves. 213 214In addition to the value itself, the manipulator also requires the attribute name to be provided. For example: 215 216 // Creates a log record with attribute value "MyAttr" of type int attached 217 BOOST_LOG(lg) << logging::add_value("MyAttr", 10) << "Hello world!"; 218 219[endsect] 220 221[section:dump Binary dump manipulator] 222 223 #include <``[boost_log_utility_manipulators_dump_hpp]``> 224 225The [funcref boost::log::dump `dump`] function creates a manipulator that outputs binary contents of a contiguous memory region. This can be useful for logging some low level binary data, such as encoded network packets or entries of a binary file. The use is quite straightforward: 226 227 void on_receive(std::vector< unsigned char > const& packet) 228 { 229 // Outputs something like "Packet received: 00 01 02 0a 0b 0c" 230 BOOST_LOG(lg) << "Packet received: " << logging::dump(packet.data(), packet.size()); 231 } 232 233The manipulator also allows to limit the amount of data to be output, in case if the input data can be too large. Just specify the maximum number of bytes of input to dump as the last argument: 234 235 void on_receive(std::vector< unsigned char > const& packet) 236 { 237 // Outputs something like "Packet received: 00 01 02 03 04 05 06 07 and 67 bytes more" 238 BOOST_LOG(lg) << "Packet received: " << logging::dump(packet.data(), packet.size(), 8); 239 } 240 241There is another manipulator called [funcref boost::log::dump_elements `dump_elements`] for printing binary representation of non-byte array elements. The special manipulator for this case is necessary because the units of the size argument of [funcref boost::log::dump `dump`] can be confusing (is it in bytes or in elements?). Therefore [funcref boost::log::dump `dump`] will not compile when used for non-byte input data. [funcref boost::log::dump_elements `dump_elements`] accepts the same arguments, and its size-related arguments always designate the number of elements to process. 242 243 void process(std::vector< double > const& matrix) 244 { 245 // Note that dump_elements accepts the number of elements in the matrix, not its size in bytes 246 BOOST_LOG(lg) << "Matrix dump: " << logging::dump_elements(matrix.data(), matrix.size()); 247 } 248 249[tip Both these manipulators can also be used with regular output streams, not necessarily loggers.] 250 251[endsect] 252 253[section:auto_newline Automatic newline insertion] 254 255 #include <``[boost_log_utility_manipulators_auto_newline_hpp]``> 256 257Sometimes it can be useful to be able to insert a newline character in the output stream, but only if it hasn't been inserted as part of the previous output. For example, if a string may or may not end with a newline, and we cannot easily tell which one it is each time. The `auto_newline` manipulator can be used to ensure that all such strings are reliably terminated with a newline and there are no duplicate newline characters. The manipulator will insert a newline unless the last character inserted into the stream before it was a newline. Its use is similar to standard stream manipulators: 258 259 BOOST_LOG(lg) << "Parameter: " << param.name << ", value: " << param.value << logging::auto_newline; 260 261[note This manipulator inspects previous output to the stream, and therefore can only be used with Boost.Log streams based on [class_log_basic_formatting_ostream].] 262 263[endsect] 264 265[section:range Range manipulator] 266 267 #include <``[boost_log_utility_manipulators_range_hpp]``> 268 269It can be useful to be able to output elements of a container (or, more generally, a range), preferably separated with a delimiter. The `range_manip` manipulator allows to do this: 270 271 std::vector< int > ints{ 1, 2, 3 }; 272 273 BOOST_LOG(lg) << "Integers: { " << logging::range_manip(ints, ", ") << " }"; // Outputs: "Integers: { 1, 2, 3 }" 274 275[tip This manipulator can also be used with regular output streams, not necessarily loggers.] 276 277Here, `range_manip` accepts two arguments - the range of elements, and, optionally, a delimiter. The range can be any type supported by __boost_range__ `begin()` and `end()` free functions, which includes any standard containers and arrays. Elements of the range must support stream insertion operator. The delimiter argument, if specified, is inserted into stream between elements. The delimiter can be any type that supports stream insertion. If delimiter is not specified, the elements are output into the stream without separation. 278 279[endsect] 280 281[section:tuple Tuple manipulator] 282 283 #include <``[boost_log_utility_manipulators_tuple_hpp]``> 284 285Tuple manipulator allows to output elements of a heterogeneous sequence (put simply, a tuple) to a stream, possibly separated with a delimiter. For example: 286 287 #include <boost/fusion/include/std_tuple.hpp> 288 289 std::tuple< std::string, int, char > address{ "Baker Street", 221, 'b' }; 290 291 BOOST_LOG(lg) << "Address: " << logging::tuple_manip(address, ", "); // Outputs: "Address: Baker Street, 221, b" 292 293[note In order to support different types of sequences, users may need to `#include` additional support headers from __boost_fusion__, like `boost/fusion/include/std_tuple.hpp` in this example. See __boost_fusion__ documentation.] 294 295[tip This manipulator can also be used with regular output streams, not necessarily loggers.] 296 297Here, `tuple_manip` accepts two arguments - the sequence of elements, and, optionally, a delimiter. The heterogeneous sequence can be any sequence supported by __boost_fusion__, for example `std::pair`, `std::tuple`, `boost::tuple`, `boost::fusion::vector` or any structure that has been adapted using one of the `BOOST_FUSION_ADAPT*` macros. Elements of the sequence must support stream insertion operator. The delimiter argument, if specified, is inserted into stream between elements. The delimiter can be any type that supports stream insertion. If delimiter is not specified, the elements are output into the stream without separation. 298 299[tip You can also use tuples generated by `std::tie` or `boost::tie` with this manipulator, which allows unified formatting of disjoint variables without having to copy them into a structure.] 300 301[endsect] 302 303[section:optional Optional manipulator] 304 305 #include <``[boost_log_utility_manipulators_optional_hpp]``> 306 307Optional manipulator allows to output an optional value to the output stream. If the value is not present, the manipulator allows to specify a "none" marker to output instead. For example: 308 309 boost::optional< int > param1; 310 boost::optional< int > param2 = 10; 311 312 BOOST_LOG(lg) << "param1: " << logging::optional_manip(param1, "[none]") << ", param2: " << logging::optional_manip(param2, "[none]"); // Outputs: "param1: [none], param2: 10" 313 314[tip This manipulator can also be used with regular output streams, not necessarily loggers.] 315 316Here, `optional_manip` accepts two arguments - the optional value, and, optionally, a "none" marker. The optional value can be any type that supports the following: 317 318* Contextually convertible to `bool`, where `true` indicates that the value is present. 319* Can be dereferenced using `operator*()`, and the result of this operator is the value. 320* The result of dereferencing must support stream insertion operator. 321 322Examples of types that fit these requirements are `boost::optional` (see __boost_optional__), `std::optional` and pointers to objects. 323 324The "none" marker argument, if specified, is inserted into stream in case if the optional value is not present (i.e. the contextual conversion to `bool` yields `false`). The marker can be any type that supports stream insertion. If the marker is not specified, no output is produced if the value is not present. 325 326[endsect] 327 328[endsect] 329 330[section:ipc Interprocess communication tools] 331 332[section:object_name Resource name wrapper] 333 334 #include <``[boost_log_utility_ipc_object_name_hpp]``> 335 336In modern operating systems process-shared system resources are typically identified with names. Unfortunately, different systems have different requirements on the name syntax and allowed character set. Additionally, some systems offer support for namespaces in order to avoid name clashes. The [class_ipc_object_name] class is intended to hide these differences. 337 338An object name can be constructed from a UTF-8 string identifier and a scope. A portable identifier can contain the following characters: 339 340[teletype] 341 342 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 343 a b c d e f g h i j k l m n o p q r s t u v w x y z 344 0 1 2 3 4 5 6 7 8 9 . _ - 345 346[c++] 347 348[note The character set corresponds to [@http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278 POSIX Portable Filename Character Set].] 349 350Use of other characters may result in non-portable system-specific behavior. 351 352The scope is identified with the `object_name::scope` enumeration: 353 354* `global` - The name has global scope; any process in the system has the potential to open the resource identified by the name. On some systems this scope may not be available or require elevated privileges. 355* `user` - The name is limited to processes running under the current user. 356* `session` - The name is limited to processes running in the current login session. 357* `process_group` - The name is limited to processes running in the current process group. Currently, on Windows all processes running in the current session are considered members of the same process group. This may change in future. 358 359The scopes are not overlapping. For instance, if an object is created in the global scope, the object cannot be opened with the same name but in user's scope. Some of the scopes may require elevated privileges to create or open objects in. 360 361[warning Object name scoping should not be considered a security measure. Objects may still be accessible by processes outside of their name scopes. The main purpose of the scopes is to avoid name clashes between different processes using [class_ipc_object_name]. Use access permissions for security control.] 362 363[endsect] 364 365[section:reliable_message_queue Reliable message queue] 366 367 #include <``[boost_log_utility_ipc_reliable_message_queue_hpp]``> 368 369The [class_ipc_reliable_message_queue] class implements a reliable one-way channel of passing messages from one or multiple writers to a single reader. The format of the messages is user-defined and must be consistent across all writers and the reader. The queue does not enforce any specific format of the messages, other than they should be supplied as a contiguous array of bytes. The queue internally uses a process-shared storage identified by an [link log.detailed.utilities.ipc.object_name object name] (the queue name). 370 371The queue storage is organized as a fixed number of blocks of a fixed size. The block size must be an integer power of 2 and is expressed in bytes. Each written message, together with some metadata added by the queue, consumes an integer number of blocks. Each read message received by the reader releases the blocks allocated for that message. As such the maximum size of a message is slightly less than block size times capacity of the queue. For efficiency, it is recommended to choose block size large enough to accommodate most of the messages to be passed through the queue. The queue is considered empty when no messages are enqueued (all blocks are free). The queue is considered full at the point of enqueueing a message when there is not enough free blocks to accommodate the message. 372 373The queue is reliable in that it will not drop successfully sent messages that are not received by the reader, other than the case when a non-empty queue is destroyed by the last user. If a message cannot be enqueued by the writer because the queue is full, the queue will act depending on the overflow policy specified at the queue creation: 374 375* `block_on_overflow` - Block the thread until there is enough space to enqueue the message or the operation is aborted by calling `stop_local`. 376* `fail_on_overflow` - Return an error code from the send operation. The error code is `operation_result::no_space`. 377* `throw_on_overflow` - Throw an exception from the send operation. The exception is [class_log_capacity_limit_reached]. 378 379The policy is object local, i.e. different writers and the reader can have different overflow policies. Here is an example of writing to the message queue: 380 381[example_util_ipc_reliable_mq_writer] 382 383[@boost:/libs/log/example/doc/util_ipc_reliable_mq_writer.cpp See the complete code]. 384 385Typically, the queue would be used for sending log records to a different process. As such, instead of using the queue for writing directly, one would use a special sink backend for that. See [link log.detailed.sink_backends.text_ipc_message_queue `text_ipc_message_queue_backend`] documentation. 386 387Receiving messages from the queue is similar. Here is an example of a log viewer that receives messages from the queue and displays them on the console. 388 389[example_sinks_ipc_receiver] 390 391[@boost:/libs/log/example/doc/sinks_ipc_receiver.cpp See the complete code]. 392 393[note The queue does not guarantee any particular order of received messages from different writer threads. Messages sent by a particular writer thread will be received in the order of sending.] 394 395A blocked reader or writer can be unblocked by calling `stop_local`. After this method is called, all threads blocked on this particular object are released and return `operation_result::aborted`. The other instances of the queue (in the current or other processes) are unaffected. In order to restore the normal functioning of the queue instance after the `stop_local` call the user has to invoke `reset_local`. 396 397[endsect] 398 399[endsect] 400 401[section:setup Simplified library initialization tools] 402 403This part of the library is provided in order to simplify logging initialization and provide basic tools to develop user-specific initialization mechanisms. It is known that setup capabilities and preferences may vary widely from application to application, therefore the library does not attempt to provide a universal solution for this task. The provided tools are mostly intended to serve as a quick drop-in support for logging setup and a set of instruments to implement something more elaborate and more fitting users' needs. 404 405Some of the features described in this section will require the separate library binary, with name based on "boost_log_setup" substring. This binary depends on the main library. 406 407[section:convenience Convenience functions] 408 409 #include <``[boost_log_utility_setup_console_hpp]``> 410 #include <``[boost_log_utility_setup_file_hpp]``> 411 #include <``[boost_log_utility_setup_common_attributes_hpp]``> 412 413The library provides a number of functions that simplify some common initialization procedures, like sink and commonly used attributes registration. This is not much functionality. However, it saves a couple of minutes of learning the library for a newcomer. 414 415Logging to the application console is the simplest way to see the logging library in action. To achieve this, one can initialize the library with a single function call, like this: 416 417 int main(int, char*[]) 418 { 419 // Initialize logging to std::clog 420 logging::add_console_log(); 421 422 // Here we go, we can write logs right away 423 src::logger lg; 424 BOOST_LOG(lg) << "Hello world!"; 425 426 return 0; 427 } 428 429Pretty easy, isn't it? There is also the `wadd_console_log` function for wide-character console. If you want to put logs to some other standard stream, you can pass the stream to the [funcref boost::log::add_console_log `add_console_log`] function as an argument. E.g. enabling logging to `std::cout` instead of `std::clog` would look like this: 430 431 logging::add_console_log(std::cout); 432 433What's important, is that you can further manage the console sink if you save the `shared_ptr` to the sink that this function returns. This allows you to set up things like filter, formatter and auto-flush flag. 434 435 int main(int, char*[]) 436 { 437 // Initialize logging to std::clog 438 boost::shared_ptr< 439 sinks::synchronous_sink< sinks::text_ostream_backend > 440 > sink = logging::add_console_log(); 441 442 sink->set_filter(expr::attr< int >("Severity") >= 3); 443 sink->locked_backend()->auto_flush(true); 444 445 // Here we go, we can write logs right away 446 src::logger lg; 447 BOOST_LOG(lg) << "Hello world!"; 448 449 return 0; 450 } 451 452Similarly to console, one can use a single function call to enable logging to a file. All you have to do is to provide the file name: 453 454 int main(int, char*[]) 455 { 456 // Initialize logging to the "test.log" file 457 logging::add_file_log("test.log"); 458 459 // Here we go, we can write logs right away 460 src::logger lg; 461 BOOST_LOG(lg) << "Hello world!"; 462 463 return 0; 464 } 465 466The [funcref boost::log::add_console_log `add_console_log`] and [funcref boost::log::add_file_log `add_file_log`] functions do not conflict and may be combined freely, so it is possible to set up logging to the console and a couple of files, including filtering and formatting, in about 10 lines of code. 467 468Lastly, there is an [funcref boost::log::add_common_attributes `add_common_attributes`] function that registers two frequently used attributes: "LineID" and "TimeStamp". The former counts log record being made and has attribute value `unsigned int`. The latter, as its name implies, provides the current time for each log record, in the form of `boost::posix_time::ptime` (see __boost_date_time__). These two attributes are registered globally, so they will remain available in all threads and loggers. This makes the final version of our code sample look something like this: 469 470 int main(int, char*[]) 471 { 472 // Initialize sinks 473 logging::add_console_log()->set_filter(expr::attr< int >("Severity") >= 4); 474 475 logging::formatter formatter = 476 expr::stream 477 << expr::attr< unsigned int >("LineID") << ": " 478 << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << " *" 479 << expr::attr< int >("Severity") << "* " 480 << expr::message; 481 482 logging::add_file_log("complete.log")->set_formatter(formatter); 483 484 boost::shared_ptr< 485 sinks::synchronous_sink< sinks::text_ostream_backend > 486 > sink = logging::add_file_log("essential.log"); 487 sink->set_formatter(formatter); 488 sink->set_filter(expr::attr< int >("Severity") >= 1); 489 490 // Register common attributes 491 logging::add_common_attributes(); 492 493 // Here we go, we can write logs 494 src::logger lg; 495 BOOST_LOG(lg) << "Hello world!"; 496 497 return 0; 498 } 499 500[endsect] 501 502[section:filter_formatter Filter and formatter parsers] 503 504 #include <``[boost_log_utility_setup_filter_parser_hpp]``> 505 #include <``[boost_log_utility_setup_formatter_parser_hpp]``> 506 507Filter and formatter parsers allow constructing filters and formatters from a descriptive string. The function `parse_filter` is responsible for recognizing filters and `parse_formatter` - for recognizing formatters. 508 509In the case of filters the string is formed of a sequence of condition expressions, interconnected with boolean operations. There are two operations supported: conjunction (designated as "&" or "and") and disjunction ("|" or "or"). Each condition itself may be either a single condition or a sub-filter, taken in round brackets. Each condition can be negated with the "!" sign or "not" keyword. The condition, if it's not a sub-filter, usually consists of an attribute name enclosed in percent characters ("%"), a relation keyword and an operand. The relation and operand may be omitted, in which case the condition is assumed to be the requirement of the attribute presence (with any type). 510 511[teletype] 512 513 filter: 514 condition { op condition } 515 516 op: 517 & 518 and 519 | 520 or 521 522 condition: 523 !condition 524 not condition 525 (filter) 526 %attribute_name% 527 %attribute_name% relation operand 528 529 relation: 530 > 531 < 532 = 533 != 534 >= 535 <= 536 begins_with 537 ends_with 538 contains 539 matches 540 541[c++] 542 543Below are some examples of filters: 544 545[table Examples of filters 546[[Filter string] [Description]] 547[[`%Severity%`] [The filter returns `true` if an attribute value with name "Severity" is found in a log record.]] 548[[`%Severity% > 3`] [The filter returns `true` if an attribute value with name "Severity" is found and it is greater than 3. The attribute value must be of one of the [link log.detailed.utilities.predef_types integral types].]] 549[[!(`%Ratio% > 0.0 & %Ratio% <= 0.5)`] [The filter returns `true` if an attribute value with name "Ratio" of one of the [link log.detailed.utilities.predef_types floating point types] is not found or it is not between 0 and 0.5.]] 550[[`%Tag% contains "net" or %Tag% contains "io" and not %StatFlow%`] [The filter returns `true` if an attribute value with name "Tag" is found and contains words "net" or "io" and if an attribute value "StatFlow" is not found. The "Tag" attribute value must be of one of the [link log.detailed.utilities.predef_types string types], the "StatFlow" attribute value type is not considered.]] 551] 552 553The formatter string syntax is even simpler and pretty much resembles __boost_format__ format string syntax. The string is interpreted as a template which can contain attribute names enclosed with percent signs ("%"). The corresponding attribute values will replace these placeholders when the formatter is applied. The placeholder "%Message%" will be replaced with the log record text. For instance, the following formatter string: 554 555[teletype] 556 557 [%TimeStamp%] *%Severity%* %Message% 558 559[c++] 560 561will make log records look like this: 562 563[teletype] 564 565 [2008-07-05 13:44:23] *0* Hello world 566 567[c++] 568 569[note Previous releases of the library also supported the "%\_%" placeholder for the message text. This placeholder is deprecated now, although it still works for backward compatibility. Its support will be removed in future releases.] 570 571It must be noted that by default the library only supports those attribute value types [link log.detailed.utilities.predef_types which are known] at the library build time. User-defined types will not work properly in parsed filters and formatters until registered in the library. It is also possible to override formatting rules of the known types, including support for additional formatting parameters in the string template. More on this is available in the [link log.extension.settings Extending the library] section. 572 573[note The parsed formatters and filters are generally less optimal than the equivalent ones written in code with [link log.detailed.expressions template expressions]. This is because of two reasons: (\*) the programmer usually knows more about types of the attribute values that may be involved in formatting or filtering and (\*) the compiler has a better chance to optimize the formatter or filter if it is known in compile time. Therefore, when performance matters, it is advised to avoid parsed filters and formatters.] 574 575[endsect] 576 577[section:settings Library initialization from a settings container] 578 579 #include <``[boost_log_utility_setup_settings_hpp]``> 580 #include <``[boost_log_utility_setup_from_settings_hpp]``> 581 582The headers define components for library initialization from a settings container. The settings container is basically a set of named parameters divided into sections. The container is implemented with the [class_log_basic_settings] class template. There are several constraints on how parameters are stored in the container: 583 584* Every parameter must reside in a section. There can be no parameters that do not belong to a section. 585* Parameters must have names unique within the section they belong to. Parameters from different sections may have the same name. 586* Sections can nest. When read from a file or accessed from the code, section names can express arbitrary hierarchy by separating the parent and child section names with '.' (e.g. "\[Parent.Child.ChildChild\]"). 587* Sections must have names unique within the enclosing section (or global scope, if the section is top level). 588 589So basically, settings container is a layered associative container, with string keys and values. In some respect it is similar to __boost_property_tree__, and in fact it supports construction from `boost::ptree`. The supported parameters are described below. 590 591[tip In the tables below, the `CharT` type denotes the character type that is used with the settings container.] 592 593[table Section "Core". Logging core settings. 594[[Parameter] [Format] [Description]] 595[[Filter] [Filter string as described [link log.detailed.utilities.setup.filter_formatter here]] 596 [Global filter to be installed to the core. If not specified, the global filter is not set.] 597] 598[[DisableLogging] ["true" or "false"] 599 [If `true`, results in calling `set_logging_enabled(false)` on the core. By default, value `false` is assumed.] 600] 601] 602 603Sink settings are divided into separate subsections within the common top-level section "Sinks" - one subsection for each sink. The subsection names denote a user-defined sink name. For example, "MyFile". 604 605[note Previous versions of the library also supported top-level sections starting with the "Sink:" prefix to describe sink parameters. This syntax is deprecated now, although it still works when parsing a settings file for backward compatibility. The parser will automatically put these sections under the "Sinks" top-level section in the resulting settings container. Support for this syntax will be removed in future releases.] 606 607[table Sections under the "Sinks" section. Common sink settings. 608[[Parameter] [Format] [Description]] 609[[Destination] [Sink target, see description] 610 [Sink backend type. Mandatory parameter. May have one of these values: [link log.detailed.sink_backends.text_ostream Console], [link log.detailed.sink_backends.text_file TextFile], [link log.detailed.sink_backends.syslog Syslog]. On Windows the following values are additionally supported: [link log.detailed.sink_backends.event_log SimpleEventLog], [link log.detailed.sink_backends.debugger Debugger]. Also, user-defined sink names may also be supported if registered by calling [funcref boost::log::register_sink_factory `register_sink_factory`]. See [link log.extension.settings.sinks this] section on how to add support for new sinks.] 611] 612[[Filter] [Filter string as described [link log.detailed.utilities.setup.filter_formatter here]] 613 [Sink-specific filter. If not specified, the filter is not set.] 614] 615[[Asynchronous] ["true" or "false"] 616 [If `true`, the [link log.detailed.sink_frontends.async asynchronous sink frontend] will be used. Otherwise the [link log.detailed.sink_frontends.sync synchronous sink frontend] will be used. By default, value `false` is assumed. In single-threaded builds this parameter is not used, as [link log.detailed.sink_frontends.unlocked unlocked sink frontend] is always used.] 617] 618] 619 620Besides the common settings that all sinks support, some sink backends also accept a number of specific parameters. These parameters should be specified in the same section. 621 622[table "Console" sink settings 623[[Parameter] [Format] [Description]] 624[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]] 625 [Log record formatter to be used by the sink. If not specified, the default formatter is used.] 626] 627[[AutoNewline] ["Disabled", "AlwaysInsert" or "InsertIfMissing"] 628 [Controls whether the backend should automatically insert a trailing newline after every log record, see [enumref boost::log::sinks::auto_newline_mode `auto_newline_mode`]. If not specified, the default value is "InsertIfMissing".] 629] 630[[AutoFlush] ["true" or "false"] 631 [Enables or disables the auto-flush feature of the backend. If not specified, the default value `false` is assumed.] 632] 633] 634 635[table "TextFile" sink settings 636[[Parameter] [Format] [Description]] 637[[FileName] [File name pattern] 638 [The active file name pattern for the sink backend. This parameter is mandatory.] 639] 640[[TargetFileName] [File name pattern] 641 [The target file name pattern for the sink backend. If not specified, active file name is preserved after rotation.] 642] 643[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]] 644 [Log record formatter to be used by the sink. If not specified, the default formatter is used.] 645] 646[[AutoNewline] ["Disabled", "AlwaysInsert" or "InsertIfMissing"] 647 [Controls whether the backend should automatically insert a trailing newline after every log record, see [enumref boost::log::sinks::auto_newline_mode `auto_newline_mode`]. If not specified, the default value is "InsertIfMissing".] 648] 649[[AutoFlush] ["true" or "false"] 650 [Enables or disables the auto-flush feature of the backend. If not specified, the default value `false` is assumed.] 651] 652[[Append] ["true" or "false"] 653 [Enables or disables [link log.detailed.sink_backends.text_file.appending appending] to the existing file instead of overwriting it. If not specified, the default value `false` is assumed.] 654] 655[[RotationSize] [Unsigned integer] 656 [File size, in bytes, upon which [link log.detailed.sink_backends.text_file.file_rotation file rotation] will be performed. If not specified, no size-based rotation will be made.] 657] 658[[RotationInterval] [Unsigned integer] 659 [Time interval, in seconds, upon which [link log.detailed.sink_backends.text_file.file_rotation file rotation] will be performed. See also the RotationTimePoint parameter and the note below.] 660] 661[[RotationTimePoint] [Time point format string, see below] 662 [Time point or a predicate that detects at what moment of time to perform log [link log.detailed.sink_backends.text_file.file_rotation file rotation]. See also the RotationInterval parameter and the note below.] 663] 664[[EnableFinalRotation] ["true" or "false"] 665 [Enables or disables final file rotation on sink destruction, which typically happens on program termination. If not specified, the default value `true` is assumed.] 666] 667[[Target] [File system path to a directory] 668 [Target directory name, in which the rotated files will be stored. If this parameter is specified, rotated [link log.detailed.sink_backends.text_file.file_collection file collection] is enabled. Otherwise the feature is not enabled and all corresponding parameters are ignored.] 669] 670[[MaxSize] [Unsigned integer] 671 [Total size of files in the target directory, in bytes, upon which the oldest file will be deleted. If not specified, no size-based file cleanup will be performed.] 672] 673[[MinFreeSpace] [Unsigned integer] 674 [Minimum free space in the target directory, in bytes, upon which the oldest file will be deleted. If not specified, no space-based file cleanup will be performed.] 675] 676[[MaxFiles] [Unsigned integer] 677 [Total number of files in the target directory, upon which the oldest file will be deleted. If not specified, no count-based file cleanup will be performed.] 678] 679[[ScanForFiles] ["All" or "Matching"] 680 [Mode of [link log.detailed.sink_backends.text_file.file_scanning scanning] for old files in the target directory, see [enumref boost::log::sinks::file::scan_method `scan_method`]. If not specified, no scanning will be performed.] 681] 682] 683 684[warning The text file sink uses __boost_filesystem__ internally, which may cause problems on process termination. See [link log.rationale.why_crash_on_term here] for more details.] 685 686The time-based rotation can be set up with one of the two parameters: RotationInterval or RotationTimePoint. Not more than one of these parameters should be specified for a given sink. If none is specified, no time-based rotation will be performed. 687 688The RotationTimePoint parameter should have one of the following formats, according to the __boost_date_time_format__ format notation: 689 690* "%H:%M:%S". In this case, file rotation will be performed on a daily basis, at the specified time. For example, "12:00:00". 691* "%a %H:%M:%S" or "%A %H:%M:%S". File rotation takes place every week, on the weekday specified in the long or short form, at the specified time. For example, "Saturday 09:00:00". 692* "%d %H:%M:%S". File rotation takes place every month, on the specified day of month, at the specified time. For example, "01 23:30:00". 693 694[table "Syslog" sink settings 695[[Parameter] [Format] [Description]] 696[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]] 697 [Log record formatter to be used by the sink. If not specified, the default formatter is used.] 698] 699[[LocalAddress] [An IP address] 700 [Local address to initiate connection to the syslog server. If not specified, the default local address will be used.] 701] 702[[TargetAddress] [An IP address] 703 [Remote address of the syslog server. If not specified, the local address will be used.] 704] 705] 706 707[table "SimpleEventLog" sink settings 708[[Parameter] [Format] [Description]] 709[[Format] [Format string as described [link log.detailed.utilities.setup.filter_formatter here]] 710 [Log record formatter to be used by the sink. If not specified, the default formatter is used.] 711] 712[[LogName] [A string] 713 [Log name to write events into. If not specified, the default log name will be used.] 714] 715[[LogSource] [A string] 716 [Log source to write events from. If not specified, the default source will be used.] 717] 718[[Registration] ["Never", "OnDemand" or "Forced"] 719 [Mode of log source registration in Windows registry, see [enumref boost::log::sinks::event_log::registration_mode `registration_mode`]. If not specified, on-demand registration will be performed.] 720] 721] 722 723The user is free to fill the settings container from whatever settings source he needs. The usage example is below: 724 725[example_util_setup_settings] 726 727[@boost:/libs/log/example/doc/util_setup_settings.cpp See the complete code]. 728 729[note Initialization from settings does not automatically create any attributes or loggers, the application developer is still responsible for creating those. It can be said that loggers and attributes define the data that is exported by the application and the settings only describe how that data is going to be presented to the application user.] 730 731The settings reader also can be extended to support custom sink types. See the [link log.extension.settings Extending the library] section for more information. 732 733[endsect] 734 735[section:settings_file Library initialization from a settings file] 736 737 #include <``[boost_log_utility_setup_from_stream_hpp]``> 738 739Support for configuration files is a frequently requested feature of the library. And despite the fact there is no ultimately convenient and flexible format of the library settings, the library provides preliminary support for this feature. The functionality is implemented with a simple function [funcref boost::log::init_from_stream `init_from_stream`], which accepts a `std::istream` and reads the library settings from it. The function then passes on the read settings to the [funcref boost::log::init_from_settings `init_from_settings`] function, described [link log.detailed.utilities.setup.settings above]. Therefore the parameter names and their meaning is the same as for the [funcref boost::log::init_from_settings `init_from_settings`] function. 740 741The settings format is quite simple and widely used. Below is the description of syntax and parameters. 742 743[teletype] 744 745 # Comments are allowed. Comment line begins with the '#' character 746 # and spans until the end of the line. 747 748 # Logging core settings section. May be omitted if no parameters specified within it. 749 [Core] 750 DisableLogging=false 751 Filter="%Severity% > 3" 752 753 # Sink settings sections 754 [Sinks.MySink1] 755 756 # Sink destination type 757 Destination=Console 758 759 # Sink-specific filter. Optional, by default no filter is applied. 760 Filter="%Target% contains \"MySink1\"" 761 762 # Formatter string. Optional, by default only log record message text is written. 763 Format="<%TimeStamp%> - %Message%" 764 765 # The flag shows whether the sink should be asynchronous 766 Asynchronous=false 767 768 # Enables automatic stream flush after each log record. 769 AutoFlush=true 770 771[c++] 772 773Here's the usage example: 774 775 int main(int, char*[]) 776 { 777 // Read logging settings from a file 778 std::ifstream file("settings.ini"); 779 logging::init_from_stream(file); 780 781 return 0; 782 } 783 784See a [@boost:/libs/log/example/settings_file/main.cpp more complete example]. 785 786[endsect] 787 788[endsect] 789 790[endsect] 791