Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / log / doc / html / log / tutorial / attributes.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Adding more information to log: Attributes</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="../tutorial.html" title="Tutorial">
9 <link rel="prev" href="sources.html" title="Creating loggers and writing logs">
10 <link rel="next" href="formatters.html" title="Log record formatting">
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="sources.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="formatters.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.attributes"></a><a class="link" href="attributes.html" title="Adding more information to log: Attributes">Adding more information to log:
21       Attributes</a>
22 </h3></div></div></div>
23 <p>
24         In previous sections we mentioned attributes and attribute values several
25         times. Here we will discover how attributes can be used to add more data
26         to log records.
27       </p>
28 <p>
29         Each log record can have a number of named attribute values attached. Attributes
30         can represent any essential information about the conditions in which the
31         log record occurred, such as position in the code, executable module name,
32         current date and time, or any piece of data relevant to your particular application
33         and execution environment. An attribute may behave as a value generator,
34         in which case it would return a different value for each log record it's
35         involved in. As soon as the attribute generates the value, the latter becomes
36         independent from the creator and can be used by filters, formatters and sinks.
37         But in order to use the attribute value one has to know its name and type,
38         or at least a set of types it may have. There are a number of commonly used
39         attributes implemented in the library, you can find the types of their values
40         in the documentation.
41       </p>
42 <p>
43         Aside from that, as described in the <a class="link" href="../design.html" title="Design overview">Design overview</a>
44         section, there are three possible scopes of attributes: source-specific,
45         thread-specific and global. When a log record is made, attribute values from
46         these three sets are joined into a single set and passed to sinks. This implies
47         that the origin of the attribute makes no difference for sinks. Any attribute
48         can be registered in any scope. When registered, an attribute is given a
49         unique name in order to make it possible to search for it. If it happens
50         that the same named attribute is found in several scopes, the attribute from
51         the most specific scope is taken into consideration in any further processing,
52         including filtering and formatting. Such behavior makes it possible to override
53         global or thread-scoped attributes with the ones registered in your local
54         logger, thus reducing thread interference.
55       </p>
56 <p>
57         Below is the description of the attribute registration process.
58       </p>
59 <h5>
60 <a name="log.tutorial.attributes.h0"></a>
61         <span class="phrase"><a name="log.tutorial.attributes.commonly_used_attributes"></a></span><a class="link" href="attributes.html#log.tutorial.attributes.commonly_used_attributes">Commonly
62         used attributes</a>
63       </h5>
64 <p>
65         There are attributes that are likely to be used in nearly any application.
66         Log record counter and a time stamp are good candidates. They can be added
67         with a single function call:
68       </p>
69 <pre class="programlisting"><span class="identifier">logging</span><span class="special">::</span><span class="identifier">add_common_attributes</span><span class="special">();</span>
70 </pre>
71 <p>
72         With this call attributes "LineID", "TimeStamp", "ProcessID"
73         and "ThreadID" are registered globally. The "LineID"
74         attribute is a counter that increments for each record being made, the first
75         record gets identifier 1. The "TimeStamp" attribute always yields
76         the current time (i.e. the time when the log record is created, not the time
77         it was written to a sink). The last two attributes identify the process and
78         the thread in which every log record is emitted.
79       </p>
80 <div class="note"><table border="0" summary="Note">
81 <tr>
82 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td>
83 <th align="left">Note</th>
84 </tr>
85 <tr><td align="left" valign="top"><p>
86           In single-threaded builds the "ThreadID" attribute is not registered.
87         </p></td></tr>
88 </table></div>
89 <div class="tip"><table border="0" summary="Tip">
90 <tr>
91 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
92 <th align="left">Tip</th>
93 </tr>
94 <tr><td align="left" valign="top"><p>
95           By default, when application starts, no attributes are registered in the
96           library. The application has to register all the necessary attributes in
97           the library before it starts writing logs. This can be done as a part of
98           the library initialization. A curious reader could have wondered how trivial
99           logging works then. The answer is that the default sink doesn't really
100           use any attribute values, except for the severity level, to compose its
101           output. This is done to avoid the need for any initialization for trivial
102           logging. Once you use filters or formatters and non-default sinks you will
103           have to register the attributes you need.
104         </p></td></tr>
105 </table></div>
106 <p>
107         The <code class="computeroutput"><a class="link" href="../../boost/log/add_common_attributes.html" title="Function add_common_attributes">add_common_attributes</a></code>
108         function is one of the several convenience helpers described <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.convenience" title="Convenience functions">here</a>.
109       </p>
110 <p>
111         Some attributes are registered automatically on loggers construction. For
112         example, <a class="link" href="../detailed/sources.html#log.detailed.sources.severity_level_logger" title="Loggers with severity level support"><code class="computeroutput"><span class="identifier">severity_logger</span></code></a> registers a source-specific
113         attribute "Severity" which can be used to add a level of emphasis
114         for different log records. For example:
115       </p>
116 <p>
117 </p>
118 <pre class="programlisting"><span class="comment">// We define our own severity levels</span>
119 <span class="keyword">enum</span> <span class="identifier">severity_level</span>
120 <span class="special">{</span>
121     <span class="identifier">normal</span><span class="special">,</span>
122     <span class="identifier">notification</span><span class="special">,</span>
123     <span class="identifier">warning</span><span class="special">,</span>
124     <span class="identifier">error</span><span class="special">,</span>
125     <span class="identifier">critical</span>
126 <span class="special">};</span>
127
128 <span class="keyword">void</span> <span class="identifier">logging_function</span><span class="special">()</span>
129 <span class="special">{</span>
130     <span class="comment">// The logger implicitly adds a source-specific attribute 'Severity'</span>
131     <span class="comment">// of type 'severity_level' on construction</span>
132     <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special">&lt;</span> <span class="identifier">severity_level</span> <span class="special">&gt;</span> <span class="identifier">slg</span><span class="special">;</span>
133
134     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">normal</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"A regular message"</span><span class="special">;</span>
135     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">warning</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Something bad is going on but I can handle it"</span><span class="special">;</span>
136     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">critical</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Everything crumbles, shoot me now!"</span><span class="special">;</span>
137 <span class="special">}</span>
138 </pre>
139 <p>
140       </p>
141 <div class="tip"><table border="0" summary="Tip">
142 <tr>
143 <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
144 <th align="left">Tip</th>
145 </tr>
146 <tr><td align="left" valign="top"><p>
147           You can define your own formatting rules for the severity level by defining
148           <code class="computeroutput"><span class="keyword">operator</span> <span class="special">&lt;&lt;</span></code>
149           for this type. It will be automatically used by the library formatters.
150           See <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr" title="Generic attribute placeholder">this</a> section for
151           more details.
152         </p></td></tr>
153 </table></div>
154 <p>
155         The <code class="computeroutput"><span class="identifier">BOOST_LOG_SEV</span></code> macro acts
156         pretty much like <code class="computeroutput"><span class="identifier">BOOST_LOG</span></code>
157         except that it takes an additional argument for the <code class="computeroutput"><span class="identifier">open_record</span></code>
158         method of the logger. The <code class="computeroutput"><span class="identifier">BOOST_LOG_SEV</span></code>
159         macro can be replaced with this equivalent:
160       </p>
161 <p>
162 </p>
163 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">manual_logging</span><span class="special">()</span>
164 <span class="special">{</span>
165     <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special">&lt;</span> <span class="identifier">severity_level</span> <span class="special">&gt;</span> <span class="identifier">slg</span><span class="special">;</span>
166
167     <span class="identifier">logging</span><span class="special">::</span><span class="identifier">record</span> <span class="identifier">rec</span> <span class="special">=</span> <span class="identifier">slg</span><span class="special">.</span><span class="identifier">open_record</span><span class="special">(</span><span class="identifier">keywords</span><span class="special">::</span><span class="identifier">severity</span> <span class="special">=</span> <span class="identifier">normal</span><span class="special">);</span>
168     <span class="keyword">if</span> <span class="special">(</span><span class="identifier">rec</span><span class="special">)</span>
169     <span class="special">{</span>
170         <span class="identifier">logging</span><span class="special">::</span><span class="identifier">record_ostream</span> <span class="identifier">strm</span><span class="special">(</span><span class="identifier">rec</span><span class="special">);</span>
171         <span class="identifier">strm</span> <span class="special">&lt;&lt;</span> <span class="string">"A regular message"</span><span class="special">;</span>
172         <span class="identifier">strm</span><span class="special">.</span><span class="identifier">flush</span><span class="special">();</span>
173         <span class="identifier">slg</span><span class="special">.</span><span class="identifier">push_record</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">rec</span><span class="special">));</span>
174     <span class="special">}</span>
175 <span class="special">}</span>
176 </pre>
177 <p>
178       </p>
179 <p>
180         You can see here that the <code class="computeroutput"><span class="identifier">open_record</span></code>
181         can take named arguments. Some logger types provided by the library have
182         support for such additional parameters and this approach can certainly be
183         used by users when writing their own loggers.
184       </p>
185 <h5>
186 <a name="log.tutorial.attributes.h1"></a>
187         <span class="phrase"><a name="log.tutorial.attributes.more_attributes"></a></span><a class="link" href="attributes.html#log.tutorial.attributes.more_attributes">More
188         attributes</a>
189       </h5>
190 <p>
191         Let's see what's under the hood of that <a class="link" href="../detailed/utilities.html#log.detailed.utilities.setup.convenience" title="Convenience functions"><code class="computeroutput"><span class="identifier">add_common_attributes</span></code></a> function we
192         used in the simple form section. It might look something like this:
193       </p>
194 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">add_common_attributes</span><span class="special">()</span>
195 <span class="special">{</span>
196     <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">core</span> <span class="special">&gt;</span> <span class="identifier">core</span> <span class="special">=</span> <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">();</span>
197     <span class="identifier">core</span><span class="special">-&gt;</span><span class="identifier">add_global_attribute</span><span class="special">(</span><span class="string">"LineID"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">counter</span><span class="special">&lt;</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="special">&gt;(</span><span class="number">1</span><span class="special">));</span>
198     <span class="identifier">core</span><span class="special">-&gt;</span><span class="identifier">add_global_attribute</span><span class="special">(</span><span class="string">"TimeStamp"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">local_clock</span><span class="special">());</span>
199
200     <span class="comment">// other attributes skipped for brevity</span>
201 <span class="special">}</span>
202 </pre>
203 <p>
204         Here the <a class="link" href="../detailed/attributes.html#log.detailed.attributes.counter" title="Counters"><code class="computeroutput"><span class="identifier">counter</span></code></a>
205         and <a class="link" href="../detailed/attributes.html#log.detailed.attributes.clock" title="Wall clock"><code class="computeroutput"><span class="identifier">local_clock</span></code></a>
206         components are attribute classes, they derive from the common attribute interface
207         <code class="computeroutput"><a class="link" href="../../boost/log/attribute.html" title="Class attribute">attribute</a></code>. The library
208         provides a number of other <a class="link" href="../detailed/attributes.html" title="Attributes">attribute
209         classes</a>, including the <a class="link" href="../detailed/attributes.html#log.detailed.attributes.function" title="Function objects as attributes"><code class="computeroutput"><span class="identifier">function</span></code></a> attribute that calls some
210         function object on value acquisition. For example, we can in a similar way
211         register a <a class="link" href="../detailed/attributes.html#log.detailed.attributes.named_scope" title="Named scopes"><code class="computeroutput"><span class="identifier">named_scope</span></code></a> attribute:
212       </p>
213 <pre class="programlisting"><span class="identifier">core</span><span class="special">-&gt;</span><span class="identifier">add_global_attribute</span><span class="special">(</span><span class="string">"Scope"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">named_scope</span><span class="special">());</span>
214 </pre>
215 <p>
216         This will give us the ability to store scope names in log for every log record
217         the application makes. Here is how it's used:
218       </p>
219 <p>
220 </p>
221 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">named_scope_logging</span><span class="special">()</span>
222 <span class="special">{</span>
223     <span class="identifier">BOOST_LOG_NAMED_SCOPE</span><span class="special">(</span><span class="string">"named_scope_logging"</span><span class="special">);</span>
224
225     <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special">&lt;</span> <span class="identifier">severity_level</span> <span class="special">&gt;</span> <span class="identifier">slg</span><span class="special">;</span>
226
227     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">normal</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Hello from the function named_scope_logging!"</span><span class="special">;</span>
228 <span class="special">}</span>
229 </pre>
230 <p>
231       </p>
232 <p>
233         Logger-specific attributes are no less useful than global ones. Severity
234         levels and channel names are the most obvious candidates to be implemented
235         on the source level. Nothing prevents you from adding more attributes to
236         your loggers, like this:
237       </p>
238 <p>
239 </p>
240 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">tagged_logging</span><span class="special">()</span>
241 <span class="special">{</span>
242     <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special">&lt;</span> <span class="identifier">severity_level</span> <span class="special">&gt;</span> <span class="identifier">slg</span><span class="special">;</span>
243     <span class="identifier">slg</span><span class="special">.</span><span class="identifier">add_attribute</span><span class="special">(</span><span class="string">"Tag"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">constant</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="string">"My tag value"</span><span class="special">));</span>
244
245     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">normal</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Here goes the tagged record"</span><span class="special">;</span>
246 <span class="special">}</span>
247 </pre>
248 <p>
249       </p>
250 <p>
251         Now all log records made through this logger will be tagged with the specific
252         attribute. This attribute value may be used later in filtering and formatting.
253       </p>
254 <p>
255         Another good use of attributes is the ability to mark log records made by
256         different parts of application in order to highlight activity related to
257         a single process. One can even implement a rough profiling tool to detect
258         performance bottlenecks. For example:
259       </p>
260 <p>
261 </p>
262 <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">timed_logging</span><span class="special">()</span>
263 <span class="special">{</span>
264     <span class="identifier">BOOST_LOG_SCOPED_THREAD_ATTR</span><span class="special">(</span><span class="string">"Timeline"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">timer</span><span class="special">());</span>
265
266     <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special">&lt;</span> <span class="identifier">severity_level</span> <span class="special">&gt;</span> <span class="identifier">slg</span><span class="special">;</span>
267     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">normal</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Starting to time nested functions"</span><span class="special">;</span>
268
269     <span class="identifier">logging_function</span><span class="special">();</span>
270
271     <span class="identifier">BOOST_LOG_SEV</span><span class="special">(</span><span class="identifier">slg</span><span class="special">,</span> <span class="identifier">normal</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="string">"Stopping to time nested functions"</span><span class="special">;</span>
272 <span class="special">}</span>
273 </pre>
274 <p>
275       </p>
276 <p>
277         Now every log record made from the <code class="computeroutput"><span class="identifier">logging_function</span></code>
278         function, or any other function it calls, will contain the "Timeline"
279         attribute with a high precision time duration passed since the attribute
280         was registered. Based on these readings, one will be able to detect which
281         parts of the code require more or less time to execute. The "Timeline"
282         attribute will be unregistered upon leaving the scope of function <code class="computeroutput"><span class="identifier">timed_logging</span></code>.
283       </p>
284 <p>
285         See the <a class="link" href="../detailed/attributes.html" title="Attributes">Attributes</a> section
286         for detailed description of attributes provided by the library. The complete
287         code for this section is available <a href="../../../../../../libs/log/example/doc/tutorial_attributes.cpp" target="_top">here</a>.
288       </p>
289 <h5>
290 <a name="log.tutorial.attributes.h2"></a>
291         <span class="phrase"><a name="log.tutorial.attributes.defining_attribute_placeholders"></a></span><a class="link" href="attributes.html#log.tutorial.attributes.defining_attribute_placeholders">Defining
292         attribute placeholders</a>
293       </h5>
294 <p>
295         As we will see in the coming sections, it is useful to define a keyword describing
296         a particular attribute the application uses. This keyword will be able to
297         participate in filtering and formatting expressions, like the <code class="computeroutput"><span class="identifier">severity</span></code> placeholder we have used in previous
298         sections. For example, to define placeholders for some of the attributes
299         we used in the previous examples we can write this:
300       </p>
301 <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>
302 <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>
303 <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>
304 <span class="identifier">BOOST_LOG_ATTRIBUTE_KEYWORD</span><span class="special">(</span><span class="identifier">scope</span><span class="special">,</span> <span class="string">"Scope"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">named_scope</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">)</span>
305 <span class="identifier">BOOST_LOG_ATTRIBUTE_KEYWORD</span><span class="special">(</span><span class="identifier">timeline</span><span class="special">,</span> <span class="string">"Timeline"</span><span class="special">,</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">timer</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">)</span>
306 </pre>
307 <p>
308         Each macro defines a keyword. The first argument is the placeholder name,
309         the second is the attribute name and the last parameter is the attribute
310         value type. Once defined, the placeholder can be used in template expressions
311         and some other contexts of the library. More details on defining attribute
312         keywords are available <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr_keywords" title="Defining attribute keywords">here</a>.
313       </p>
314 </div>
315 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
316 <td align="left"></td>
317 <td align="right"><div class="copyright-footer">Copyright &#169; 2007-2014 Andrey Semashev<p>
318         Distributed under the Boost Software License, Version 1.0. (See accompanying
319         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>).
320       </p>
321 </div></td>
322 </tr></table>
323 <hr>
324 <div class="spirit-nav">
325 <a accesskey="p" href="sources.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="formatters.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
326 </div>
327 </body>
328 </html>