• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Filtering revisited</title>
5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Log v2">
8<link rel="up" href="../tutorial.html" title="Tutorial">
9<link rel="prev" href="formatters.html" title="Log record formatting">
10<link rel="next" href="wide_char.html" title="Wide character logging">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td></tr></table>
14<hr>
15<div class="spirit-nav">
16<a accesskey="p" href="formatters.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="wide_char.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
17</div>
18<div class="section">
19<div class="titlepage"><div><div><h3 class="title">
20<a name="log.tutorial.advanced_filtering"></a><a class="link" href="advanced_filtering.html" title="Filtering revisited">Filtering revisited</a>
21</h3></div></div></div>
22<p>
23        We've already touched filtering in the previous sections but we barely scratched
24        the surface. Now that we are able to add attributes to log records and set
25        up sinks, we can build however complex filtering we need. Let's consider
26        this example:
27      </p>
28<p>
29</p>
30<pre class="programlisting"><span class="identifier">BOOST_LOG_ATTRIBUTE_KEYWORD</span><span class="special">(</span><span class="identifier">line_id</span><span class="special">,</span> <span class="string">"LineID"</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">)</span>
31<span class="identifier">BOOST_LOG_ATTRIBUTE_KEYWORD</span><span class="special">(</span><span class="identifier">severity</span><span class="special">,</span> <span class="string">"Severity"</span><span class="special">,</span> <span class="identifier">severity_level</span><span class="special">)</span>
32<span class="identifier">BOOST_LOG_ATTRIBUTE_KEYWORD</span><span class="special">(</span><span class="identifier">tag_attr</span><span class="special">,</span> <span class="string">"Tag"</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">)</span>
33
34<span class="keyword">void</span> <span class="identifier">init</span><span class="special">()</span>
35<span class="special">{</span>
36    <span class="comment">// Setup the common formatter for all sinks</span>
37    <span class="identifier">logging</span><span class="special">::</span><span class="identifier">formatter</span> <span class="identifier">fmt</span> <span class="special">=</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">stream</span>
38        <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">setw</span><span class="special">(</span><span class="number">6</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">setfill</span><span class="special">(</span><span class="char">'0'</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="identifier">line_id</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">setfill</span><span class="special">(</span><span class="char">' '</span><span class="special">)</span>
39        <span class="special">&lt;&lt;</span> <span class="string">": &lt;"</span> <span class="special">&lt;&lt;</span> <span class="identifier">severity</span> <span class="special">&lt;&lt;</span> <span class="string">"&gt;\t"</span>
40        <span class="special">&lt;&lt;</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">if_</span><span class="special">(</span><span class="identifier">expr</span><span class="special">::</span><span class="identifier">has_attr</span><span class="special">(</span><span class="identifier">tag_attr</span><span class="special">))</span>
41           <span class="special">[</span>
42               <span class="identifier">expr</span><span class="special">::</span><span class="identifier">stream</span> <span class="special">&lt;&lt;</span> <span class="string">"["</span> <span class="special">&lt;&lt;</span> <span class="identifier">tag_attr</span> <span class="special">&lt;&lt;</span> <span class="string">"] "</span>
43           <span class="special">]</span>
44        <span class="special">&lt;&lt;</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">smessage</span><span class="special">;</span>
45
46    <span class="comment">// Initialize sinks</span>
47    <span class="keyword">typedef</span> <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">synchronous_sink</span><span class="special">&lt;</span> <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">text_ostream_backend</span> <span class="special">&gt;</span> <span class="identifier">text_sink</span><span class="special">;</span>
48    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">text_sink</span> <span class="special">&gt;</span> <span class="identifier">sink</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">text_sink</span> <span class="special">&gt;();</span>
49
50    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">locked_backend</span><span class="special">()-&gt;</span><span class="identifier">add_stream</span><span class="special">(</span>
51        <span class="identifier">boost</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ofstream</span> <span class="special">&gt;(</span><span class="string">"full.log"</span><span class="special">));</span>
52
53    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">set_formatter</span><span class="special">(</span><span class="identifier">fmt</span><span class="special">);</span>
54
55    <span class="identifier">logging</span><span class="special">::</span><span class="identifier">core</span><span class="special">::</span><span class="identifier">get</span><span class="special">()-&gt;</span><span class="identifier">add_sink</span><span class="special">(</span><span class="identifier">sink</span><span class="special">);</span>
56
57    <span class="identifier">sink</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">text_sink</span> <span class="special">&gt;();</span>
58
59    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">locked_backend</span><span class="special">()-&gt;</span><span class="identifier">add_stream</span><span class="special">(</span>
60        <span class="identifier">boost</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ofstream</span> <span class="special">&gt;(</span><span class="string">"important.log"</span><span class="special">));</span>
61
62    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">set_formatter</span><span class="special">(</span><span class="identifier">fmt</span><span class="special">);</span>
63
64    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">set_filter</span><span class="special">(</span><span class="identifier">severity</span> <span class="special">&gt;=</span> <span class="identifier">warning</span> <span class="special">||</span> <span class="special">(</span><span class="identifier">expr</span><span class="special">::</span><span class="identifier">has_attr</span><span class="special">(</span><span class="identifier">tag_attr</span><span class="special">)</span> <span class="special">&amp;&amp;</span> <span class="identifier">tag_attr</span> <span class="special">==</span> <span class="string">"IMPORTANT_MESSAGE"</span><span class="special">));</span>
65
66    <span class="identifier">logging</span><span class="special">::</span><span class="identifier">core</span><span class="special">::</span><span class="identifier">get</span><span class="special">()-&gt;</span><span class="identifier">add_sink</span><span class="special">(</span><span class="identifier">sink</span><span class="special">);</span>
67
68    <span class="comment">// Add attributes</span>
69    <span class="identifier">logging</span><span class="special">::</span><span class="identifier">add_common_attributes</span><span class="special">();</span>
70<span class="special">}</span>
71</pre>
72<p>
73      </p>
74<p>
75        <a href="../../../../../../libs/log/example/doc/tutorial_filtering.cpp" target="_top">See the complete
76        code</a>.
77      </p>
78<p>
79        In this sample we initialize two sinks - one for the complete log file and
80        the other for important messages only. Both sinks will be writing to text
81        files with the same log record format, which we initialize first and save
82        to the <code class="computeroutput"><span class="identifier">fmt</span></code> variable. The
83        <code class="computeroutput"><a class="link" href="../../boost/log/basic_formatter.html" title="Class template basic_formatter">formatter</a></code> type is
84        a type-erased function object with the formatter calling signature; in many
85        respects it can be viewed similar to <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">function</span></code>
86        or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code> except that it is never empty.
87        There is also <code class="computeroutput"><a class="link" href="../../boost/log/filter.html" title="Class filter">a similar function object</a></code>
88        for filters.
89      </p>
90<p>
91        Notably, the formatter itself contains a filter here. As you can see, the
92        format contains a conditional part that is only present when log records
93        contain the "Tag" attribute. The <a class="link" href="../detailed/expressions.html#log.detailed.expressions.predicates.has_attr" title="Attribute presence filter"><code class="computeroutput"><span class="identifier">has_attr</span></code></a> predicate checks whether
94        the record contains the "Tag" attribute value and controls whether
95        it is put into the file or not. We used the attribute keyword to specify
96        the name and type of the attribute for the predicate, but it is also possible
97        to specify them in the <a class="link" href="../detailed/expressions.html#log.detailed.expressions.predicates.has_attr" title="Attribute presence filter"><code class="computeroutput"><span class="identifier">has_attr</span></code></a> call site. Conditional
98        formatters are explained in more details <a class="link" href="../detailed/expressions.html#log.detailed.expressions.formatters.conditional" title="Conditional formatters">here</a>.
99      </p>
100<p>
101        Further goes the initialization of the two sinks. The first sink does not
102        have any filter, which means it will save every log record to the file. We
103        call <code class="computeroutput"><span class="identifier">set_filter</span></code> on the second
104        sink to only save log records with severity no less than <code class="computeroutput"><span class="identifier">warning</span></code>
105        or having a "Tag" attribute with value "IMPORTANT_MESSAGE".
106        As you can see, the filter syntax resembles usual C++ very much, especially
107        when attribute keywords are used.
108      </p>
109<p>
110        Like with formatters, it is also possible to use custom functions as filters.
111        Fundamentally, a filter function must support the following signature:
112      </p>
113<pre class="programlisting"><span class="keyword">bool</span> <span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_value_set</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">attrs</span><span class="special">);</span>
114</pre>
115<p>
116        When the filter is called, <code class="computeroutput"><span class="identifier">attrs</span></code>
117        will contain a complete set of attribute values, which can be used to decide
118        whether the log record should be passed or suppressed. If the filter returns
119        <code class="computeroutput"><span class="keyword">true</span></code>, the log record will be
120        constructed and further processed by sinks. Otherwise, the record will be
121        discarded.
122      </p>
123<p>
124        <a href="http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html" target="_top">Boost.Phoenix</a>
125        can be very helpful in constructing filters. It allows to automate extraction
126        of attribute values from the <code class="computeroutput"><span class="identifier">attrs</span></code>
127        set as its <code class="computeroutput"><span class="identifier">bind</span></code> implementation
128        is compatible with attribute placeholders. The previous example can be modified
129        in the following way:
130      </p>
131<p>
132</p>
133<pre class="programlisting"><span class="keyword">bool</span> <span class="identifier">my_filter</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">value_ref</span><span class="special">&lt;</span> <span class="identifier">severity_level</span><span class="special">,</span> <span class="identifier">tag</span><span class="special">::</span><span class="identifier">severity</span> <span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">level</span><span class="special">,</span>
134               <span class="identifier">logging</span><span class="special">::</span><span class="identifier">value_ref</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">tag</span><span class="special">::</span><span class="identifier">tag_attr</span> <span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">tag</span><span class="special">)</span>
135<span class="special">{</span>
136    <span class="keyword">return</span> <span class="identifier">level</span> <span class="special">&gt;=</span> <span class="identifier">warning</span> <span class="special">||</span> <span class="identifier">tag</span> <span class="special">==</span> <span class="string">"IMPORTANT_MESSAGE"</span><span class="special">;</span>
137<span class="special">}</span>
138
139<span class="keyword">void</span> <span class="identifier">init</span><span class="special">()</span>
140<span class="special">{</span>
141    <span class="comment">// ...</span>
142
143    <span class="keyword">namespace</span> <span class="identifier">phoenix</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">;</span>
144    <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">set_filter</span><span class="special">(</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">my_filter</span><span class="special">,</span> <span class="identifier">severity</span><span class="special">.</span><span class="identifier">or_none</span><span class="special">(),</span> <span class="identifier">tag_attr</span><span class="special">.</span><span class="identifier">or_none</span><span class="special">()));</span>
145
146    <span class="comment">// ...</span>
147<span class="special">}</span>
148</pre>
149<p>
150      </p>
151<p>
152        As you can see, the custom filter receives attribute values as separate arguments,
153        wrapped into the <a class="link" href="../detailed/utilities.html#log.detailed.utilities.value_ref" title="Value reference wrapper"><code class="computeroutput"><span class="identifier">value_ref</span></code></a> template. This wrapper
154        contains an optional reference to the attribute value of the specified type;
155        the reference is valid if the log record contains the attribute value of
156        the required type. The relational operators used in <code class="computeroutput"><span class="identifier">my_filter</span></code>
157        can be applied unconditionally because they will automatically return <code class="computeroutput"><span class="keyword">false</span></code> if the reference is not valid. The rest
158        is done with the <code class="computeroutput"><span class="identifier">bind</span></code> expression
159        which will recognize the <code class="computeroutput"><span class="identifier">severity</span></code>
160        and <code class="computeroutput"><span class="identifier">tag_attr</span></code> keywords and
161        extract the corresponding values before passing them to <code class="computeroutput"><span class="identifier">my_filter</span></code>.
162      </p>
163<div class="note"><table border="0" summary="Note">
164<tr>
165<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
166<th align="left">Note</th>
167</tr>
168<tr><td align="left" valign="top"><p>
169          Because of limitations related to the integration with <a href="http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html" target="_top">Boost.Phoenix</a>
170          (see <a href="https://svn.boost.org/trac/boost/ticket/7996" target="_top">#7996</a>), it is required to explicitly specify the fallback policy
171          in case if the attribute value is missing, when attribute keywords are
172          used with <code class="computeroutput"><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">bind</span></code> or <code class="computeroutput"><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">function</span></code>.
173          In the example above, this is done by calling <code class="computeroutput"><span class="identifier">or_none</span></code>,
174          which results in an empty <a class="link" href="../detailed/utilities.html#log.detailed.utilities.value_ref" title="Value reference wrapper"><code class="computeroutput"><span class="identifier">value_ref</span></code></a> if the value is not
175          found. In other contexts this policy is the default. There are <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr.fallback_policies" title="Customizing fallback policy">other
176          policies</a> that can be used instead.
177        </p></td></tr>
178</table></div>
179<p>
180        You can try how this works by compiling and running the <a href="../../../../../../libs/log/example/doc/tutorial_filtering.cpp" target="_top">test</a>.
181      </p>
182</div>
183<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
184<td align="left"></td>
185<td align="right"><div class="copyright-footer">Copyright © 2007-2019 Andrey Semashev<p>
186        Distributed under the Boost Software License, Version 1.0. (See accompanying
187        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>).
188      </p>
189</div></td>
190</tr></table>
191<hr>
192<div class="spirit-nav">
193<a accesskey="p" href="formatters.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="wide_char.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
194</div>
195</body>
196</html>
197