| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <!-- Generated by Apache Maven Doxia at 2020-08-22 --> |
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
| <title>log4cxx - |
| How to use Apache log4cxx - Apache log4cxx</title> |
| <link rel="stylesheet" href="./css/bootstrap.min.css" type="text/css" /> |
| <link rel="stylesheet" href="./css/site.css" type="text/css" /> |
| <script type="text/javascript" src="./js/jquery.min.js"></script> |
| <script type="text/javascript" src="./js/bootstrap.min.js"></script> |
| <script type="text/javascript" src="./js/prettify.min.js"></script> |
| <script type="text/javascript" src="./js/site.js"></script> |
| <meta name="Date-Revision-yyyymmdd" content="20200822" /> |
| <meta http-equiv="Content-Language" content="en" /> |
| |
| </head> |
| <body class="composite"> |
| <a href="https://logging.apache.org/"> |
| <img class="logo-left" src="./images/logos/ls-logo.jpg" alt="Apache logging services logo" /> |
| </a> |
| <img class="logo-right" src="./images/logos/logo.png" alt="Apache log4j logo" /> |
| <div class="clear"></div> |
| |
| <div class="navbar"> |
| <div class="navbar-inner"> |
| <div class="container-fluid"> |
| <a class="brand" href="http://logging.apache.org/log4cxx">Apache log4cxx ™</a> |
| <ul class="nav"> |
| <li> |
| |
| |
| <a href="https://wiki.apache.org/logging" class="external" target="_blank" title="Logging Wiki">Logging Wiki</a> |
| </li> |
| <li> |
| |
| |
| <a href="https://www.apache.org/" class="external" target="_blank" title="Apache">Apache</a> |
| </li> |
| <li> |
| |
| |
| <a href="https://logging.apache.org/" class="external" target="_blank" title="Logging Services">Logging Services</a> |
| </li> |
| <li> |
| |
| |
| <a href="https://github.com/apache/logging-log4cxx" class="external" target="_blank" title="GitHub">GitHub</a> |
| </li> |
| </ul> |
| |
| <div class="pull-right"> |
| |
| |
| <span id="publishDate">Last Published: 2020-08-22</span> |
| <span class="divider">|</span> <span id="projectVersion">Version: 0.11.0</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="container-fluid"> |
| <table class="layout-table"> |
| <tr> |
| <td class="sidebar"> |
| <div class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-home"></i>About</li> |
| <li class="none"> |
| <a href="index.html" title="What is log4cxx?">What is log4cxx?</a> |
| </li> |
| <li class="none"> |
| <a href="project-info.html" title="Project Information">Project Information</a> |
| </li> |
| <li class="none"> |
| <a href="project-reports.html" title="Generated Reports">Generated Reports</a> |
| </li> |
| </ul> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-book"></i>Usage</li> |
| <li class="none active"> |
| <a href="usage.html" title="How to use log4cxx?">How to use log4cxx?</a> |
| </li> |
| <li class="none"> |
| <a href="apidocs/index.html" title="API Documentation">API Documentation</a> |
| </li> |
| <li class="none"> |
| <a href="faq.html" title="FAQ">FAQ</a> |
| </li> |
| </ul> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-cog"></i>Get</li> |
| <li class="none"> |
| <a href="download.html" title="Download">Download</a> |
| </li> |
| <li class="none"> |
| <a href="changes-report.html" title="Changes">Changes</a> |
| </li> |
| <li class="none"> |
| <a href="license.html" title="License">License</a> |
| </li> |
| </ul> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-pencil"></i>Community</li> |
| <li class="none"> |
| <a href="mail-lists.html" title="Mailing Lists">Mailing Lists</a> |
| </li> |
| <li class="none"> |
| <a href="community/issue-tracking.html" title="Issue Tracking">Issue Tracking</a> |
| </li> |
| <li class="none"> |
| |
| |
| <a href="https://wiki.apache.org/logging-log4cxx" class="external" target="_blank" title="Wiki">Wiki</a> |
| </li> |
| </ul> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-pencil"></i>Development</li> |
| <li class="none"> |
| <a href="source-repository.html" title="Repository">Repository</a> |
| </li> |
| <li class="none"> |
| <a href="dependencies.html" title="Dependencies">Dependencies</a> |
| </li> |
| <li class="expanded"> |
| <a href="building/index.html" title="Building">Building</a> |
| <ul> |
| <li class="none"> |
| <a href="building/maven.html" title="Apache Maven 2">Apache Maven 2</a> |
| </li> |
| <li class="none"> |
| <a href="building/autotools.html" title="Autotools">Autotools</a> |
| </li> |
| <li class="none"> |
| <a href="building/cmake.html" title="CMake">CMake</a> |
| </li> |
| <li class="none"> |
| <a href="building/vcpkg.html" title="Microsoft vcpkg">Microsoft vcpkg</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><i class="icon-info-sign"></i>Apache</li> |
| <li class="none"> |
| |
| |
| <a href="https://www.apache.org" class="external" target="_blank" title="Home">Home</a> |
| </li> |
| <li class="none"> |
| |
| |
| <a href="https://www.apache.org/foundation/sponsorship.html" class="external" target="_blank" title="Sponsorship">Sponsorship</a> |
| </li> |
| <li class="none"> |
| |
| |
| <a href="https://www.apache.org/foundation/thanks.html" class="external" target="_blank" title="Thanks">Thanks</a> |
| </li> |
| <li class="none"> |
| |
| |
| <a href="https://www.apachecon.com" class="external" target="_blank" title="Conferences">Conferences</a> |
| </li> |
| </ul> |
| </div> |
| <div id="poweredBy"> |
| <a href="https://maven.apache.org/" title="Built by Maven" class="poweredBy"> |
| <img class="poweredBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /> |
| </a> |
| </div> |
| </td> |
| <td class="content"> |
| <!-- Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. --> |
| |
| <div class="section"> |
| <h2>Loggers<a name="Loggers"></a></h2> |
| |
| <p> |
| Log4cxx has three main components: <i>loggers</i>, |
| <i>appenders</i> and <i>layouts</i>. These three types of |
| components work together to enable developers to log messages according |
| to message type and level, and to control at runtime how these |
| messages are formatted and where they are reported. |
| </p> |
| |
| |
| <div class="section"> |
| <h3>Hierarchy<a name="Hierarchy"></a></h3> |
| |
| <p> |
| The first and foremost advantage of any logging API over plain |
| <tt>std::cout</tt> resides in its ability to disable |
| certain log statements while allowing others to print unhindered. This |
| capability assumes that the logging space, that is, the space of all |
| possible logging statements, is categorized according to some |
| developer-chosen criteria. |
| </p> |
| |
| |
| <p> |
| Loggers are named entities. Logger names are case-sensitive and |
| they follow the hierarchical naming rule: |
| </p> |
| |
| |
| <dl> |
| |
| <dt><b>Named Hierarchy</b></dt> |
| |
| <dd> |
| A logger is said to be an <i>ancestor</i> of another |
| logger if its name followed by a dot is a prefix of the |
| <i>descendant</i> logger name. A logger is said to be a |
| <i>parent</i> of a <i>child</i> logger if there are no |
| ancestors between itself and the descendant logger. |
| </dd> |
| </dl> |
| |
| |
| <p> |
| For example, the logger named <tt>"com.foo"</tt> is a parent |
| of the logger named <tt>"com.foo.Bar"</tt>. Similarly, |
| <tt>"java"</tt> is a parent of <tt>"java.util"</tt> and an |
| ancestor of <tt>"java.util.Vector"</tt>. This naming scheme |
| should be familiar to most developers. |
| </p> |
| |
| |
| <p> |
| The root logger resides at the top of the logger hierarchy. It |
| is exceptional in two ways: |
| </p> |
| |
| |
| <ol style="list-style-type: decimal"> |
| |
| <li> it always exists,</li> |
| |
| <li> it cannot be retrieved by name.</li> |
| </ol> |
| |
| |
| <p> |
| Invoking the class static <a href="apidocs/classlog4cxx_1_1_logger.html#afc0e4d99cab7c38a2851d41e6edc1dee">log4cxx::Logger::getRootLogger</a> |
| method retrieves it. All other loggers are instantiated and retrieved with the class static |
| <a href="apidocs/classlog4cxx_1_1_logger.html#a76017df17da02bc11bfe50e47de703a3">log4cxx::Logger::getLogger</a> |
| method. This method takes the name of the desired logger as a parameter. Some of the basic methods in the Logger |
| class are listed below. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| namespace log4cxx { |
| class <b>Logger</b> { |
| public: |
| // Creation & retrieval methods: |
| static LoggerPtr getRootLogger(); |
| static LoggerPtr getLogger(const std::string& name); |
| static LoggerPtr getLogger(const std::wstring& name); |
| } |
| } |
| |
| // |
| // Use these macros instead of calling Logger methods directly. |
| // Macros will handle char or wchar_t pointers or strings |
| // or most right-hand side expressions of an |
| // std::basic_string::operator<<. |
| // |
| #define LOG4CXX_TRACE(logger, expression) ... |
| #define LOG4CXX_DEBUG(logger, expression) ... |
| #define LOG4CXX_INFO(logger, expression) ... |
| #define LOG4CXX_WARN(logger, expression) ... |
| #define LOG4CXX_ERROR(logger, expression) ... |
| #define LOG4CXX_FATAL(logger, expression) ...</pre></div> |
| </div> |
| |
| |
| <div class="section"> |
| <h3>Levels<a name="Levels"></a></h3> |
| |
| <p> |
| Loggers <i>may</i> be assigned levels. The pre-defined |
| levels: TRACE, DEBUG, INFO, WARN, ERROR and FATAL are defined in the |
| <tt><a href="apidocs/classlog4cxx_1_1_level.html">log4cxx::Level</a></tt> |
| class which provides accessor functions. |
| </p> |
| |
| |
| <p> |
| If a given logger is not assigned a level, then it inherits |
| one from its closest ancestor with an assigned level. More |
| formally: |
| </p> |
| |
| |
| <dl> |
| |
| <dt><b>Level Inheritance</b></dt> |
| |
| |
| <dd> |
| The <i>inherited level</i> for a given logger <i>C</i>, is equal to the |
| first non-null level in the logger hierarchy, starting at <i>C</i> and |
| proceeding upwards in the hierarchy towards the <tt>root</tt> logger. |
| </dd> |
| </dl> |
| |
| |
| <p> |
| To ensure that all loggers can eventually inherit a level, |
| the root logger always has an assigned level. |
| </p> |
| |
| |
| <p> |
| Below are four tables with various assigned level values and the |
| resulting inherited levels according to the above rule. |
| </p> |
| |
| |
| <table class="bodyTable" border="1"><caption align="bottom">Example 1</caption> |
| |
| <tr class="a"> |
| |
| <th>Logger name</th> |
| |
| <th>Assigned level</th> |
| |
| <th>Inherited level</th> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>root</td> |
| |
| <td>Proot</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X </td> |
| |
| <td>none</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>X.Y </td> |
| |
| <td>none</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X.Y.Z</td> |
| |
| <td>none</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| </table> |
| |
| |
| <p> |
| In example 1 above, only the root logger is assigned a |
| level. This level value, <tt>Proot</tt>, is inherited by the |
| other loggers <tt>X</tt>, <tt>X.Y</tt> and |
| <tt>X.Y.Z</tt>. |
| </p> |
| |
| |
| <table class="bodyTable" border="1"><caption align="bottom">Example 2</caption> |
| |
| <tr class="a"> |
| |
| <th>Logger name</th> |
| |
| <th>Assigned level</th> |
| |
| <th>Inherited level</th> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>root</td> |
| |
| <td>Proot</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X </td> |
| |
| <td>Px</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>X.Y </td> |
| |
| <td>Pxy</td> |
| |
| <td>Pxy</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X.Y.Z</td> |
| |
| <td>Pxyz</td> |
| |
| <td>Pxyz</td> |
| </tr> |
| |
| </table> |
| |
| |
| <p> |
| In example 2, all loggers have an assigned level value. There |
| is no need for level inheritence. |
| </p> |
| |
| |
| <table class="bodyTable" border="1"><caption align="bottom">Example 3</caption> |
| |
| <tr class="a"> |
| |
| <th>Logger name</th> |
| |
| <th>Assigned level</th> |
| |
| <th>Inherited level</th> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>root</td> |
| |
| <td>Proot</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X </td> |
| |
| <td>Px</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>X.Y </td> |
| |
| <td>none</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X.Y.Z</td> |
| |
| <td>Pxyz</td> |
| |
| <td>Pxyz</td> |
| </tr> |
| |
| </table> |
| |
| |
| <p> |
| In example 3, the loggers <tt>root</tt>, <tt>X</tt> and |
| <tt>X.Y.Z</tt> are assigned the levels <tt>Proot</tt>, |
| <tt>Px</tt> and <tt>Pxyz</tt> respectively. The logger |
| <tt>X.Y</tt> inherits its level value from its parent |
| <tt>X</tt>. |
| </p> |
| |
| |
| <table class="bodyTable" border="1"><caption align="bottom">Example 4</caption> |
| |
| <tr class="a"> |
| |
| <th>Logger name</th> |
| |
| <th>Assigned level</th> |
| |
| <th>Inherited level</th> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>root</td> |
| |
| <td>Proot</td> |
| |
| <td>Proot</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X </td> |
| |
| <td>Px</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| <tr class="b" align="left"> |
| |
| <td>X.Y </td> |
| |
| <td>none</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| <tr class="a" align="left"> |
| |
| <td>X.Y.Z</td> |
| |
| <td>none</td> |
| |
| <td>Px</td> |
| </tr> |
| |
| </table> |
| |
| |
| <p> |
| In example 4, the loggers <tt>root</tt> and <tt>X</tt> |
| and are assigned the levels <tt>Proot</tt> and <tt>Px</tt> |
| respectively. The loggers <tt>X.Y</tt> and <tt>X.Y.Z</tt> |
| inherits their level value from their nearest parent <tt>X</tt> |
| having an assigned level. |
| </p> |
| </div> |
| |
| |
| <div class="section"> |
| <h3>Requests<a name="Requests"></a></h3> |
| |
| <p> |
| Logging requests are made by invoking a method of |
| a logger instance, preferrably through the use of LOG4CXX_INFO or similar |
| macros which support short-circuiting if the threshold is not satisfied |
| and use of the insertion operator (<<) in the message parameter. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(<b>"com.foo"</b>)); |
| const char* region = "World"; |
| LOG4CXX_INFO(logger, "Simple message text.") |
| LOG4CXX_INFO(logger, "Hello, " << region) |
| LOG4CXX_DEBUG(logger, L"Iteration " << i) |
| LOG4CXX_DEBUG(logger, "e^10 = " << std::scientific << exp(10.0)) |
| // |
| // Use a wchar_t first operand to force use of wchar_t based stream. |
| // |
| LOG4CXX_WARN(logger, L"" << i << L" is the number of the iteration.")</pre></div> |
| |
| |
| <p> |
| A logging request is said to be <i>enabled</i> if its level is |
| higher than or equal to the level of its logger. Otherwise, the |
| request is said to be <i>disabled</i>. A logger without an |
| assigned level will inherit one from the hierarchy. This rule is |
| summarized below. |
| </p> |
| |
| |
| <dl> |
| |
| <dt><b>Basic Selection Rule</b></dt> |
| |
| |
| <dd> |
| A log request of level <i>p</i> in a logger with (either assigned or |
| inherited, whichever is appropriate) level <i>q</i>, is enabled if |
| <i>p >= q</i>. |
| </dd> |
| </dl> |
| |
| |
| <p> |
| This rule is at the heart of log4cxx. It assumes that levels are |
| ordered. For the standard levels, we have <tt>TRACE < DEBUG < INFO |
| < WARN < ERROR < FATAL</tt>. |
| </p> |
| |
| |
| <p> |
| Here is an example of this rule. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| // get a logger instance named "com.foo" |
| log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger(<b>"com.foo"</b>)); |
| |
| // Now set its level. Normally you do not need to set the |
| // level of a logger programmatically. This is usually done |
| // in configuration files. |
| <b>logger</b>->setLevel(<b>log4cxx::Level::getInfo()</b>); |
| |
| log4cxx::LoggerPtr barlogger(log4cxx::Logger::getLogger(<b>"com.foo.Bar"</b>)); |
| |
| // This request is enabled, because <b>WARN</b> >= <b>INFO</b>. |
| LOG4CXX_WARN(logger, "Low fuel level.") |
| |
| // This request is disabled, because <b>DEBUG</b> < <b>INFO</b>. |
| LOG4CXX_DEBUG(logger, "Starting search for nearest gas station.") |
| |
| // The logger instance barlogger, named "com.foo.Bar", |
| // will inherit its level from the logger named |
| // "com.foo" Thus, the following request is enabled |
| // because <b>INFO</b> >= <b>INFO</b>. |
| LOG4CXX_INFO(barlogger. "Located nearest gas station.") |
| |
| // This request is disabled, because <b>DEBUG</b> < <b>INFO</b>. |
| LOG4CXX_DEBUG(barlogger, "Exiting gas station search")</pre></div> |
| |
| |
| <p> |
| Calling the <tt>getLogger</tt> method with the same name will |
| always return a reference to the exact same logger object. |
| </p> |
| |
| |
| <p> |
| For example, in |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| log4cxx::LoggerPtr x = log4cxx::Logger::getLogger("wombat"); |
| log4cxx::LoggerPtr y = log4cxx::Logger::getLogger("wombat");</pre></div> |
| |
| <p> |
| <tt>x</tt> and <tt>y</tt> refer to <i>exactly</i> the same logger object. |
| </p> |
| |
| |
| <p> |
| Thus, it is possible to configure a logger and then to retrieve |
| the same instance somewhere else in the code without passing around |
| references. In fundamental contradiction to biological parenthood, |
| where parents always preceed their children, log4cxx loggers can be |
| created and configured in any order. In particular, a "parent" |
| logger will find and link to its descendants even if it is |
| instantiated after them. |
| </p> |
| |
| |
| <p> |
| Configuration of the log4cxx environment is typically done at |
| application initialization. The preferred way is by reading a |
| configuration file. This approach will be discussed shortly. |
| </p> |
| |
| |
| <p> |
| Log4cxx makes it easy to name loggers by <i>software |
| component</i>. This can be accomplished by statically instantiating |
| a logger in each class, with the logger name equal to the fully |
| qualified name of the class. This is a useful and straightforward |
| method of defining loggers. As the log output bears the name of the |
| generating logger, this naming strategy makes it easy to identify |
| the origin of a log message. However, this is only one possible, |
| albeit common, strategy for naming loggers. Log4cxx does not restrict |
| the possible set of loggers. The developer is free to name the |
| loggers as desired. |
| </p> |
| |
| |
| <p> |
| Nevertheless, naming loggers after the class where they are |
| located seems to be the best strategy known so far. |
| </p> |
| </div> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Appenders and Layouts<a name="Appenders_and_Layouts"></a></h2> |
| |
| <p> |
| The ability to selectively enable or disable logging requests based |
| on their logger is only part of the picture. Log4cxx allows logging |
| requests to print to multiple destinations. In log4cxx speak, an output |
| destination is called an <i>appender</i>. Currently, appenders exist |
| for the <a href="apidocs/classlog4cxx_1_1_console_appender.html">console</a>, |
| <a href="apidocs/classlog4cxx_1_1_file_appender.html">files</a>, GUI |
| components, <a href="apidocs/classlog4cxx_1_1net_1_1_socket_appender.html">remote socket</a> |
| servers, <a href="apidocs/classlog4cxx_1_1nt_1_1_n_t_event_log_appender.html"> NT Event Loggers</a>, and remote UNIX |
| <a href="apidocs/classlog4cxx_1_1net_1_1_syslog_appender.html">Syslog</a> |
| daemons. It is also possible to log <a href="apidocs/classlog4cxx_1_1_async_appender.html">asynchronously</a>. |
| </p> |
| |
| |
| <p>More than one appender can be attached to a logger.</p> |
| |
| |
| <p> |
| The <a href="apidocs/classlog4cxx_1_1_logger.html#a7c0629acee8dbd1251474bea15d7c9e2">addAppender</a> |
| method adds an appender to a given logger. |
| |
| <b> |
| Each enabled logging request for a given logger will be forwarded to all the |
| appenders in that logger as well as the appenders higher in the hierarchy. |
| </b> |
| In other words, appenders are inherited additively from the logger hierarchy. |
| For example, if a console appender is added to the root logger, then all enabled |
| logging requests will at least print on the console. If in addition a file appender |
| is added to a logger, say <i>C</i>, then enabled logging requests for <i>C</i> and |
| <i>C</i>'s children will print on a file <i>and</i> on the console. It is possible |
| to override this default behavior so that appender accumulation is no longer additive |
| by <a href="apidocs/classlog4cxx_1_1_logger.html#a80f9397947dba9071ad485f178257c17">setting the additivity flag</a> to |
| <tt>false</tt>. |
| </p> |
| |
| |
| <p>The rules governing appender additivity are summarized below.</p> |
| |
| |
| <dl> |
| |
| <dt><b>Appender Additivity</b></dt> |
| |
| |
| <dd> |
| The output of a log statement of logger <i>C</i> will go to all the appenders |
| in <i>C</i> and its ancestors. This is the meaning of the term "appender |
| additivity". However, if an ancestor of logger <i>C</i>, say <i>P</i>, has the |
| additivity flag set to <tt>false</tt>, then <i>C</i>'s output will be |
| directed to all the appenders in <i>C</i> and it's ancestors up to and |
| including <i>P</i> but, not the appenders in any of the ancestors of <i>P</i>. |
| <br /><br /> |
| Loggers have their additivity flag set to <tt>true</tt> by default. |
| </dd> |
| </dl> |
| |
| |
| <p>The table below shows an example:</p> |
| |
| |
| <table class="bodyTable" align="center" border="3" cellpadding="10"> |
| |
| <tr class="a"> |
| |
| <th>Logger Name </th> |
| |
| <th>Added Appenders</th> |
| |
| <th>Additivity Flag</th> |
| |
| <th>Output Targets</th> |
| |
| <th>Comment</th> |
| </tr> |
| |
| <tr class="b"> |
| |
| <td>root</td> |
| |
| <td>A1</td> |
| |
| <td>not applicable</td> |
| |
| <td>A1</td> |
| |
| <td> |
| The root logger is anonymous but can be accessed with the |
| log4cxx::Logger::getRootLogger() method. There is no default appender |
| attached to root. |
| </td> |
| </tr> |
| |
| <tr class="a"> |
| |
| <td>x</td> |
| |
| <td>A-x1, A-x2</td> |
| |
| <td>true</td> |
| |
| <td>A1, A-x1, A-x2</td> |
| |
| <td>Appenders of "x" and root.</td> |
| </tr> |
| |
| <tr class="b"> |
| |
| <td>x.y</td> |
| |
| <td>none</td> |
| |
| <td>true</td> |
| |
| <td>A1, A-x1, A-x2</td> |
| |
| <td>Appenders of "x" and root.</td> |
| </tr> |
| |
| <tr class="a"> |
| |
| <td>x.y.z</td> |
| |
| <td>A-xyz1</td> |
| |
| <td>true</td> |
| |
| <td>A1, A-x1, A-x2, A-xyz1</td> |
| |
| <td>Appenders in "x.y.z", "x" and root.</td> |
| </tr> |
| |
| <tr class="b"> |
| |
| <td>security</td> |
| |
| <td>A-sec</td> |
| |
| <td> |
| <span class="activity-flag-highlight">false</span> |
| </td> |
| |
| <td>A-sec</td> |
| |
| <td> |
| No appender accumulation since the additivity flag is set to <tt>false</tt>. |
| </td> |
| </tr> |
| |
| <tr class="a"> |
| |
| <td>security.access</td> |
| |
| <td>none</td> |
| |
| <td>true</td> |
| |
| <td>A-sec</td> |
| |
| <td> |
| Only appenders of "security" because the additivity flag in "security" is |
| set to <tt>false</tt>. |
| </td> |
| </tr> |
| </table> |
| |
| |
| <p> |
| More often than not, users wish to customize not only the output |
| destination but also the output format. This is accomplished by |
| associating a <i>layout</i> with an appender. The layout is |
| responsible for formatting the logging request according to the user's |
| wishes, whereas an appender takes care of sending the formatted output |
| to its destination. |
| </p> |
| |
| |
| <p> |
| The <a href="apidocs/classlog4cxx_1_1_pattern_layout.html">PatternLayout</a>, part |
| of the standard log4cxx distribution, lets the user specify the output |
| format according to conversion patterns similar to the C language |
| <tt>printf</tt> function. |
| </p> |
| |
| |
| <p> |
| For example, the PatternLayout with the conversion pattern "%r [%t] |
| %-5p %c - %m%n" will output something akin to: |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| 176 [main] INFO org.foo.Bar - Located nearest gas station.</pre></div> |
| |
| |
| <p> |
| The first field is the number of milliseconds elapsed since the |
| start of the program. The second field is the thread making the log |
| request. The third field is the level of the log statement. The |
| fourth field is the name of the logger associated with the log |
| request. The text after the '-' is the message of the statement. |
| </p> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Configuration<a name="Configuration"></a></h2> |
| |
| <p> |
| Inserting log requests into the application code requires a fair |
| amount of planning and effort. Observation shows that approximately 4 |
| percent of code is dedicated to logging. Consequently, even moderately |
| sized applications will have thousands of logging statements embedded |
| within their code. Given their number, it becomes imperative to |
| manage these log statements without the need to modify them manually. |
| </p> |
| |
| |
| <p> |
| The log4cxx environment is fully configurable programmatically. |
| However, it is far more flexible to configure log4cxx using |
| configuration files. Currently, configuration files can be written in |
| XML or in Java properties (key=value) format. |
| </p> |
| |
| |
| <p> |
| Let us give a taste of how this is done with the help of an |
| imaginary application <tt>MyApp</tt> that uses log4cxx. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| #include "com/foo/bar.h" |
| using namespace com::foo; |
| |
| // include log4cxx header files. |
| #include "log4cxx/logger.h" |
| #include "log4cxx/basicconfigurator.h" |
| #include "log4cxx/helpers/exception.h" |
| |
| using namespace log4cxx; |
| using namespace log4cxx::helpers; |
| |
| LoggerPtr logger(Logger::getLogger("MyApp")); |
| |
| int main(int argc, char **argv) |
| { |
| int result = EXIT_SUCCESS; |
| try |
| { |
| // Set up a simple configuration that logs on the console. |
| BasicConfigurator::configure(); |
| |
| LOG4CXX_INFO(logger, "Entering application.") |
| Bar bar; |
| bar.doIt(); |
| LOG4CXX_INFO(logger, "Exiting application.") |
| } |
| catch(Exception&) |
| { |
| result = EXIT_FAILURE; |
| } |
| |
| return result; |
| }</pre></div> |
| |
| |
| <p> |
| <tt>MyApp</tt> begins by including log4cxx headers. It |
| then defines a static logger variable with the name <tt>MyApp</tt> |
| which happens to be the fully qualified name of the |
| class. |
| </p> |
| |
| |
| <p> |
| <tt>MyApp</tt> uses the <tt>Bar</tt> class defined in header |
| file <tt>com/foo/bar.h</tt>. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| // file com/foo/bar.h |
| #include "log4cxx/logger.h" |
| |
| namespace com { |
| namespace foo { |
| class Bar { |
| static log4cxx::LoggerPtr logger; |
| |
| public: |
| void doIt(); |
| } |
| } |
| }</pre></div> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| // file bar.cpp |
| #include "com/foo/bar.h" |
| |
| using namespace com::foo; |
| using namespace log4cxx; |
| |
| LoggerPtr Bar::logger(Logger::getLogger("com.foo.bar")); |
| |
| void Bar::doIt() { |
| LOG4CXX_DEBUG(logger, "Did it again!") |
| }</pre></div> |
| |
| |
| <p> |
| The invocation of the <a href="apidocs/classlog4cxx_1_1_basic_configurator.html#a4f96a09e1372664e3556ce94ace4a70c">BasicConfigurator::configure</a> |
| method creates a rather simple log4cxx setup. This method is hardwired |
| to add to the root logger a <a href="apidocs/classlog4cxx_1_1_console_appender.html"> |
| ConsoleAppender</a>. The output will be formatted using a |
| <a href="apidocs/classlog4cxx_1_1_pattern_layout.html">PatternLayout</a> set |
| to the pattern "%-4r [%t] %-5p %c %x - %m%n". |
| </p> |
| |
| |
| <p> |
| Note that by default, the root logger is assigned to |
| <tt>Level::getDebug()</tt>. |
| </p> |
| |
| |
| <p> |
| The output of MyApp is: |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| 0 [12345] INFO MyApp - Entering application. |
| 36 [12345] DEBUG com.foo.Bar - Did it again! |
| 51 [12345] INFO MyApp - Exiting application.</pre></div> |
| |
| |
| <p> |
| The previous example always outputs the same log information. |
| Fortunately, it is easy to modify <tt>MyApp</tt> so that the log |
| output can be controlled at run-time. Here is a slightly modified |
| version. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| // file MyApp2.cpp |
| |
| #include "com/foo/bar.h" |
| using namespace com::foo; |
| |
| // include log4cxx header files. |
| #include "log4cxx/logger.h" |
| #include "log4cxx/basicconfigurator.h" |
| #include "log4cxx/propertyconfigurator.h" |
| #include "log4cxx/helpers/exception.h" |
| |
| using namespace log4cxx; |
| using namespace log4cxx::helpers; |
| // Define a static logger variable so that it references the |
| // Logger instance named "MyApp". |
| LoggerPtr logger(Logger::getLogger("MyApp")); |
| |
| int main(int argc, char **argv) |
| { |
| int result = EXIT_SUCCESS; |
| try |
| { |
| if (argc > 1) |
| { |
| // BasicConfigurator replaced with PropertyConfigurator. |
| PropertyConfigurator::configure(argv[1]); |
| } |
| else |
| { |
| BasicConfigurator::configure(); |
| } |
| |
| LOG4CXX_INFO(logger, "Entering application.") |
| Bar bar |
| bar.doIt(); |
| LOG4CXX_INFO(logger, "Exiting application.") |
| } |
| catch(Exception&) |
| { |
| result = EXIT_FAILURE; |
| } |
| |
| return result; |
| }</pre></div> |
| |
| |
| <p> |
| This version of <tt>MyApp</tt> instructs |
| <tt>PropertyConfigurator</tt> to parse a configuration file and |
| set up logging accordingly. |
| </p> |
| |
| |
| <p> |
| Here is a sample configuration file that results in exactly same |
| output as the previous <tt>BasicConfigurator</tt> based example. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| # Set root logger level to DEBUG and its only appender to A1. |
| log4j.rootLogger=DEBUG, A1 |
| |
| # A1 is set to be a ConsoleAppender. |
| log4j.appender.A1=org.apache.log4j.ConsoleAppender |
| |
| # A1 uses PatternLayout. |
| log4j.appender.A1.layout=org.apache.log4j.PatternLayout |
| log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n</pre></div> |
| |
| |
| <p> |
| It can be noticed that the PropertyConfigurator file format is the same as log4j. |
| </p> |
| |
| |
| <p> |
| Suppose we are no longer interested in seeing the output of any |
| component belonging to the <tt>com::foo</tt> package. The following |
| configuration file shows one possible way of achieving this. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| log4j.rootLogger=DEBUG, A1 |
| log4j.appender.A1=org.apache.log4j.ConsoleAppender |
| log4j.appender.A1.layout=org.apache.log4j.PatternLayout |
| |
| # <b>Print the date in ISO 8601 format</b> |
| log4j.appender.A1.layout.ConversionPattern=<b>%d</b> [%t] %-5p %c - %m%n |
| |
| # Print only messages of level WARN or above in the package com.foo. |
| <b>log4j.logger.com.foo=WARN</b></pre></div> |
| |
| |
| <p> |
| The output of <tt>MyApp</tt> configured with this file is shown below. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| <b>2000-09-07 14:07:41,508</b> [12345] INFO MyApp - Entering application. |
| <b>2000-09-07 14:07:41,529</b> [12345] INFO MyApp - Exiting application.</pre></div> |
| |
| |
| <p> |
| As the logger <tt>com.foo.Bar</tt> does not have an assigned |
| level, it inherits its level from <tt>com.foo</tt>, which |
| was set to WARN in the configuration file. The log statement from the |
| <tt>Bar::doIt</tt> method has the level DEBUG, lower than the |
| logger level WARN. Consequently, <tt>doIt()</tt> method's log |
| request is suppressed. |
| </p> |
| |
| |
| <p> |
| Here is another configuration file that uses multiple appenders. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| log4j.rootLogger=debug, <b>stdout, R</b> |
| |
| log4j.appender.<b>stdout</b>=org.apache.log4j.ConsoleAppender |
| log4j.appender.stdout.layout=org.apache.log4j.PatternLayout |
| |
| # Pattern to output the caller's file name and line number. |
| log4j.appender.stdout.layout.ConversionPattern=%5p [%t] <b>(%F:%L)</b> - %m%n |
| |
| log4j.appender.<b>R</b>=org.apache.log4j.RollingFileAppender |
| log4j.appender.R.File=example.log |
| |
| log4j.appender.R.MaxFileSize=<b>100KB</b> |
| # Keep one backup file |
| log4j.appender.R.MaxBackupIndex=1 |
| |
| log4j.appender.R.layout=org.apache.log4j.PatternLayout |
| log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n</pre></div> |
| |
| |
| <p> |
| Calling the enhanced MyApp with the this configuration file will |
| output the following on the console. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| INFO [12345] <b>(MyApp2.cpp:31)</b> - Entering application. |
| DEBUG [12345] (Bar.h:16) - Doing it again! |
| INFO [12345] (MyApp2.cpp:34) - Exiting application.</pre></div> |
| |
| |
| <p> |
| In addition, as the root logger has been allocated a second |
| appender, output will also be directed to the <tt>example.log</tt> |
| file. This file will be rolled over when it reaches 100KB. When |
| roll-over occurs, the old version of <tt>example.log</tt> is |
| automatically moved to <tt>example.log.1</tt>. |
| </p> |
| |
| |
| <p> |
| Note that to obtain these different logging behaviors we did not |
| need to recompile code. We could just as easily have logged to a UNIX |
| Syslog daemon, redirected all <tt>com.foo</tt> output to an NT |
| Event logger, or forwarded logging events to a remote log4cxx server, |
| which would log according to local server policy, for example by |
| forwarding the log event to a second log4cxx server. |
| </p> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Default Initialization Procedure<a name="Default_Initialization_Procedure"></a></h2> |
| |
| <p> |
| The log4cxx library does not make any assumptions about its |
| environment. In particular, there are no default log4cxx |
| appenders. Under certain well-defined circumstances however, the |
| static inializer of the <tt>Logger</tt> class will attempt to |
| automatically configure log4cxx. |
| </p> |
| |
| |
| <p> |
| The exact default initialization algorithm is defined as follows: |
| </p> |
| |
| |
| <ol style="list-style-type: decimal"> |
| |
| <li> |
| |
| <p> |
| Set the configurationOptionStr string variable to the value of the |
| <b>LOG4CXX_CONFIGURATION</b> environment variable if set, otherwise |
| the value of the <b>log4j.configuration</b> environment variable |
| if set, otherwise the first of the following file names which exist in the |
| current working directory, "log4cxx.xml", "log4cxx.properties", |
| "log4j.xml" and "log4j.properties". If configurationOptionStr has not been |
| set, then disable logging. |
| </p> |
| </li> |
| |
| <li> |
| |
| <p> |
| Unless a custom configurator is specified using the |
| <b>LOG4CXX_CONFIGURATOR_CLASS</b> or <b>log4j.configuratorClass</b> |
| environment variable, the PropertyConfigurator will be used to configure |
| log4cxx unless the file name ends with the ".xml" extension, |
| in which case the DOMConfigurator will be used. |
| If a custom configurator is specified, the environment variable |
| should contain a fully qualified class name of a class that |
| implements the Configurator interface. |
| </p> |
| </li> |
| </ol> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Nested Diagnostic Contexts<a name="Nested_Diagnostic_Contexts"></a></h2> |
| |
| <p> |
| Most real-world systems have to deal with multiple clients |
| simultaneously. In a typical multithreaded implementation of such a |
| system, different threads will handle different clients. Logging is |
| especially well suited to trace and debug complex distributed |
| applications. A common approach to differentiate the logging output of |
| one client from another is to instantiate a new separate logger for |
| each client. This promotes the proliferation of loggers and |
| increases the management overhead of logging. |
| </p> |
| |
| |
| <p> |
| A lighter technique is to uniquely stamp each log request initiated |
| from the same client interaction. Neil Harrison described this method |
| in the book "Patterns for Logging Diagnostic Messages," in <i>Pattern |
| Languages of Program Design 3</i>, edited by R. Martin, D. Riehle, |
| and F. Buschmann (Addison-Wesley, 1997). |
| </p> |
| |
| |
| <p> |
| To uniquely stamp each request, the |
| user pushes contextual information into the NDC, the abbreviation of |
| <i>Nested Diagnostic Context</i>. The NDC class is shown below. |
| </p> |
| |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| namespace log4cxx { |
| class NDC { |
| public: |
| // pushes the value on construction and pops on destruction. |
| NDC(const std::string& value); |
| NDC(const std::wstring& value); |
| |
| // Remove the top of the context from the NDC. |
| <b>static</b> LogString pop(); |
| |
| // Add diagnostic context for the current thread. |
| <b>static</b> void push(const std::string& message); |
| <b>static</b> void push(const std::wstring& message); |
| } |
| }</pre></div> |
| |
| |
| <p> |
| The NDC is managed per thread as a <i>stack</i> of contextual |
| information. Note that all methods of the <tt>log4cxx::NDC</tt> |
| class are static. Assuming that NDC printing is turned on, every time |
| a log request is made, the appropriate log4cxx component will include |
| the <i>entire</i> NDC stack for the current thread in the log |
| output. This is done without the intervention of the user, who is |
| responsible only for placing the correct information in the NDC by |
| using the <tt>push</tt> and <tt>pop</tt> methods at a few |
| well-defined points in the code. In contrast, the per-client logger |
| approach commands extensive changes in the code. |
| </p> |
| |
| |
| <p> |
| To illustrate this point, let us take the example of a servlet |
| delivering content to numerous clients. The servlet can build the NDC |
| at the very beginning of the request before executing other code. The |
| contextual information can be the client's host name and other |
| information inherent to the request, typically information contained |
| in cookies. Hence, even if the servlet is serving multiple clients |
| simultaneously, the logs initiated by the same code, i.e. belonging to |
| the same logger, can still be distinguished because each client |
| request will have a different NDC stack. Contrast this with the |
| complexity of passing a freshly instantiated logger to all code |
| exercised during the client's request. |
| </p> |
| |
| |
| <p> |
| Nevertheless, some sophisticated applications, such as virtual |
| hosting web servers, must log differently depending on the virtual |
| host context and also depending on the software component issuing the |
| request. Recent log4cxx releases support multiple hierarchy trees. This |
| enhancement allows each virtual host to possess its own copy of the |
| logger hierarchy. |
| </p> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Performance<a name="Performance"></a></h2> |
| |
| <p> |
| One of the often-cited arguments against logging is its |
| computational cost. This is a legitimate concern as even moderately |
| sized applications can generate thousands of log requests. Much |
| effort was spent measuring and tweaking logging performance. Log4cxx |
| claims to be fast and flexible: speed first, flexibility second. |
| </p> |
| |
| |
| <p> |
| The user should be aware of the following performance issues. |
| </p> |
| |
| |
| <ol style="list-style-type: decimal"> |
| |
| <li> |
| |
| <p> |
| <b>Logging performance when logging is turned off.</b> |
| </p> |
| |
| |
| <p> |
| When logging is turned off entirely or just for a set |
| of levels, the cost of a log request consists of a method |
| invocation plus an integer comparison. The LOG4CXX_DEBUG and similar |
| macros suppress unnecessary expression evaluation if the |
| request is not enabled. |
| </p> |
| </li> |
| |
| |
| <li> |
| |
| <p> |
| <b>The performance of deciding whether to log or not to log when logging is turned on.</b> |
| </p> |
| |
| |
| <p> |
| This is essentially the performance of walking the logger |
| hierarchy. When logging is turned on, log4cxx still needs to compare |
| the level of the log request with the level of the request |
| logger. However, loggers may not have an assigned |
| level; they can inherit them from the logger hierarchy. Thus, |
| before inheriting a level, the logger may need to search its |
| ancestors. |
| </p> |
| |
| |
| <p> |
| There has been a serious effort to make this hierarchy walk to |
| be as fast as possible. For example, child loggers link only to |
| their existing ancestors. In the <tt>BasicConfigurator</tt> |
| example shown earlier, the logger named <tt>com.foo.Bar</tt> is |
| linked directly to the root logger, thereby circumventing the |
| nonexistent <tt>com</tt> or <tt>com.foo</tt> loggers. This |
| significantly improves the speed of the walk, especially in "sparse" |
| hierarchies. |
| </p> |
| |
| |
| <p> |
| The cost of walking the hierarchy is typically 3 |
| times slower than when logging is turned off entirely. |
| </p> |
| </li> |
| |
| <li> |
| |
| <p> |
| <b>Actually outputting log messages</b> |
| </p> |
| |
| |
| <p> |
| This is the cost of formatting the log output and sending it to |
| its target destination. Here again, a serious effort was made to |
| make layouts (formatters) perform as quickly as possible. The same |
| is true for appenders. |
| </p> |
| </li> |
| </ol> |
| </div> |
| |
| |
| <div class="section"> |
| <h2>Conclusions<a name="Conclusions"></a></h2> |
| |
| <p> |
| Apache Log4cxx is a popular logging package written in C++. One of its |
| distinctive features is the notion of inheritance in loggers. Using |
| a logger hierarchy it is possible to control which log statements |
| are output at arbitrary granularity. This helps reduce the volume of |
| logged output and minimize the cost of logging. |
| </p> |
| |
| |
| <p> |
| One of the advantages of the log4cxx API is its manageability. Once |
| the log statements have been inserted into the code, they can be |
| controlled with configuration files. They can be selectively enabled |
| or disabled, and sent to different and multiple output targets in |
| user-chosen formats. The log4cxx package is designed so that log |
| statements can remain in shipped code without incurring a heavy |
| performance cost. |
| </p> |
| </div> |
| |
| |
| </td> |
| </tr> |
| </table> |
| </div> |
| |
| <div class="footer"> |
| <p>Copyright © 2003-2020 <a class="external" href="http://www.apache.org">Apache Software Foundation</a>. All Rights Reserved.</p> |
| <p>Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the Apache Logging project logo are trademarks of The Apache Software Foundation.</p> |
| <p>Site powered by <a class="external" href="https://getbootstrap.com/">Twitter Bootstrap</a>. Icons from <a class="external" href="https://glyphicons.com/">Glyphicons Free</a>.</p> |
| </div> |
| </body> |
| </html> |