]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/doc/expressions.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / log / doc / expressions.qbk
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:expressions Lambda expressions]
11
12 As it was pointed out in [link log.tutorial tutorial], filters and formatters can be specified as Lambda expressions with placeholders for attribute values. This section will describe the placeholders that can be used to build more complex Lambda expressions.
13
14 There is also a way to specify the filter in the form of a string template. This can be useful for initialization from the application settings. This part of the library is described [link log.detailed.utilities.setup.filter_formatter here].
15
16 [section:attr Generic attribute placeholder]
17
18 #include <``[boost_log_expressions_attr_fwd_hpp]``>
19 #include <``[boost_log_expressions_attr_hpp]``>
20
21 The [funcref boost::log::expressions::attr attr] placeholder represents an attribute value in template expressions. Given the record view or a set of attribute values, the placeholder will attempt to extract the specified attribute value from the argument upon invocation. This can be roughly described with the following pseudo-code:
22
23 logging::value_ref< T, TagT > val = expr::attr< T, TagT >(name)(rec);
24
25 where `val` is the [link log.detailed.utilities.value_ref reference] to the extracted value, `name` and `T` are the attribute value [link log.detailed.attributes.related_components.attribute_name name] and type, `TagT` is an optional tag (we'll return to it in a moment) and `rec` is the log [link log.detailed.core.record record view] or [link log.detailed.attributes.related_components.attribute_value_set attribute value set]. `T` can be a __boost_mpl__ type sequence with possible expected types of the value; the extraction will succeed if the type of the value matches one of the types in the sequence.
26
27 The `attr` placeholder can be used in __boost_phoenix__ expressions, including the `bind` expression.
28
29 [example_tutorial_filtering_bind]
30
31 The placeholder can be used both in filters and formatters:
32
33 sink->set_filter
34 (
35 expr::attr< int >("Severity") >= 5 &&
36 expr::attr< std::string >("Channel") == "net"
37 );
38
39 sink->set_formatter
40 (
41 expr::stream
42 << expr::attr< int >("Severity")
43 << " [" << expr::attr< std::string >("Channel") << "] "
44 << expr::smessage
45 );
46
47 The call to `set_filter` registers a composite filter that consists of two elementary subfilters: the first one checks the severity level, and the second checks the channel name. The call to `set_formatter` installs a formatter that composes a string containing the severity level and the channel name along with the message text.
48
49 [section:fallback_policies Customizing fallback policy]
50
51 By default, when the requested attribute value is not found in the record, `attr` will return an empty reference. In case of filters, this will result in `false` in any ordering expressions, and in case of formatters the output from the placeholder will be empty. This behavior can be changed:
52
53 * To throw an exception ([class_log_missing_value] or [class_log_invalid_type], depending on the reason of the failure). Add the `or_throw` modifier:
54
55 sink->set_filter
56 (
57 expr::attr< int >("Severity").or_throw() >= 5 &&
58 expr::attr< std::string >("Channel").or_throw() == "net"
59 );
60
61 * To use a default value instead. Add the `or_default` modifier with the desired default value:
62
63 sink->set_filter
64 (
65 expr::attr< int >("Severity").or_default(0) >= 5 &&
66 expr::attr< std::string >("Channel").or_default(std::string("general")) == "net"
67 );
68
69 [tip You can also use the [link log.detailed.expressions.predicates.has_attr `has_attr`] predicate to implement filters and formatters conditional on the attribute value presence.]
70
71 The default behavior is also accessible through the `or_none` modifier. The modified placeholders can be used in filters and formatters just the same way as the unmodified ones.
72
73 In `bind` expressions, the bound function object will still receive the [link log.detailed.utilities.value_ref `value_ref`]-wrapped values in place of the modified `attr` placeholder. Even though both `or_throw` and `or_default` modifiers guarantee that the bound function will receive a filled reference, [link log.detailed.utilities.value_ref `value_ref`] is still needed if the value type is specified as a type sequence. Also, the reference wrapper may contain a tag type which may be useful for formatting customization.
74
75 [endsect]
76
77 [section:tags Attribute tags and custom formatting operators]
78
79 The `TagT` type in the [link log.detailed.expressions.attr abstract description] of `attr` above is optional and by default is `void`. This is an attribute tag which can be used to customize the output formatters produce for different attributes. This tag is forwarded to the [link log.detailed.utilities.manipulators.to_log `to_log`] manipulator when the extracted attribute value is put to a stream (this behavior is warranted by [link log.detailed.utilities.value_ref `value_ref`] implementation). Here's a quick example:
80
81 [example_expressions_attr_formatter_stream_tag]
82
83 [@boost:/libs/log/example/doc/expressions_attr_fmt_tag.cpp See the complete code].
84
85 Here we specify a different formatting operator for the severity level wrapped in the [link log.detailed.utilities.manipulators.to_log `to_log_manip`] manipulator marked with the tag `severity_tag`. This operator will be called when log records are formatted while the regular `operator<<` will be used in other contexts.
86
87 [endsect]
88
89 [endsect]
90
91 [section:attr_keywords Defining attribute keywords]
92
93 #include <``[boost_log_expressions_keyword_fwd_hpp]``>
94 #include <``[boost_log_expressions_keyword_hpp]``>
95
96 Attribute keywords can be used as replacements for the [link log.detailed.expressions.attr `attr`] placeholders in filters and formatters while providing a more concise and less error prone syntax. An attribute keyword can be declared with the [macroref BOOST_LOG_ATTRIBUTE_KEYWORD] macro:
97
98 BOOST_LOG_ATTRIBUTE_KEYWORD(keyword, "Keyword", type)
99
100 Here the macro declares a keyword `keyword` for an attribute named "Keyword" with the value type of `type`. Additionally, the macro defines an attribute tag type `keyword` within the `tag` namespace. We can rewrite the previous example in the following way:
101
102 [example_expressions_keyword_formatter_stream_tag]
103
104 Attribute keywords behave the same way as the [link log.detailed.expressions.attr `attr`] placeholders and can be used both in filters and formatters. The `or_throw` and `or_default` modifiers are also supported.
105
106 Keywords can also be used in attribute value lookup expressions in log records and attribute value sets:
107
108 [example_expressions_keyword_lookup]
109
110 [endsect]
111
112 [section:record Record placeholder]
113
114 #include <``[boost_log_expressions_record_hpp]``>
115
116 The `record` placeholder can be used in `bind` expressions to pass the whole log [link log.detailed.core.record record view] to the bound function object.
117
118 void my_formatter(logging::formatting_ostream& strm, logging::record_view const& rec)
119 {
120 // ...
121 }
122
123 namespace phoenix = boost::phoenix;
124 sink->set_formatter(phoenix::bind(&my_formatter, expr::stream, expr::record));
125
126 [note In case of filters, the placeholder will correspond to the [link log.detailed.attributes.related_components.attribute_value_set set of attribute values] rather than the log record itself. This is because the record is not constructed yet at the point of filtering, and filters only operate on the set of attribute values.]
127
128 [endsect]
129
130 [section:message Message text placeholders]
131
132 #include <``[boost_log_expressions_message_hpp]``>
133
134 Log records typically contain a special attribute "Message" with the value of one of the string types (more specifically, an `std::basic_string` specialization). This attribute contains the text of the log message that is constructed at the point of the record creation. This attribute is only constructed after filtering, so filters cannot use it. There are several keywords to access this attribute value:
135
136 * `smessage` - the attribute value is expected to be an `std::string`
137 * `wmessage` - the attribute value is expected to be an `std::wstring`
138 * `message` - the attribute value is expected to be an `std::string` or `std::wstring`
139
140 The `message` keyword has to dispatch between different string types, so it is slightly less efficient than the other two keywords. If the application is able to guarantee the fixed character type of log messages, it is advised to use the corresponding keyword for better performance.
141
142 // Sets up a formatter that will ignore all attributes and only print log record text
143 sink->set_formatter(expr::stream << expr::message);
144
145 [endsect]
146
147 [section:predicates Predicate expressions]
148
149 This section describes several expressions that can be used as predicates in the filtering expressions.
150
151 [section:has_attr Attribute presence filter]
152
153 #include <``[boost_log_expressions_predicates_has_attr_hpp]``>
154
155 The filter [funcref boost::log::expressions::has_attr `has_attr`] checks if an attribute value with the specified name and, optionally, type is attached to a log record. If no type specified to the filter, the filter returns `true` if any value with the specified name is found. If an MPL-compatible type sequence in specified as a value type, the filter returns `true` if a value with the specified name and one of the specified types is found.
156
157 This filter is usually used in conjunction with [link log.detailed.expressions.formatters.conditional conditional formatters], but it also can be used as a quick filter based on the log record structure. For example, one can use this filter to extract statistic records and route them to a specific sink.
158
159 [example_expressions_has_attr_stat_accumulator]
160
161 [@boost:/libs/log/example/doc/expressions_has_attr_stat_accum.cpp See the complete code].
162
163 In this example, log records emitted with the `PUT_STAT` macro will be directed to the `my_stat_accumulator` sink backend, which will accumulate the changes passed in the "Change" attribute values. All other records (even those made through the same logger) will be passed to the filter sink. This is achieved with the mutually exclusive filters set for the two sinks.
164
165 Please note that in the example above we extended the library in two ways: we defined a new sink backend `my_stat_accumulator` and a new macro `PUT_STAT`. Also note that `has_attr` can accept attribute keywords to identify the attribute to check.
166
167 [endsect]
168
169 [section:is_in_range Range checking filter]
170
171 #include <``[boost_log_expressions_predicates_is_in_range_hpp]``>
172
173 The [funcref boost::log::expressions::is_in_range `is_in_range`] predicate checks that the attribute value fits in the half-open range (i.e. it returns `true` if the attribute value `x` satisfies the following condition: `left <= x < right`). For example:
174
175 sink->set_filter
176 (
177 // drops all records that have level below 3 or greater than 4
178 expr::is_in_range(expr::attr< int >("Severity"), 3, 5)
179 );
180
181 The attribute can also be identified by an attribute keyword or name and type:
182
183 sink->set_filter
184 (
185 expr::is_in_range(severity, 3, 5)
186 );
187
188 sink->set_filter
189 (
190 expr::is_in_range< int >("Severity", 3, 5)
191 );
192
193 [endsect]
194
195 [section:simple_string_matching Simple string matching filters]
196
197 #include <``[boost_log_expressions_predicates_begins_with_hpp]``>
198 #include <``[boost_log_expressions_predicates_ends_with_hpp]``>
199 #include <``[boost_log_expressions_predicates_contains_hpp]``>
200
201 Predicates [funcref boost::log::expressions::begins_with `begins_with`], [funcref boost::log::expressions::ends_with `ends_with`] and [funcref boost::log::expressions::contains `contains`] provide an easy way of matching string attribute values. As follows from their names, the functions construct filters that return `true` if an attribute value begins with, ends with or contains the specified substring, respectively. The string comparison is case sensitive.
202
203 sink->set_filter
204 (
205 // selects only records that are related to Russian web domains
206 expr::ends_with(expr::attr< std::string >("Domain"), ".ru")
207 );
208
209 The attribute can also be identified by an attribute keyword or name and type.
210
211 [endsect]
212
213 [section:advanced_string_matching Advanced string matching filter]
214
215 #include <``[boost_log_expressions_predicates_matches_hpp]``>
216
217 // Supporting headers
218 #include <``[boost_log_support_regex_hpp]``>
219 #include <``[boost_log_support_std_regex_hpp]``>
220 #include <``[boost_log_support_xpressive_hpp]``>
221 #include <``[boost_log_support_spirit_qi_hpp]``>
222 #include <``[boost_log_support_spirit_classic_hpp]``>
223
224 The [funcref boost::log::expressions::matches `matches`] function creates a filter that apples a regular expression or a parser to a string attribute value. The regular expression can be provided by __boost_regex__ or __boost_xpressive__. Parsers from __boost_spirit__ and __boost_spirit2__ are also supported. The filter returns `true` if the regular expression matches or the parser successfully parses the attribute value.
225
226 [note In order to use this predicate, a corresponding supporting header should also be included.]
227
228 sink->set_filter
229 (
230 expr::matches(expr::attr< std::string >("Domain"), boost::regex("www\\..*\\.ru"))
231 );
232
233 The attribute can also be identified by an attribute keyword or name and type.
234
235 [endsect]
236
237 [section:channel_severity_filter Severity threshold per channel filter]
238
239 #include <``[boost_log_expressions_predicates_channel_severity_filter_hpp]``>
240
241 This filter is aimed for a specific but commonly encountered use case. The [funcref boost::log::expressions::channel_severity_filter `channel_severity_filter`] function creates a predicate that will check log record severity levels against a threshold. The predicate allows setting different thresholds for different channels. The mapping between channel names and severity thresholds can be filled in `std::map` style by using the subscript operator or by calling `add` method on the filter itself (the [class_expressions_channel_severity_filter_actor] instance). Let's see an example:
242
243 [example_expressions_channel_severity_filter]
244
245 [@boost:/libs/log/example/doc/expressions_channel_severity_filter.cpp See the complete code].
246
247 The filter for the console sink is composed from the [class_expressions_channel_severity_filter_actor] filter and a general severity level check. This general check will be used when log records do not have a channel attribute or the channel name is not one of those specified in [class_expressions_channel_severity_filter_actor] initialization. It should be noted that it is possible to set the default result of the threshold filter that will be used in this case; the default result can be set by the `set_default` method. The [class_expressions_channel_severity_filter_actor] filter is set up to limit record severity levels for channels "general", "network" and "gui" - all records in these channels with levels below the specified thresholds will not pass the filter and will be ignored.
248
249 The threshold filter is implemented as an equivalent to `std::map` over the channels, which means that the channel value type must support partial ordering. Obviously, the severity level type must also support ordering to be able to be compared against thresholds. By default the predicate will use `std::less` equivalent for channel name ordering and `std::greater_equal` equivalent to compare severity levels. It is possible to customize the ordering predicates. Consult the reference of the [class_expressions_channel_severity_filter_actor] class and [funcref boost::log::expressions::channel_severity_filter `channel_severity_filter`] generator to see the relevant template parameters.
250
251 [endsect]
252
253 [section:is_debugger_present Debugger presence filter]
254
255 #include <``[boost_log_expressions_predicates_is_debugger_present_hpp]``>
256
257 This filter is implemented for Windows only. The `is_debugger_present` filter returns `true` if the application is run under a debugger and `false` otherwise. It does not use any attribute values from the log record. This predicate is typically used with the [link log.detailed.sink_backends.debugger debugger output] sink.
258
259 [example_sinks_debugger]
260
261 [@boost:/libs/log/example/doc/sinks_debugger.cpp See the complete code].
262
263 [endsect]
264
265 [endsect]
266
267 [section:formatters Formatting expressions]
268
269 As was noted in the [link log.tutorial.formatters tutorial], the library provides several ways of expressing formatters, most notable being with a stream-style syntax and __boost_format__-style expression. Which of the two formats is chosen is determined by the appropriate anchor expression. To use stream-style syntax one should begin the formatter definition with the `stream` keyword, like that:
270
271 #include <``[boost_log_expressions_formatters_stream_hpp]``>
272
273 sink->set_formatter(expr::stream << expr1 << expr2 << ... << exprN);
274
275 Here expressions `expr1` through `exprN` may be either manipulators, described in this section, or other expressions resulting in an object that supports putting into an STL-stream.
276
277 To use __boost_format__-style syntax one should use `format` construct:
278
279 #include <``[boost_log_expressions_formatters_format_hpp]``>
280
281 sink->set_formatter(expr::format("format string") % expr1 % expr2 % ... % exprN);
282
283 The format string passed to the `format` keyword should contain positional placeholders for the appropriate expressions. In the case of wide-character logging the format string should be wide. Expressions `expr1` through `exprN` have the same meaning as in stream-like variant. It should be noted though that using stream-like syntax usually results in a faster formatter than the one constructed with the `format` keyword.
284
285 Another useful way of expressing formatters is by using string templates. This part of the library is described in [link log.detailed.utilities.setup.filter_formatter this] section and is mostly intended to support initialization from the application settings.
286
287 [section:date_time Date and time formatter]
288
289 #include <``[boost_log_expressions_formatters_date_time_hpp]``>
290
291 // Supporting headers
292 #include <``[boost_log_support_date_time_hpp]``>
293
294 The library provides the [funcref boost::log::expressions::format_date_time `format_date_time`] formatter dedicated to date and time-related attribute value types. The function accepts the attribute value name and the format string compatible with __boost_date_time__.
295
296 sink->set_formatter
297 (
298 expr::stream << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
299 );
300
301 The attribute value can alternatively be identified with the [link log.detailed.expressions.attr `attr`] placeholder or the [link log.detailed.expressions.attr_keywords attribute keyword].
302
303 The following placeholders are supported in the format string:
304
305 [table Date format placeholders
306 [[Placeholder][Meaning][Example]]
307 [[%a] [Abbreviated weekday name]["Mon" => Monday]]
308 [[%A] [Long weekday name]["Monday"]]
309 [[%b] [Abbreviated month name]["Feb" => February]]
310 [[%B] [Long month name]["February"]]
311 [[%d] [Numeric day of month with leading zero]["01"]]
312 [[%e] [Numeric day of month with leading space][" 1"]]
313 [[%m] [Numeric month, 01-12]["01"]]
314 [[%w] [Numeric day of week, 1-7]["1"]]
315 [[%y] [Short year]["12" => 2012]]
316 [[%Y] [Long year]["2012"]]
317 ]
318
319 [table Time format placeholders
320 [[Placeholder][Meaning][Example]]
321 [[%f] [Fractional seconds with leading zeros]["000231"]]
322 [[%H, %O] [Hours in 24 hour clock or hours in time duration types with leading zero if less than 10]["07"]]
323 [[%I] [Hours in 12 hour clock with leading zero if less than 10]["07"]]
324 [[%k] [Hours in 24 hour clock or hours in time duration types with leading space if less than 10][" 7"]]
325 [[%l] [Hours in 12 hour clock with leading space if less than 10][" 7"]]
326 [[%M] [Minutes]["32"]]
327 [[%p] [AM/PM mark, uppercase]["AM"]]
328 [[%P] [AM/PM mark, lowercase]["am"]]
329 [[%q] [ISO time zone]["-0700" => Mountain Standard Time]]
330 [[%Q] [Extended ISO time zone]["-05:00" => Eastern Standard Time]]
331 [[%S] [Seconds]["26"]]
332 ]
333
334 [table Miscellaneous placeholders
335 [[Placeholder][Meaning][Example]]
336 [[%-] [Negative sign in case of time duration, if the duration is less than zero]["-"]]
337 [[%+] [Sign of time duration, even if positive]["+"]]
338 [[%%] [An escaped percent sign]["%"]]
339 [[%T] [Extended ISO time, equivalent to "%H:%M:%S"]["07:32:26"]]
340 ]
341
342 Note that in order to use this formatter you will also have to include a supporting header. When [boost_log_support_date_time_hpp] is included, the formatter supports the following types of __boost_date_time__:
343
344 * Date and time types: `boost::posix_time::ptime` and `boost::local_time::local_date_time`.
345 * Gregorian date type: `boost::gregorian::date`.
346 * Time duration types: `boost::posix_time::time_duration` as well as all the specialized time units such as `boost::posix_time::seconds`, including subsecond units.
347 * Date duration types: `boost::gregorian::date_duration`.
348
349 [tip __boost_date_time__ already provides formatting functionality implemented as a number of locale facets. This functionality can be used instead of this formatter, although the formatter is expected to provide better performance.]
350
351 [endsect]
352
353 [section:named_scope Named scope formatter]
354
355 #include <``[boost_log_expressions_formatters_named_scope_hpp]``>
356
357 The formatter [funcref boost::log::expressions::format_named_scope `format_named_scope`] is intended to add support for flexible formatting of the [link log.detailed.attributes.named_scope named scope] attribute values. The basic usage is quite straightforward and its result is similar to what [link log.detailed.expressions.attr `attr`] provides:
358
359 // Puts the scope stack from outer ones towards inner ones: outer scope -> inner scope
360 sink->set_formatter(expr::stream << expr::format_named_scope("Scopes", "%n"));
361
362 The first argument names the attribute and the second is the format string. The string can contain the following placeholders:
363
364 [table Named scope format placeholders
365 [[Placeholder][Meaning][Example]]
366 [[%n] [Scope name]["void bar::foo()"]]
367 [[%c] [Function name, if the scope is denoted with `BOOST_LOG_FUNCTION`, otherwise the full scope name. See the note below.]["bar::foo"]]
368 [[%C] [Function name, without the function scope, if the scope is denoted with `BOOST_LOG_FUNCTION`, otherwise the full scope name. See the note below.]["foo"]]
369 [[%f] [Source file name of the scope]["/home/user/project/foo.cpp"]]
370 [[%F] [Source file name of the scope, without the path]["foo.cpp"]]
371 [[%l] [Line number in the source file]["45"]]
372 ]
373
374 [note As described in the [link log.detailed.attributes.named_scope named scope] attribute description, it is possible to use `BOOST_LOG_FUNCTION` macro to automatically generate scope names from the enclosing function name. Unfortunately, the actual format of the generated strings is compiler-dependent and in many cases it includes the complete signature of the function. When "%c" or "%C" format flag is specified, the library attempts to parse the generated string to extract the function name. Since C++ syntax is very context dependent and complex, it is not possible to parse function signature correctly in all cases, so the library is basically guessing. Depending on the string format, this may fail or produce incorrect results. In particular, type conversion operators can pose problems for the parser. In case if the parser fails to recognize the function signature the library falls back to using the whole string (i.e. behave equivalent to the "%n" flag). To alleviate the problem the user can replace the problematic `BOOST_LOG_FUNCTION` usage with the `BOOST_LOG_NAMED_SCOPE` macro and explicitly write the desired scope name. Scope names denoted with `BOOST_LOG_NAMED_SCOPE` will not be interpreted by the library and will be output as is. In general, for portability and runtime performance reasons it is preferable to always use `BOOST_LOG_NAMED_SCOPE` and "%n" format flag.]
375
376 While the format string describes the presentation of each named scope in the list, the following named arguments allow to customize the list traversal and formatting:
377
378 * `format`. The named scope format string, as described above. This parameter is used to specify the format when other named parameters are used.
379 * `iteration`. The argument describes the direction of iteration through scopes. Can have values `forward` (default) or `reverse`.
380 * `delimiter`. The argument can be used to specify the delimiters between scopes. The default delimiter depends on the `iteration` argument. If `iteration == forward` the default `delimiter` will be "->", otherwise it will be "<-".
381 * `depth`. The argument can be used to limit the number of scopes to put to log. The formatter will print `depth` innermost scopes and, if there are more scopes left, append an ellipsis to the written sequence. By default the formatter will write all scope names.
382 * `incomplete_marker`. The argument can be used to specify the string that is used to indicate that the list has been limited by the `depth` argument. By default the "..." string is used as the marker.
383 * `empty_marker`. The argument can be used to specify the string to output in case if the scope list is empty. By default nothing is output in this case.
384
385 Here are a few usage examples:
386
387 // Puts the scope stack in reverse order:
388 // inner scope (file:line) <- outer scope (file:line)
389 sink->set_formatter
390 (
391 expr::stream
392 << expr::format_named_scope(
393 "Scopes",
394 keywords::format = "%n (%f:%l)",
395 keywords::iteration = expr::reverse)
396 );
397
398 // Puts the scope stack in reverse order with a custom delimiter:
399 // inner scope | outer scope
400 sink->set_formatter
401 (
402 expr::stream
403 << expr::format_named_scope(
404 "Scopes",
405 keywords::format = "%n",
406 keywords::iteration = expr::reverse,
407 keywords::delimiter = " | ")
408 );
409
410 // Puts the scope stack in forward order, no more than 2 inner scopes:
411 // ... outer scope -> inner scope
412 sink->set_formatter
413 (
414 expr::stream
415 << expr::format_named_scope(
416 "Scopes",
417 keywords::format = "%n",
418 keywords::iteration = expr::forward,
419 keywords::depth = 2)
420 );
421
422 // Puts the scope stack in reverse order, no more than 2 inner scopes:
423 // inner scope <- outer scope <<and more>>...
424 sink->set_formatter
425 (
426 expr::stream
427 << expr::format_named_scope(
428 "Scopes",
429 keywords::format = "%n",
430 keywords::iteration = expr::reverse,
431 keywords::incomplete_marker = " <<and more>>..."
432 keywords::depth = 2)
433 );
434
435 [tip An empty string can be specified as the `incomplete_marker` parameter, in which case there will be no indication that the list was truncated.]
436
437 [endsect]
438
439 [section:conditional Conditional formatters]
440
441 #include <``[boost_log_expressions_formatters_if_hpp]``>
442
443 There are cases when one would want to check some condition about the log record and format it depending on that condition. One example of such a need is formatting an attribute value depending on its runtime type. The general syntax of the conditional formatter is as follows:
444
445 expr::if_ (filter)
446 [
447 true_formatter
448 ]
449 .else_
450 [
451 false_formatter
452 ]
453
454 Those familiar with __boost_phoenix__ lambda expressions will find this syntax quite familiar. The `filter` argument is a filter that is applied to the record being formatted. If it returns `true`, the `true_formatter` is executed, otherwise `false_formatter` is executed. The `else_` section with `false_formatter` is optional. If it is omitted and `filter` yields `false`, no formatter is executed. Here is an example:
455
456 sink->set_formatter
457 (
458 expr::stream
459 // First, put the current time
460 << expr::format_date_time("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " "
461 << expr::if_ (expr::has_attr< int >("ID"))
462 [
463 // if "ID" is present then put it to the record
464 expr::stream << expr::attr< int >("ID")
465 ]
466 .else_
467 [
468 // otherwise put a missing marker
469 expr::stream << "--"
470 ]
471 // and after that goes the log record text
472 << " " << expr::message
473 );
474
475 [endsect]
476
477 [section:decorators Character decorators]
478
479 There are times when one would like to additionally post-process the composed string before passing it to the sink backend. For example, in order to store log into an XML file the formatted log record should be checked for special characters that have a special meaning in XML documents. This is where decorators step in.
480
481 [note Unlike most other formatters, decorators are dependent on the character type of the formatted output and this type cannot be deduced from the decorated formatter. By default, the character type is assumed to be `char`. If the formatter is used to compose a wide-character string, prepend the decorator name with the `w` letter (e.g. use `wxml_decor` instead of `xml_decor`). Also, for each decorator there is a generator function that accepts the character type as a template parameter; the function is named similarly to the decorator prepended with the `make_` prefix (e.g. `make_xml_decor`).]
482
483 [section:xml XML character decorator]
484
485 #include <``[boost_log_expressions_formatters_xml_decorator_hpp]``>
486
487 This decorator replaces XML special characters (&, <, >, \" and \') with the corresponding tokens (`&amp;`, `&lt;`, `&gt;`, `&quot;` and `&apos;`, correspondingly). The usage is as follows:
488
489 xml_sink->set_formatter
490 (
491 // Apply the decoration to the whole formatted record
492 expr::stream << expr::xml_decor
493 [
494 expr::stream << expr::message
495 ]
496 );
497
498 Since character decorators are yet another kind of formatters, it's fine to use them in other contexts where formatters are appropriate. For example, this is also a valid example:
499
500 xml_sink->set_formatter
501 (
502 expr::format("<message>%1%: %2%</message>")
503 % expr::attr< unsigned int >("LineID")
504 % expr::xml_decor[ expr::stream << expr::message ]; // Only decorate the message text
505 );
506
507 There is an example of the library set up for logging into an XML file, see [@boost:/libs/log/example/doc/sinks_xml_file.cpp here].
508
509 [endsect]
510
511 [section:csv CSV character decorator]
512
513 #include <``[boost_log_expressions_formatters_csv_decorator_hpp]``>
514
515 This decorator allows to ensure that the resulting string conforms to the [@http://en.wikipedia.org/wiki/Comma-separated_values CSV] format requirements. In particular, it duplicates the quote characters in the formatted string.
516
517 csv_sink->set_formatter
518 (
519 expr::stream
520 << expr::attr< unsigned int >("LineID") << ","
521 << expr::csv_decor[ expr::stream << expr::attr< std::string >("Tag") ] << ","
522 << expr::csv_decor[ expr::stream << expr::message ]
523 );
524
525 [endsect]
526
527 [section:c C-style character decorators]
528
529 #include <``[boost_log_expressions_formatters_c_decorator_hpp]``>
530
531 The header defines two character decorators: `c_decor` and `c_ascii_decor`. The first one replaces the following characters with their escaped counterparts: \\ (backslash, 0x5c), \\a (bell character, 0x07), \\b (backspace, 0x08), \\f (formfeed, 0x0c), \\n (newline, 0x0a), \\r (carriage return, 0x0d), \\t (horizontal tabulation, 0x09), \\v (vertical tabulation, 0x0b), \' (apostroph, 0x27), \" (quote, 0x22), ? (question mark, 0x3f). The `c_ascii_decor` decorator does the same but also replaces all other non-printable and non-ASCII characters with escaped hexadecimal character codes in C notation (e.g. "\\x8c"). The usage is similar to other character decorators:
532
533 sink->set_formatter
534 (
535 expr::stream
536 << expr::attr< unsigned int >("LineID") << ": ["
537 << expr::c_decor[ expr::stream << expr::attr< std::string >("Tag") ] << "] "
538 << expr::c_ascii_decor[ expr::stream << expr::message ]
539 );
540
541 [endsect]
542
543 [section:char General character decorator]
544
545 #include <``[boost_log_expressions_formatters_char_decorator_hpp]``>
546
547 This decorator allows the user to define his own character replacement mapping in one of the two forms. The first form is a range of `std::pair`s of strings (which can be C-style strings or ranges of characters, including `std::string`s). The strings in the `first` elements of pairs will be replaced with the `second` elements of the corresponding pair.
548
549 std::array< std::pair< const char*, const char* >, 3 > shell_escapes =
550 {
551 { "\"", "\\\"" },
552 { "'", "\\'" },
553 { "$", "\\$" }
554 };
555
556 sink->set_formatter
557 (
558 expr::stream << expr::char_decor(shell_escapes)
559 [
560 expr::stream << expr::message
561 ]
562 );
563
564 The second form is two same-sized sequences of strings; the first containing the search patterns and the second - the corresponding replacements.
565
566 std::array< const char*, 3 > shell_patterns =
567 {
568 "\"", "'", "$"
569 };
570 std::array< const char*, 3 > shell_replacements =
571 {
572 "\\\"", "\\'", "\\$"
573 };
574
575 sink->set_formatter
576 (
577 expr::stream << expr::char_decor(shell_patterns, shell_replacements)
578 [
579 expr::stream << expr::message
580 ]
581 );
582
583 In both cases the patterns are not interpreted and are sought in the formatted characters in the original form.
584
585 [endsect]
586
587 [section:max_size String length limiting decorator]
588
589 #include <``[boost_log_expressions_formatters_max_size_decorator_hpp]``>
590
591 Sometimes it can be useful to be able to limit the size of the output of a formatter or its part. For example, the limit might be imposed by the sink or the required output format. The `max_size_decor` decorator allows to enforce such limit. Let's see a simple example:
592
593 sink->set_formatter
594 (
595 expr::stream << expr::max_size_decor< char >(20)
596 [
597 expr::stream << expr::message
598 ]
599 );
600
601 [note The explicit template parameter for `max_size_decor` specifies the character type that is used by formatter. In this example the string produced by the formatter contains characters of type `char`, hence the template parameter.]
602
603 In this example the decorator limits the log message to no more than 20 [@https://en.wikipedia.org/wiki/Character_encoding#Terminology code units] of type `char` and removes the rest from the output. So if we had a log record like this:
604
605 BOOST_LOG(lg) << "The quick brown fox jumps over the lazy dog";
606
607 the resulting output would look like this:
608
609 [pre
610 The quick brown fox
611 ]
612
613 However, looking at this output in a log file it is unclear whether the original output contained anything else. One might want to indicate the fact of message truncation, should one occur. For that purpose the decorator allows to specify an overflow marker that will be placed at the end of the truncated output, if the truncation took place. We can modify the above example like this:
614
615 sink->set_formatter
616 (
617 expr::stream << expr::max_size_decor(20, ">>>")
618 [
619 expr::stream << expr::message
620 ]
621 );
622
623 [tip The formatter character type is deduced from the character type of the overflow marker, so it can be omitted.]
624
625 Now our log record will look like this in the output:
626
627 [pre
628 The quick brown f>>>
629 ]
630
631 This output makes it more obvious that there was more to the original message. Note also that the length of the output is still 20 characters; the marker replaced the last characters of the truncated output.
632
633 [tip For the character truncation and marker positioning to work correctly in multibyte encodings, it is important that the locale used by the formatter is set up properly. In particular, the `std::codecvt` facet in the locale must correctly recognize multibyte sequences corresponding to a single character in the output. One can use __boost_locale__ to generate the locale and then install it in the sink frontend by calling `imbue` (see [class_sinks_basic_formatting_sink_frontend] for reference). If the output character type is `wchar_t`, `char16_t` or `char32_t` the library assumes that the output is encoded in UTF-16 or UTF-32, depending on the size of the character type. Because the truncation might occur in the middle of a multi-unit character, truncated output produced by the decorator can be slightly shorter than the specified limit sometimes.]
634
635 As with any other formatter, `max_size_decor` can participate in more complex formatting expressions and limit length of only part of the message.
636
637 sink->set_formatter
638 (
639 expr::stream
640 << expr::format_date_time("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
641 << expr::max_size_decor(20, ">>>")
642 [
643 expr::stream << expr::message
644 ]
645 << "]"
646 );
647
648 The above formatter can produce output like this:
649
650 [pre
651 2016-08-10 00:36:44.028473 \[The quick brown f>>>\]
652 ]
653
654 [endsect]
655
656 [endsect]
657
658 [endsect]
659
660 [endsect]