| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>Adding more information to log: Attributes</title> |
| <link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.78.1"> |
| <link rel="home" href="../../index.html" title="Chapter 1. Boost.Log v2"> |
| <link rel="up" href="../tutorial.html" title="Tutorial"> |
| <link rel="prev" href="sources.html" title="Creating loggers and writing logs"> |
| <link rel="next" href="formatters.html" title="Log record formatting"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <table cellpadding="2" width="100%"><tr><td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td></tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <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> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="log.tutorial.attributes"></a><a class="link" href="attributes.html" title="Adding more information to log: Attributes">Adding more information to log: |
| Attributes</a> |
| </h3></div></div></div> |
| <p> |
| In previous sections we mentioned attributes and attribute values several |
| times. Here we will discover how attributes can be used to add more data |
| to log records. |
| </p> |
| <p> |
| Each log record can have a number of named attribute values attached. Attributes |
| can represent any essential information about the conditions in which the |
| log record occurred, such as position in the code, executable module name, |
| current date and time, or any piece of data relevant to your particular application |
| and execution environment. An attribute may behave as a value generator, |
| in which case it would return a different value for each log record it's |
| involved in. As soon as the attribute generates the value, the latter becomes |
| independent from the creator and can be used by filters, formatters and sinks. |
| But in order to use the attribute value one has to know its name and type, |
| or at least a set of types it may have. There are a number of commonly used |
| attributes implemented in the library, you can find the types of their values |
| in the documentation. |
| </p> |
| <p> |
| Aside from that, as described in the <a class="link" href="../design.html" title="Design overview">Design overview</a> |
| section, there are three possible scopes of attributes: source-specific, |
| thread-specific and global. When a log record is made, attribute values from |
| these three sets are joined into a single set and passed to sinks. This implies |
| that the origin of the attribute makes no difference for sinks. Any attribute |
| can be registered in any scope. When registered, an attribute is given a |
| unique name in order to make it possible to search for it. If it happens |
| that the same named attribute is found in several scopes, the attribute from |
| the most specific scope is taken into consideration in any further processing, |
| including filtering and formatting. Such behavior makes it possible to override |
| global or thread-scoped attributes with the ones registered in your local |
| logger, thus reducing thread interference. |
| </p> |
| <p> |
| Below is the description of the attribute registration process. |
| </p> |
| <h5> |
| <a name="log.tutorial.attributes.h0"></a> |
| <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 |
| used attributes</a> |
| </h5> |
| <p> |
| There are attributes that are likely to be used in nearly any application. |
| Log record counter and a time stamp are good candidates. They can be added |
| with a single function call: |
| </p> |
| <pre class="programlisting"><span class="identifier">logging</span><span class="special">::</span><span class="identifier">add_common_attributes</span><span class="special">();</span> |
| </pre> |
| <p> |
| With this call attributes "LineID", "TimeStamp", "ProcessID" |
| and "ThreadID" are registered globally. The "LineID" |
| attribute is a counter that increments for each record being made, the first |
| record gets identifier 1. The "TimeStamp" attribute always yields |
| the current time (i.e. the time when the log record is created, not the time |
| it was written to a sink). The last two attributes identify the process and |
| the thread in which every log record is emitted. |
| </p> |
| <div class="note"><table border="0" summary="Note"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../doc/src/images/note.png"></td> |
| <th align="left">Note</th> |
| </tr> |
| <tr><td align="left" valign="top"><p> |
| In single-threaded builds the "ThreadID" attribute is not registered. |
| </p></td></tr> |
| </table></div> |
| <div class="tip"><table border="0" summary="Tip"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td> |
| <th align="left">Tip</th> |
| </tr> |
| <tr><td align="left" valign="top"><p> |
| By default, when application starts, no attributes are registered in the |
| library. The application has to register all the necessary attributes in |
| the library before it starts writing logs. This can be done as a part of |
| the library initialization. A curious reader could have wondered how trivial |
| logging works then. The answer is that the default sink doesn't really |
| use any attribute values, except for the severity level, to compose its |
| output. This is done to avoid the need for any initialization for trivial |
| logging. Once you use filters or formatters and non-default sinks you will |
| have to register the attributes you need. |
| </p></td></tr> |
| </table></div> |
| <p> |
| The <code class="computeroutput"><a class="link" href="../../boost/log/add_common_attributes.html" title="Function add_common_attributes">add_common_attributes</a></code> |
| 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>. |
| </p> |
| <p> |
| Some attributes are registered automatically on loggers construction. For |
| 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 |
| attribute "Severity" which can be used to add a level of emphasis |
| for different log records. For example: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="comment">// We define our own severity levels</span> |
| <span class="keyword">enum</span> <span class="identifier">severity_level</span> |
| <span class="special">{</span> |
| <span class="identifier">normal</span><span class="special">,</span> |
| <span class="identifier">notification</span><span class="special">,</span> |
| <span class="identifier">warning</span><span class="special">,</span> |
| <span class="identifier">error</span><span class="special">,</span> |
| <span class="identifier">critical</span> |
| <span class="special">};</span> |
| |
| <span class="keyword">void</span> <span class="identifier">logging_function</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">// The logger implicitly adds a source-specific attribute 'Severity'</span> |
| <span class="comment">// of type 'severity_level' on construction</span> |
| <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special"><</span> <span class="identifier">severity_level</span> <span class="special">></span> <span class="identifier">slg</span><span class="special">;</span> |
| |
| <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"><<</span> <span class="string">"A regular message"</span><span class="special">;</span> |
| <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"><<</span> <span class="string">"Something bad is going on but I can handle it"</span><span class="special">;</span> |
| <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"><<</span> <span class="string">"Everything crumbles, shoot me now!"</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <div class="tip"><table border="0" summary="Tip"> |
| <tr> |
| <td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td> |
| <th align="left">Tip</th> |
| </tr> |
| <tr><td align="left" valign="top"><p> |
| You can define your own formatting rules for the severity level by defining |
| <code class="computeroutput"><span class="keyword">operator</span> <span class="special"><<</span></code> |
| for this type. It will be automatically used by the library formatters. |
| See <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr" title="Generic attribute placeholder">this</a> section for |
| more details. |
| </p></td></tr> |
| </table></div> |
| <p> |
| The <code class="computeroutput"><span class="identifier">BOOST_LOG_SEV</span></code> macro acts |
| pretty much like <code class="computeroutput"><span class="identifier">BOOST_LOG</span></code> |
| except that it takes an additional argument for the <code class="computeroutput"><span class="identifier">open_record</span></code> |
| method of the logger. The <code class="computeroutput"><span class="identifier">BOOST_LOG_SEV</span></code> |
| macro can be replaced with this equivalent: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">manual_logging</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special"><</span> <span class="identifier">severity_level</span> <span class="special">></span> <span class="identifier">slg</span><span class="special">;</span> |
| |
| <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> |
| <span class="keyword">if</span> <span class="special">(</span><span class="identifier">rec</span><span class="special">)</span> |
| <span class="special">{</span> |
| <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> |
| <span class="identifier">strm</span> <span class="special"><<</span> <span class="string">"A regular message"</span><span class="special">;</span> |
| <span class="identifier">strm</span><span class="special">.</span><span class="identifier">flush</span><span class="special">();</span> |
| <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> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| You can see here that the <code class="computeroutput"><span class="identifier">open_record</span></code> |
| can take named arguments. Some logger types provided by the library have |
| support for such additional parameters and this approach can certainly be |
| used by users when writing their own loggers. |
| </p> |
| <h5> |
| <a name="log.tutorial.attributes.h1"></a> |
| <span class="phrase"><a name="log.tutorial.attributes.more_attributes"></a></span><a class="link" href="attributes.html#log.tutorial.attributes.more_attributes">More |
| attributes</a> |
| </h5> |
| <p> |
| 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 |
| used in the simple form section. It might look something like this: |
| </p> |
| <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">add_common_attributes</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</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">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> |
| <span class="identifier">core</span><span class="special">-></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"><</span> <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="special">>(</span><span class="number">1</span><span class="special">));</span> |
| <span class="identifier">core</span><span class="special">-></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> |
| |
| <span class="comment">// other attributes skipped for brevity</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| 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> |
| 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> |
| components are attribute classes, they derive from the common attribute interface |
| <code class="computeroutput"><a class="link" href="../../boost/log/attribute.html" title="Class attribute">attribute</a></code>. The library |
| provides a number of other <a class="link" href="../detailed/attributes.html" title="Attributes">attribute |
| 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 |
| function object on value acquisition. For example, we can in a similar way |
| 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: |
| </p> |
| <pre class="programlisting"><span class="identifier">core</span><span class="special">-></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> |
| </pre> |
| <p> |
| This will give us the ability to store scope names in log for every log record |
| the application makes. Here is how it's used: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">named_scope_logging</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="identifier">BOOST_LOG_NAMED_SCOPE</span><span class="special">(</span><span class="string">"named_scope_logging"</span><span class="special">);</span> |
| |
| <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special"><</span> <span class="identifier">severity_level</span> <span class="special">></span> <span class="identifier">slg</span><span class="special">;</span> |
| |
| <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"><<</span> <span class="string">"Hello from the function named_scope_logging!"</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Logger-specific attributes are no less useful than global ones. Severity |
| levels and channel names are the most obvious candidates to be implemented |
| on the source level. Nothing prevents you from adding more attributes to |
| your loggers, like this: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">tagged_logging</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special"><</span> <span class="identifier">severity_level</span> <span class="special">></span> <span class="identifier">slg</span><span class="special">;</span> |
| <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"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">>(</span><span class="string">"My tag value"</span><span class="special">));</span> |
| |
| <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"><<</span> <span class="string">"Here goes the tagged record"</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Now all log records made through this logger will be tagged with the specific |
| attribute. This attribute value may be used later in filtering and formatting. |
| </p> |
| <p> |
| Another good use of attributes is the ability to mark log records made by |
| different parts of application in order to highlight activity related to |
| a single process. One can even implement a rough profiling tool to detect |
| performance bottlenecks. For example: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="keyword">void</span> <span class="identifier">timed_logging</span><span class="special">()</span> |
| <span class="special">{</span> |
| <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> |
| |
| <span class="identifier">src</span><span class="special">::</span><span class="identifier">severity_logger</span><span class="special"><</span> <span class="identifier">severity_level</span> <span class="special">></span> <span class="identifier">slg</span><span class="special">;</span> |
| <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"><<</span> <span class="string">"Starting to time nested functions"</span><span class="special">;</span> |
| |
| <span class="identifier">logging_function</span><span class="special">();</span> |
| |
| <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"><<</span> <span class="string">"Stopping to time nested functions"</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| Now every log record made from the <code class="computeroutput"><span class="identifier">logging_function</span></code> |
| function, or any other function it calls, will contain the "Timeline" |
| attribute with a high precision time duration passed since the attribute |
| was registered. Based on these readings, one will be able to detect which |
| parts of the code require more or less time to execute. The "Timeline" |
| attribute will be unregistered upon leaving the scope of function <code class="computeroutput"><span class="identifier">timed_logging</span></code>. |
| </p> |
| <p> |
| See the <a class="link" href="../detailed/attributes.html" title="Attributes">Attributes</a> section |
| for detailed description of attributes provided by the library. The complete |
| code for this section is available <a href="../../../../../../libs/log/example/doc/tutorial_attributes.cpp" target="_top">here</a>. |
| </p> |
| <h5> |
| <a name="log.tutorial.attributes.h2"></a> |
| <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 |
| attribute placeholders</a> |
| </h5> |
| <p> |
| As we will see in the coming sections, it is useful to define a keyword describing |
| a particular attribute the application uses. This keyword will be able to |
| participate in filtering and formatting expressions, like the <code class="computeroutput"><span class="identifier">severity</span></code> placeholder we have used in previous |
| sections. For example, to define placeholders for some of the attributes |
| we used in the previous examples we can write this: |
| </p> |
| <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> |
| <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> |
| <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> |
| <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> |
| <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> |
| </pre> |
| <p> |
| Each macro defines a keyword. The first argument is the placeholder name, |
| the second is the attribute name and the last parameter is the attribute |
| value type. Once defined, the placeholder can be used in template expressions |
| and some other contexts of the library. More details on defining attribute |
| keywords are available <a class="link" href="../detailed/expressions.html#log.detailed.expressions.attr_keywords" title="Defining attribute keywords">here</a>. |
| </p> |
| </div> |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> |
| <td align="left"></td> |
| <td align="right"><div class="copyright-footer">Copyright © 2007-2015 Andrey |
| Semashev<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 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>). |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <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> |
| </div> |
| </body> |
| </html> |