Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / log / doc / html / log / extension / settings.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Extending library settings support</title>
5 <link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
7 <link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;Boost.Log v2">
8 <link rel="up" href="../extension.html" title="Extending the library">
9 <link rel="prev" href="attributes.html" title="Writing your own attributes">
10 <link rel="next" href="../rationale.html" title="Rationale and FAQ">
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="attributes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../extension.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="../rationale.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.extension.settings"></a><a class="link" href="settings.html" title="Extending library settings support">Extending library settings support</a>
21 </h3></div></div></div>
22 <p>
23         If you write your own logging sinks or use your own types in attributes,
24         you may want to add support for these components to the settings parser provided
25         by the library. Without doing this, the library will not be aware of your
26         types and thus will not be able to use them when parsing settings.
27       </p>
28 <h5>
29 <a name="log.extension.settings.h0"></a>
30         <span class="phrase"><a name="log.extension.settings.adding_support_for_user_defined_types_to_the_formatter_parser"></a></span><a class="link" href="settings.html#log.extension.settings.adding_support_for_user_defined_types_to_the_formatter_parser">Adding
31         support for user-defined types to the formatter parser</a>
32       </h5>
33 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../utilities.html#header.boost.log.utility.setup.formatter_parser_hpp" title="Header &lt;boost/log/utility/setup/formatter_parser.hpp&gt;">boost/log/utility/setup/formatter_parser.hpp</a></code><span class="special">&gt;</span>
34 </pre>
35 <p>
36         In order to add support for user-defined types to the formatter parser, one
37         has to register a formatter factory. The factory is basically an object that
38         derives from <code class="computeroutput"><a class="link" href="../../boost/log/formatter_factory.html" title="Struct template formatter_factory">formatter_factory</a></code>
39         interface. The factory mainly implements the single <code class="computeroutput"><span class="identifier">create_formatter</span></code>
40         method which, when called, will construct a formatter for the particular
41         attribute value.
42       </p>
43 <p>
44         When the user-defined type supports putting to a stream with <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
45         and this operator behavior is suitable for logging, one can use a simple
46         generic formatter factory provided by the library out of the box. For example,
47         let's assume we have the following user-defined type that we want to use
48         as an attribute value:
49       </p>
50 <p>
51 </p>
52 <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">point</span>
53 <span class="special">{</span>
54     <span class="keyword">float</span> <span class="identifier">m_x</span><span class="special">,</span> <span class="identifier">m_y</span><span class="special">;</span>
55
56     <span class="identifier">point</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">m_x</span><span class="special">(</span><span class="number">0.0f</span><span class="special">),</span> <span class="identifier">m_y</span><span class="special">(</span><span class="number">0.0f</span><span class="special">)</span> <span class="special">{}</span>
57     <span class="identifier">point</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">float</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_x</span><span class="special">(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">m_y</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span> <span class="special">{}</span>
58 <span class="special">};</span>
59
60 <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">TraitsT</span> <span class="special">&gt;</span>
61 <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="identifier">strm</span><span class="special">,</span> <span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">p</span><span class="special">)</span>
62 <span class="special">{</span>
63     <span class="identifier">strm</span> <span class="special">&lt;&lt;</span> <span class="string">"("</span> <span class="special">&lt;&lt;</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">m_x</span> <span class="special">&lt;&lt;</span> <span class="string">", "</span> <span class="special">&lt;&lt;</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">m_y</span> <span class="special">&lt;&lt;</span> <span class="string">")"</span><span class="special">;</span>
64     <span class="keyword">return</span> <span class="identifier">strm</span><span class="special">;</span>
65 <span class="special">}</span>
66 </pre>
67 <p>
68       </p>
69 <p>
70         Then, in order to register this type with the simple formatter factory, a
71         single call to <code class="computeroutput"><a class="link" href="../../boost/log/register_simpl_idp40225072.html" title="Function template register_simple_formatter_factory">register_simple_formatter_factory</a></code>
72         will suffice:
73       </p>
74 <p>
75 </p>
76 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
77 <span class="special">{</span>
78     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_simple_formatter_factory</span><span class="special">&lt;</span> <span class="identifier">point</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">&gt;(</span><span class="string">"Coordinates"</span><span class="special">);</span>
79 <span class="special">}</span>
80 </pre>
81 <p>
82       </p>
83 <div class="note"><table border="0" summary="Note">
84 <tr>
85 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
86 <th align="left">Note</th>
87 </tr>
88 <tr><td align="left" valign="top"><p>
89           The <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
90           for the attribute value stored type must be visible from the point of this
91           call.
92         </p></td></tr>
93 </table></div>
94 <p>
95         The function takes the stored attribute value type (<code class="computeroutput"><span class="identifier">point</span></code>,
96         in our case) and the target character type used by formatters as template
97         parameters. From the point of this call, whenever the formatter parser encounters
98         a reference to the "Coordinates" attribute in the format string,
99         it will invoke the formatter factory, which will construct the formatter
100         that calls our <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
101         for class <code class="computeroutput"><span class="identifier">point</span></code>.
102       </p>
103 <div class="tip"><table border="0" summary="Tip">
104 <tr>
105 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
106 <th align="left">Tip</th>
107 </tr>
108 <tr><td align="left" valign="top"><p>
109           It is typically a good idea to register all formatter factories at an early
110           stage of the application initialization, before any other library initialization,
111           such as reading config files.
112         </p></td></tr>
113 </table></div>
114 <p>
115         From the <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.filter_formatter" title="Filter and formatter parsers">formatter
116         parser description</a> it is known that the parser supports passing additional
117         parameters from the format string to the formatter factory. We can use these
118         parameters to customize the output generated by the formatter.
119       </p>
120 <p>
121         For example, let's implement customizable formatting of our <code class="computeroutput"><span class="identifier">point</span></code> objects, so that the following format
122         string works as expected:
123       </p>
124 <pre class="programlisting">%TimeStamp% %Coordinates(format="{%0.3f; %0.3f}")% %Message%</pre>
125 <p>
126         The simple formatter factory ignores all additional parameters from the format
127         string, so we have to implement our own factory instead. Custom factories
128         are registered with the <code class="computeroutput"><a class="link" href="../../boost/log/register_forma_idp40212368.html" title="Function template register_formatter_factory">register_formatter_factory</a></code>
129         function, which is similar to <code class="computeroutput"><a class="link" href="../../boost/log/register_simpl_idp40225072.html" title="Function template register_simple_formatter_factory">register_simple_formatter_factory</a></code>
130         but accepts a pointer to the factory instead of the explicit template parameters.
131       </p>
132 <p>
133 </p>
134 <pre class="programlisting"><span class="comment">// Custom point formatter</span>
135 <span class="keyword">class</span> <span class="identifier">point_formatter</span>
136 <span class="special">{</span>
137 <span class="keyword">public</span><span class="special">:</span>
138     <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">result_type</span><span class="special">;</span>
139
140 <span class="keyword">public</span><span class="special">:</span>
141     <span class="keyword">explicit</span> <span class="identifier">point_formatter</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">fmt</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_format</span><span class="special">(</span><span class="identifier">fmt</span><span class="special">)</span>
142     <span class="special">{</span>
143     <span class="special">}</span>
144
145     <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()</span> <span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">formatting_ostream</span><span class="special">&amp;</span> <span class="identifier">strm</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">point</span> <span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">value</span><span class="special">)</span> <span class="keyword">const</span>
146     <span class="special">{</span>
147         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">value</span><span class="special">)</span>
148         <span class="special">{</span>
149             <span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">value</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
150             <span class="identifier">m_format</span> <span class="special">%</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">m_x</span> <span class="special">%</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">m_y</span><span class="special">;</span>
151             <span class="identifier">strm</span> <span class="special">&lt;&lt;</span> <span class="identifier">m_format</span><span class="special">;</span>
152             <span class="identifier">m_format</span><span class="special">.</span><span class="identifier">clear</span><span class="special">();</span>
153         <span class="special">}</span>
154     <span class="special">}</span>
155
156 <span class="keyword">private</span><span class="special">:</span>
157     <span class="keyword">mutable</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">format</span> <span class="identifier">m_format</span><span class="special">;</span>
158 <span class="special">};</span>
159
160 <span class="comment">// Custom point formatter factory</span>
161 <span class="keyword">class</span> <span class="identifier">point_formatter_factory</span> <span class="special">:</span>
162     <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">basic_formatter_factory</span><span class="special">&lt;</span> <span class="keyword">char</span><span class="special">,</span> <span class="identifier">point</span> <span class="special">&gt;</span>
163 <span class="special">{</span>
164 <span class="keyword">public</span><span class="special">:</span>
165     <span class="identifier">formatter_type</span> <span class="identifier">create_formatter</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">args_map</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">args</span><span class="special">)</span>
166     <span class="special">{</span>
167         <span class="identifier">args_map</span><span class="special">::</span><span class="identifier">const_iterator</span> <span class="identifier">it</span> <span class="special">=</span> <span class="identifier">args</span><span class="special">.</span><span class="identifier">find</span><span class="special">(</span><span class="string">"format"</span><span class="special">);</span>
168         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">it</span> <span class="special">!=</span> <span class="identifier">args</span><span class="special">.</span><span class="identifier">end</span><span class="special">())</span>
169             <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span><span class="identifier">point_formatter</span><span class="special">(</span><span class="identifier">it</span><span class="special">-&gt;</span><span class="identifier">second</span><span class="special">),</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">stream</span><span class="special">,</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">));</span>
170         <span class="keyword">else</span>
171             <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">stream</span> <span class="special">&lt;&lt;</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">);</span>
172     <span class="special">}</span>
173 <span class="special">};</span>
174
175 <span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
176 <span class="special">{</span>
177     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_formatter_factory</span><span class="special">(</span><span class="string">"Coordinates"</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">point_formatter_factory</span> <span class="special">&gt;());</span>
178 <span class="special">}</span>
179 </pre>
180 <p>
181       </p>
182 <p>
183         Let's walk through this code sample. Our <code class="computeroutput"><span class="identifier">point_formatter_factory</span></code>
184         class derives from the <code class="computeroutput"><a class="link" href="../../boost/log/basic_formatter_factory.html" title="Class template basic_formatter_factory">basic_formatter_factory</a></code>
185         base class provided by the library. This class derives from the base <code class="computeroutput"><a class="link" href="../../boost/log/formatter_factory.html" title="Struct template formatter_factory">formatter_factory</a></code> interface
186         and defines a few useful types, such as <code class="computeroutput"><span class="identifier">formatter_type</span></code>
187         and <code class="computeroutput"><span class="identifier">args_map</span></code> that we use.
188         The only thing left to do in our factory is to define the <code class="computeroutput"><span class="identifier">create_formatter</span></code>
189         method. The method analyzes the parameters from the format string which are
190         passed as the <code class="computeroutput"><span class="identifier">args</span></code> argument,
191         which is basically <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code> of string keys (parameter names) to
192         string values (the parameter values). We seek for the <code class="computeroutput"><span class="identifier">format</span></code>
193         parameter and expect it to contain a <a href="http://www.boost.org/doc/libs/release/libs/format/index.html" target="_top">Boost.Format</a>-compatible
194         format string for our <code class="computeroutput"><span class="identifier">point</span></code>
195         objects. If the parameter is found we create a formatter that invokes <code class="computeroutput"><span class="identifier">point_formatter</span></code> for the attribute values.
196         Otherwise we create a default formatter that simply uses the <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>,
197         like the simple formatter factory does. Note that we use the <code class="computeroutput"><span class="identifier">name</span></code> argument of <code class="computeroutput"><span class="identifier">create_formatter</span></code>
198         to identify the attribute so that the same factory can be used for different
199         attributes.
200       </p>
201 <p>
202         The <code class="computeroutput"><span class="identifier">point_formatter</span></code> is our
203         custom formatter based on <a href="http://www.boost.org/doc/libs/release/libs/format/index.html" target="_top">Boost.Format</a>.
204         With help of <a href="http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html" target="_top">Boost.Phoenix</a>
205         and <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr" title="Generic attribute placeholder">expression placeholders</a>
206         we can construct a formatter that will extract the attribute value and pass
207         it along with the target stream to the <code class="computeroutput"><span class="identifier">point_formatter</span></code>
208         function object. Note that the formatter accepts the attribute value wrapped
209         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>
210         wrapper which can be empty if the value is not present.
211       </p>
212 <p>
213         Lastly, the call to <code class="computeroutput"><a class="link" href="../../boost/log/register_forma_idp40212368.html" title="Function template register_formatter_factory">register_formatter_factory</a></code>
214         creates the factory and adds it to the library.
215       </p>
216 <p>
217         You can find the complete code of this example <a href="../../../../../../libs/log/example/doc/extension_formatter_parser.cpp" target="_top">here</a>.
218       </p>
219 <h5>
220 <a name="log.extension.settings.h1"></a>
221         <span class="phrase"><a name="log.extension.settings.adding_support_for_user_defined_types_to_the_filter_parser"></a></span><a class="link" href="settings.html#log.extension.settings.adding_support_for_user_defined_types_to_the_filter_parser">Adding
222         support for user-defined types to the filter parser</a>
223       </h5>
224 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../utilities.html#header.boost.log.utility.setup.filter_parser_hpp" title="Header &lt;boost/log/utility/setup/filter_parser.hpp&gt;">boost/log/utility/setup/filter_parser.hpp</a></code><span class="special">&gt;</span>
225 </pre>
226 <p>
227         You can extend filter parser in the similar way you can extend the formatter
228         parser - by registering filter factories for your attribute values into the
229         library. However, since it takes a considerably more complex syntax to describe
230         filters, a filter factory typically implements several generator functions.
231       </p>
232 <p>
233         Like with formatter parser extension, you can avoid spelling out the filter
234         factory and register a simple factory provided by the library:
235       </p>
236 <p>
237 </p>
238 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
239 <span class="special">{</span>
240     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_simple_filter_factory</span><span class="special">&lt;</span> <span class="identifier">point</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">&gt;(</span><span class="string">"Coordinates"</span><span class="special">);</span>
241 <span class="special">}</span>
242 </pre>
243 <p>
244       </p>
245 <p>
246         In order this to work the user's type should fulfill these requirements:
247       </p>
248 <div class="orderedlist"><ol class="orderedlist" type="1">
249 <li class="listitem">
250             Support reading from an input stream with <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>.
251           </li>
252 <li class="listitem">
253             Support the complete set of comparison and ordering operators.
254           </li>
255 </ol></div>
256 <p>
257         Naturally, all these operators must be visible from the point of the <code class="computeroutput"><a class="link" href="../../boost/log/register_simpl_idp40142960.html" title="Function template register_simple_filter_factory">register_simple_filter_factory</a></code>
258         call. Note that unlike the simple formatter factory, the filter factory requires
259         the user's type to support reading from a stream. This is so because the
260         filter factory would have to parse the argument of the filter relation from
261         a string.
262       </p>
263 <p>
264         But we won't get away with a simple filter factory, because our <code class="computeroutput"><span class="identifier">point</span></code> class doesn't have a sensible ordering
265         semantics and thus we cannot define the complete set of operators. We'll
266         have to implement our own filter factory instead. Filter factories derive
267         from the <code class="computeroutput"><a class="link" href="../../boost/log/filter_factory.html" title="Struct template filter_factory">filter_factory</a></code>
268         interface. This base class declares a number of virtual functions that will
269         be called in order to create filters, according to the filter expression.
270         If some functions are not overridden by the factory, the corresponding operations
271         are considered to be not supported by the attribute value. But before we
272         define the filter factory we have to improve our <code class="computeroutput"><span class="identifier">point</span></code>
273         class slightly:
274       </p>
275 <p>
276 </p>
277 <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">point</span>
278 <span class="special">{</span>
279     <span class="keyword">float</span> <span class="identifier">m_x</span><span class="special">,</span> <span class="identifier">m_y</span><span class="special">;</span>
280
281     <span class="identifier">point</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">m_x</span><span class="special">(</span><span class="number">0.0f</span><span class="special">),</span> <span class="identifier">m_y</span><span class="special">(</span><span class="number">0.0f</span><span class="special">)</span> <span class="special">{}</span>
282     <span class="identifier">point</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">float</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">m_x</span><span class="special">(</span><span class="identifier">x</span><span class="special">),</span> <span class="identifier">m_y</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span> <span class="special">{}</span>
283 <span class="special">};</span>
284
285 <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==</span> <span class="special">(</span><span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">left</span><span class="special">,</span> <span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">right</span><span class="special">);</span>
286 <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=</span> <span class="special">(</span><span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">left</span><span class="special">,</span> <span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">right</span><span class="special">);</span>
287
288 <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">TraitsT</span> <span class="special">&gt;</span>
289 <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="identifier">strm</span><span class="special">,</span> <span class="identifier">point</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">p</span><span class="special">);</span>
290 <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">TraitsT</span> <span class="special">&gt;</span>
291 <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="identifier">strm</span><span class="special">,</span> <span class="identifier">point</span><span class="special">&amp;</span> <span class="identifier">p</span><span class="special">);</span>
292 </pre>
293 <p>
294       </p>
295 <p>
296         We have added comparison and input operators for the <code class="computeroutput"><span class="identifier">point</span></code>
297         class. The output operator is still used by formatters and not required by
298         the filter factory. Now we can define and register the filter factory:
299       </p>
300 <p>
301 </p>
302 <pre class="programlisting"><span class="comment">// Custom point filter factory</span>
303 <span class="keyword">class</span> <span class="identifier">point_filter_factory</span> <span class="special">:</span>
304     <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter_factory</span><span class="special">&lt;</span> <span class="keyword">char</span> <span class="special">&gt;</span>
305 <span class="special">{</span>
306 <span class="keyword">public</span><span class="special">:</span>
307     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_exists_test</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">)</span>
308     <span class="special">{</span>
309         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">has_attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">);</span>
310     <span class="special">}</span>
311
312     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_equality_relation</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arg</span><span class="special">)</span>
313     <span class="special">{</span>
314         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">);</span>
315     <span class="special">}</span>
316
317     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_inequality_relation</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arg</span><span class="special">)</span>
318     <span class="special">{</span>
319         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">)</span> <span class="special">!=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">);</span>
320     <span class="special">}</span>
321 <span class="special">};</span>
322
323 <span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
324 <span class="special">{</span>
325     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_filter_factory</span><span class="special">(</span><span class="string">"Coordinates"</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">point_filter_factory</span> <span class="special">&gt;());</span>
326 <span class="special">}</span>
327 </pre>
328 <p>
329       </p>
330 <p>
331         Having called the <code class="computeroutput"><a class="link" href="../../boost/log/register_filte_idp40130064.html" title="Function template register_filter_factory">register_filter_factory</a></code>
332         function, whenever the <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.filter_formatter" title="Filter and formatter parsers">filter
333         parser</a> encounters the "Coordinates" attribute mentioned
334         in the filter, it will use the <code class="computeroutput"><span class="identifier">point_filter_factory</span></code>
335         object to construct the appropriate filter. For example, in the case of the
336         following filter
337       </p>
338 <pre class="programlisting">%Coordinates% = "(10, 10)"</pre>
339 <p>
340         the <code class="computeroutput"><span class="identifier">on_equality_relation</span></code>
341         method will be called with <code class="computeroutput"><span class="identifier">name</span></code>
342         argument being "Coordinates" and <code class="computeroutput"><span class="identifier">arg</span></code>
343         being "(10, 10)".
344       </p>
345 <div class="note"><table border="0" summary="Note">
346 <tr>
347 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
348 <th align="left">Note</th>
349 </tr>
350 <tr><td align="left" valign="top"><p>
351           The quotes around the parenthesis are necessary because the filter parser
352           should interpret the point coordinates as a single string. Also, round
353           brackets are already used to group subexpressions of the filter expression.
354           Whenever there is need to pass several parameters to the relation (like
355           in this case - a number of components of the <code class="computeroutput"><span class="identifier">point</span></code>
356           class) the parameters should be encoded into a quoted string. The string
357           may include C-style escape sequences that will be unfolded upon parsing.
358         </p></td></tr>
359 </table></div>
360 <p>
361         The constructed filter will use the corresponding comparison operators for
362         the <code class="computeroutput"><span class="identifier">point</span></code> class. Ordering
363         operations, like "&gt;" or "&lt;=", will not be supported
364         for attributes named "Coordinates", and this is exactly the way
365         we want it, because the <code class="computeroutput"><span class="identifier">point</span></code>
366         class does not support them either. The complete example is available <a href="../../../../../../libs/log/example/doc/extension_filter_parser.cpp" target="_top">here</a>.
367       </p>
368 <p>
369         The library allows not only adding support for new types, but also associating
370         new relations with them. For instance, we can create a new relation "is_in_rect"
371         that will yield positive if the coordinates fit into a rectangle denoted
372         with two points. The filter might look like this:
373       </p>
374 <pre class="programlisting">%Coordinates% is_in_rect "{(10, 10) - (20, 20)}"</pre>
375 <p>
376         First, let's define our rectangle class:
377       </p>
378 <p>
379 </p>
380 <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">rectangle</span>
381 <span class="special">{</span>
382     <span class="identifier">point</span> <span class="identifier">m_top_left</span><span class="special">,</span> <span class="identifier">m_bottom_right</span><span class="special">;</span>
383 <span class="special">};</span>
384
385 <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">TraitsT</span> <span class="special">&gt;</span>
386 <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ostream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="identifier">strm</span><span class="special">,</span> <span class="identifier">rectangle</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">);</span>
387 <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">TraitsT</span> <span class="special">&gt;</span>
388 <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_istream</span><span class="special">&lt;</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">TraitsT</span> <span class="special">&gt;&amp;</span> <span class="identifier">strm</span><span class="special">,</span> <span class="identifier">rectangle</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">);</span>
389 </pre>
390 <p>
391       </p>
392 <p>
393         As it was said, the rectangle is described by two points - the top left and
394         the bottom right corners of the rectangle area. Now let's extend our filter
395         factory with the <code class="computeroutput"><span class="identifier">on_custom_relation</span></code>
396         method:
397       </p>
398 <p>
399 </p>
400 <pre class="programlisting"><span class="comment">// The function checks if the point is inside the rectangle</span>
401 <span class="keyword">bool</span> <span class="identifier">is_in_rect</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">point</span> <span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">rectangle</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">r</span><span class="special">)</span>
402 <span class="special">{</span>
403     <span class="keyword">if</span> <span class="special">(</span><span class="identifier">p</span><span class="special">)</span>
404     <span class="special">{</span>
405         <span class="keyword">return</span> <span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_x</span> <span class="special">&gt;=</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">m_top_left</span><span class="special">.</span><span class="identifier">m_x</span> <span class="special">&amp;&amp;</span> <span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_x</span> <span class="special">&lt;=</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">m_bottom_right</span><span class="special">.</span><span class="identifier">m_x</span> <span class="special">&amp;&amp;</span>
406                <span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_y</span> <span class="special">&gt;=</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">m_top_left</span><span class="special">.</span><span class="identifier">m_y</span> <span class="special">&amp;&amp;</span> <span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_y</span> <span class="special">&lt;=</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">m_bottom_right</span><span class="special">.</span><span class="identifier">m_y</span><span class="special">;</span>
407     <span class="special">}</span>
408     <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span>
409 <span class="special">}</span>
410
411 <span class="comment">// Custom point filter factory</span>
412 <span class="keyword">class</span> <span class="identifier">point_filter_factory</span> <span class="special">:</span>
413     <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter_factory</span><span class="special">&lt;</span> <span class="keyword">char</span> <span class="special">&gt;</span>
414 <span class="special">{</span>
415 <span class="keyword">public</span><span class="special">:</span>
416     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_exists_test</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">)</span>
417     <span class="special">{</span>
418         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">has_attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">);</span>
419     <span class="special">}</span>
420
421     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_equality_relation</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arg</span><span class="special">)</span>
422     <span class="special">{</span>
423         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">);</span>
424     <span class="special">}</span>
425
426     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_inequality_relation</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arg</span><span class="special">)</span>
427     <span class="special">{</span>
428         <span class="keyword">return</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">)</span> <span class="special">!=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">);</span>
429     <span class="special">}</span>
430
431     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">filter</span> <span class="identifier">on_custom_relation</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_name</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">name</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rel</span><span class="special">,</span> <span class="identifier">string_type</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">arg</span><span class="special">)</span>
432     <span class="special">{</span>
433         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">rel</span> <span class="special">==</span> <span class="string">"is_in_rect"</span><span class="special">)</span>
434         <span class="special">{</span>
435             <span class="keyword">return</span> <span class="identifier">boost</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">is_in_rect</span><span class="special">,</span> <span class="identifier">expr</span><span class="special">::</span><span class="identifier">attr</span><span class="special">&lt;</span> <span class="identifier">point</span> <span class="special">&gt;(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="identifier">rectangle</span> <span class="special">&gt;(</span><span class="identifier">arg</span><span class="special">));</span>
436         <span class="special">}</span>
437         <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span><span class="string">"Unsupported filter relation: "</span> <span class="special">+</span> <span class="identifier">rel</span><span class="special">);</span>
438     <span class="special">}</span>
439 <span class="special">};</span>
440
441 <span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
442 <span class="special">{</span>
443     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_filter_factory</span><span class="special">(</span><span class="string">"Coordinates"</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">point_filter_factory</span> <span class="special">&gt;());</span>
444 <span class="special">}</span>
445 </pre>
446 <p>
447       </p>
448 <p>
449         The <code class="computeroutput"><span class="identifier">on_custom_relation</span></code> method
450         is called with the relation name (the "is_in_rect" string in our
451         case) and the right-hand argument for the relation (the rectangle description).
452         All we have to do is to construct the filter, which is implemented by our
453         <code class="computeroutput"><span class="identifier">is_in_rect</span></code> function. We use
454         <code class="computeroutput"><span class="identifier">bind</span></code> from <a href="http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html" target="_top">Boost.Phoenix</a>
455         to compose the filter from the function and the <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr" title="Generic attribute placeholder">attribute
456         placeholder</a>. You can find the complete code of this example <a href="../../../../../../libs/log/example/doc/extension_filter_parser_custom_rel.cpp" target="_top">here</a>.
457       </p>
458 <h5>
459 <a name="log.extension.settings.h2"></a>
460         <span class="phrase"><a name="log.extension.settings.adding_support_for_user_defined_sinks"></a></span><a class="link" href="settings.html#log.extension.settings.adding_support_for_user_defined_sinks">Adding
461         support for user-defined sinks</a>
462       </h5>
463 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../utilities.html#header.boost.log.utility.setup.from_settings_hpp" title="Header &lt;boost/log/utility/setup/from_settings.hpp&gt;">boost/log/utility/setup/from_settings.hpp</a></code><span class="special">&gt;</span>
464 <span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../utilities.html#header.boost.log.utility.setup.from_stream_hpp" title="Header &lt;boost/log/utility/setup/from_stream.hpp&gt;">boost/log/utility/setup/from_stream.hpp</a></code><span class="special">&gt;</span>
465 </pre>
466 <p>
467         The library provides mechanism of extending support for sinks similar to
468         the formatter and filter parsers. In order to be able to mention user-defined
469         sinks in a settings file, the user has to register a sink factory, which
470         essentially contains the <code class="computeroutput"><span class="identifier">create_sink</span></code>
471         method that receives a <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.settings" title="Library initialization from a settings container">settings
472         subsection</a> and returns a pointer to the initialized sink. The factory
473         is registered for a specific destination (see the <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.settings" title="Library initialization from a settings container">settings
474         file description</a>), so whenever a sink with the specified destination
475         is mentioned in the settings file, the factory gets called.
476       </p>
477 <p>
478         For example, let's register the <code class="computeroutput"><span class="identifier">stat_collector</span></code>
479         sink we described <a class="link" href="../extension.html#log.extension.sinks" title="Writing your own sinks">before</a> in the
480         library. First, let's remember the sink definition:
481       </p>
482 <p>
483 </p>
484 <pre class="programlisting"><span class="comment">// The backend collects statistical information about network activity of the application</span>
485 <span class="keyword">class</span> <span class="identifier">stat_collector</span> <span class="special">:</span>
486     <span class="keyword">public</span> <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">basic_sink_backend</span><span class="special">&lt;</span>
487         <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">combine_requirements</span><span class="special">&lt;</span>
488             <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">synchronized_feeding</span><span class="special">,</span>
489             <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">flushing</span>
490         <span class="special">&gt;::</span><span class="identifier">type</span>
491     <span class="special">&gt;</span>
492 <span class="special">{</span>
493 <span class="keyword">private</span><span class="special">:</span>
494     <span class="comment">// The file to write the collected information to</span>
495     <span class="identifier">std</span><span class="special">::</span><span class="identifier">ofstream</span> <span class="identifier">m_csv_file</span><span class="special">;</span>
496
497     <span class="comment">// Here goes the data collected so far:</span>
498     <span class="comment">// Active connections</span>
499     <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">m_active_connections</span><span class="special">;</span>
500     <span class="comment">// Sent bytes</span>
501     <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">m_sent_bytes</span><span class="special">;</span>
502     <span class="comment">// Received bytes</span>
503     <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">m_received_bytes</span><span class="special">;</span>
504
505     <span class="comment">// The number of collected records since the last write to the file</span>
506     <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">m_collected_count</span><span class="special">;</span>
507     <span class="comment">// The time when the collected data has been written to the file last time</span>
508     <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span> <span class="identifier">m_last_store_time</span><span class="special">;</span>
509     <span class="comment">// The collected data writing interval</span>
510     <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">time_duration</span> <span class="identifier">m_write_interval</span><span class="special">;</span>
511
512 <span class="keyword">public</span><span class="special">:</span>
513     <span class="comment">// The constructor initializes the internal data</span>
514     <span class="identifier">stat_collector</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">file_name</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">time_duration</span> <span class="identifier">write_interval</span><span class="special">);</span>
515
516     <span class="comment">// The function consumes the log records that come from the frontend</span>
517     <span class="keyword">void</span> <span class="identifier">consume</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">record_view</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rec</span><span class="special">);</span>
518     <span class="comment">// The function flushes the file</span>
519     <span class="keyword">void</span> <span class="identifier">flush</span><span class="special">();</span>
520
521 <span class="keyword">private</span><span class="special">:</span>
522     <span class="comment">// The function resets statistical accumulators to initial values</span>
523     <span class="keyword">void</span> <span class="identifier">reset_accumulators</span><span class="special">();</span>
524     <span class="comment">// The function writes the collected data to the file</span>
525     <span class="keyword">void</span> <span class="identifier">write_data</span><span class="special">();</span>
526 <span class="special">};</span>
527 </pre>
528 <p>
529       </p>
530 <p>
531         Compared to the earlier definition we added the <code class="computeroutput"><span class="identifier">write_interval</span></code>
532         constructor parameter so we can set the statistical information flush interval
533         in the settings file. The implementation of the sink stays pretty much the
534         same as before. Now we have to define the factory:
535       </p>
536 <p>
537 </p>
538 <pre class="programlisting"><span class="comment">// Factory for the stat_collector sink</span>
539 <span class="keyword">class</span> <span class="identifier">stat_collector_factory</span> <span class="special">:</span>
540     <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">sink_factory</span><span class="special">&lt;</span> <span class="keyword">char</span> <span class="special">&gt;</span>
541 <span class="special">{</span>
542 <span class="keyword">public</span><span class="special">:</span>
543     <span class="comment">// Creates the sink with the provided parameters</span>
544     <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">sink</span> <span class="special">&gt;</span> <span class="identifier">create_sink</span><span class="special">(</span><span class="identifier">settings_section</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">settings</span><span class="special">)</span>
545     <span class="special">{</span>
546         <span class="comment">// Read sink parameters</span>
547         <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">file_name</span><span class="special">;</span>
548         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&gt;</span> <span class="identifier">param</span> <span class="special">=</span> <span class="identifier">settings</span><span class="special">[</span><span class="string">"FileName"</span><span class="special">])</span>
549             <span class="identifier">file_name</span> <span class="special">=</span> <span class="identifier">param</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
550         <span class="keyword">else</span>
551             <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span><span class="string">"No target file name specified in settings"</span><span class="special">);</span>
552
553         <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">time_duration</span> <span class="identifier">write_interval</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">minutes</span><span class="special">(</span><span class="number">1</span><span class="special">);</span>
554         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&gt;</span> <span class="identifier">param</span> <span class="special">=</span> <span class="identifier">settings</span><span class="special">[</span><span class="string">"WriteInterval"</span><span class="special">])</span>
555         <span class="special">{</span>
556             <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">sec</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span><span class="special">&lt;</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="special">&gt;(</span><span class="identifier">param</span><span class="special">.</span><span class="identifier">get</span><span class="special">());</span>
557             <span class="identifier">write_interval</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">seconds</span><span class="special">(</span><span class="identifier">sec</span><span class="special">);</span>
558         <span class="special">}</span>
559
560         <span class="comment">// Create the sink</span>
561         <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">stat_collector</span> <span class="special">&gt;</span> <span class="identifier">backend</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">stat_collector</span> <span class="special">&gt;(</span><span class="identifier">file_name</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">(),</span> <span class="identifier">write_interval</span><span class="special">);</span>
562         <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">sinks</span><span class="special">::</span><span class="identifier">synchronous_sink</span><span class="special">&lt;</span> <span class="identifier">stat_collector</span> <span class="special">&gt;</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">sinks</span><span class="special">::</span><span class="identifier">synchronous_sink</span><span class="special">&lt;</span> <span class="identifier">stat_collector</span> <span class="special">&gt;</span> <span class="special">&gt;(</span><span class="identifier">backend</span><span class="special">);</span>
563
564         <span class="keyword">if</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&gt;</span> <span class="identifier">param</span> <span class="special">=</span> <span class="identifier">settings</span><span class="special">[</span><span class="string">"Filter"</span><span class="special">])</span>
565         <span class="special">{</span>
566             <span class="identifier">sink</span><span class="special">-&gt;</span><span class="identifier">set_filter</span><span class="special">(</span><span class="identifier">logging</span><span class="special">::</span><span class="identifier">parse_filter</span><span class="special">(</span><span class="identifier">param</span><span class="special">.</span><span class="identifier">get</span><span class="special">()));</span>
567         <span class="special">}</span>
568
569         <span class="keyword">return</span> <span class="identifier">sink</span><span class="special">;</span>
570     <span class="special">}</span>
571 <span class="special">};</span>
572
573 <span class="keyword">void</span> <span class="identifier">init_factories</span><span class="special">()</span>
574 <span class="special">{</span>
575     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">register_sink_factory</span><span class="special">(</span><span class="string">"StatCollector"</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">stat_collector_factory</span> <span class="special">&gt;());</span>
576 <span class="special">}</span>
577 </pre>
578 <p>
579       </p>
580 <p>
581         As you can see, we read parameters from settings and simply create our sink
582         with them as a result of <code class="computeroutput"><span class="identifier">create_sink</span></code>
583         method. Generally, users are free to name parameters of their sinks the way
584         they like, as long as <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.settings_file" title="Library initialization from a settings file">settings
585         file format</a> is adhered. However, it is a good idea to follow the pattern
586         established by the library and reuse parameter names with the same meaning.
587         That is, it should be obvious that the parameter "Filter" means
588         the same for both the library-provided "TextFile" sink and out
589         custom "StatCollector" sink.
590       </p>
591 <p>
592         After defining the factory we only have to register it with the <code class="computeroutput"><a class="link" href="../../boost/log/register_sink__idp40274512.html" title="Function template register_sink_factory">register_sink_factory</a></code>
593         call. The first argument is the new value of the "Destination"
594         parameter in the settings. Whenever the library finds sink description with
595         destination "StatCollector", our factory will be invoked to create
596         the sink. It is also possible to override library-provided destination types
597         with user-defined factories, however it is not possible to restore the default
598         factories afterwards.
599       </p>
600 <div class="note"><table border="0" summary="Note">
601 <tr>
602 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
603 <th align="left">Note</th>
604 </tr>
605 <tr><td align="left" valign="top"><p>
606           As the "Destination" parameter is used to determine the sink
607           factory, this parameter is reserved and cannot be used by sink factories
608           for their own purposes.
609         </p></td></tr>
610 </table></div>
611 <p>
612         Now that the factory is registered, we can use it when initializing from
613         files or settings. For example, this is what the settings file could look
614         like:
615       </p>
616 <pre class="programlisting">[Sinks.MyStat]
617
618 Destination=StatCollector
619 FileName=stat.csv
620 WriteInterval=30
621 </pre>
622 <p>
623         The complete code of the example in this section can be found <a href="../../../../../../libs/log/example/doc/extension_stat_collector_settings.cpp" target="_top">here</a>.
624       </p>
625 </div>
626 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
627 <td align="left"></td>
628 <td align="right"><div class="copyright-footer">Copyright &#169; 2007-2014 Andrey Semashev<p>
629         Distributed under the Boost Software License, Version 1.0. (See accompanying
630         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>).
631       </p>
632 </div></td>
633 </tr></table>
634 <hr>
635 <div class="spirit-nav">
636 <a accesskey="p" href="attributes.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../extension.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="../rationale.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
637 </div>
638 </body>
639 </html>