| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| <title>Apache Logging Services</title> |
| |
| <link href="css/asciidoctor-default.css" rel="stylesheet" type="text/css" /> |
| <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css" /> |
| <link href="css/site.css" rel="stylesheet" type="text/css" /> |
| |
| <script src="js/jquery.min.js"></script> |
| <script src="js/bootstrap.min.js"></script> |
| <script src="js/site.js"></script> |
| |
| </head> |
| |
| <body> |
| <div class="navbar"> |
| <div class="navbar-inner"> |
| <div class="container"> |
| <a class="brand" href="https://logging.apache.org">Apache Logging Services™</a> |
| <ul class="nav"> |
| <li class="dropdown"> |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown">About<b class="caret"></b></a> |
| <ul class="dropdown-menu"> |
| <li><a target="_blank" href="guidelines.html">Guidelines</a></li> |
| <li><a target="_blank" href="charter.html">Charter</a></li> |
| <li><a target="_blank" href="team-list.html">Team</a></li> |
| <li><a target="_blank" href="mailing-lists.html">Mailing lists</a></li> |
| <li><a target="_blank" href="https://cwiki.apache.org/confluence/display/LOGGING/Home">Wiki</a> |
| <li><a target="_blank" href="what-is-logging.html">What is logging?</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| <ul class="nav"> |
| <li class="dropdown"> |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown">Projects<b class="caret"></b></a> |
| <ul class="dropdown-menu"> |
| <li><a target="_blank" href="chainsaw/2.x/index.html">Apache chainsaw</a></li> |
| <li><a target="_blank" href="log4cxx">Apache log4cxx</a></li> |
| <li><a target="_blank" href="log4j/2.x/index.html">Apache log4j</a></li> |
| <li><a target="_blank" href="log4j-audit/latest/index.html">Apache log4j-audit</a></li> |
| <li><a target="_blank" href="log4j/kotlin/index.html">Apache log4j Kotlin API</a></li> |
| <li><a target="_blank" href="log4j/scala/index.html">Apache log4j Scala API</a></li> |
| <li><a target="_blank" href="log4net">Apache log4net</a></li> |
| </ul> |
| </li> |
| </ul> |
| <ul class="nav"> |
| <li class="dropdown"> |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dormant<b class="caret"></b></a> |
| <ul class="dropdown-menu"> |
| <li><a target="_blank" href="log4j/1.2/index.html">Apache log4j 1.x</a></li> |
| <li><a target="_blank" href="log4j/extras/index.html">Apache log4j 1.x extras</a></li> |
| <li><a target="_blank" href="log4php">Apache log4php</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <ul class="nav pull-right"> |
| <li class="dropdown"> |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown">Apache<b class="caret"></b></a> |
| <ul class="dropdown-menu"> |
| <li><a target="_blank" href="https://www.apache.org/">Home</a></li> |
| <li><a target="_blank" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a target="_blank" href="https://www.apache.org/licenses/">License</a></li> |
| <li><a target="_blank" href="https://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a target="_blank" href="https://www.apache.org/events/current-event.html">Current Events</a></li> |
| <li><a target="_blank" href="https://www.apache.org/security/">Security</a></li> |
| <li><a target="_blank" href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy</a></li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| |
| <div class="container"> |
| <div class="content"> |
| <h1>What is logging?</h1> |
| <p>At a high level, logging is used to capture information during the run of an<br /> |
| application. This can include different types of information about both the<br /> |
| state of the application and inputs to the application. For example, an HTTP<br /> |
| server may log information about incoming connections(such as an IP address).<br /> |
| Logging can also be at different levels of verbosity, in order to allow a user<br /> |
| of the application to not be overwhelmed with too much information.</p> |
| <p>Logging can be broadly classified into two categories. The two main categories<br /> |
| of logging are debug logging and audit logging. Debug logging is generally<br /> |
| useful for application developers who can turn on messages that an end-user<br /> |
| does not care about - for example, if data is being parsed correctly, or if an<br /> |
| exception is thrown. Audit logging is more interesting to system<br /> |
| administrators. This type of data would include information such as when<br /> |
| somebody logged in, who changed a piece of information, etc. Debug logging and<br /> |
| audit logging are not mutually exclusive, and there can be plenty of overlap<br /> |
| between these two categories.</p> |
| <h1>What should a logging framework do?</h1> |
| <p>At a minimum, a logging framework needs to be able to do the following:</p> |
| <ul> |
| <li>Easily allow you to create log messages</li> |
| <li>Send log messages to stdout and/or stderr</li> |
| <li>Be completely transparent to your application - your application should<br /> |
| behave exactly the same no matter if logging is enabled or disabled</li> |
| </ul> |
| <p>However, a logging framework that does only these things is not particularly<br /> |
| useful, and no better than using System.out.println() or printf(). Common<br /> |
| features of logging frameworks generally include:</p> |
| <ul> |
| <li>Ability to send log messages to other places than just stdout/stderr. For<br /> |
| example, common places to send logs could be:<br /> |
| ** syslog<br /> |
| ** A file on the local filesystem<br /> |
| ** Remote log server(e.g. ELK, Splunk, kibana, etc.)<br /> |
| ** Windows event log<br /> |
| ** Database</li> |
| <li>Filtering based off of levels and data</li> |
| <li>Location information of where the log statement is in the code</li> |
| <li>Allow for rotation of files when logging to a file. This allows you to do<br /> |
| things such as creating a new log whenever you start up, doing one log file per<br /> |
| day, limiting files to a specific size, etc.</li> |
| <li>Log to multiple locations at once(send the same data to stdout and a file for<br /> |
| example)</li> |
| <li>Classify messages based off of the particular subsystem that they are from</li> |
| <li>Format log messages according to some user-defined pattern</li> |
| </ul> |
| <p>This is not an exhaustive list of all features that could exist. There are<br /> |
| many different logging frameworks that exist which may implement different<br /> |
| subsets of these features, and may also have more features than are listed here.</p> |
| <h1>Log Levels and Subsystem Classification</h1> |
| <p>When you are logging information, two of the most important things to know are<br /> |
| the level of the log message and the subsystem that the log message is from.<br /> |
| This allows you to determine how severe something is, as well as where it is<br /> |
| coming from.</p> |
| <p>The traditional log levels are as follows(from most verbose to least verbose):<br /> |
| TRACE<br /> |
| DEBUG<br /> |
| INFO<br /> |
| WARN<br /> |
| ERROR</p> |
| <p>In addition, levels of CRITICAL and FATAL may exist as well. Generally, FATAL<br /> |
| indicates that the application is about to exit, while CRITICAL is similar to<br /> |
| ERROR.</p> |
| <p>Levels make it easy to quickly filter messages. Since more verbose messages<br /> |
| still allow less verbose messages to be printed, you don't lose information by<br /> |
| turning the verbosity up. When you are working on a particular subsystem, you<br /> |
| may want that subsystem to be at the DEBUG level to see all the messages, or<br /> |
| TRACE if there is something that you really need to see. As a general rule of<br /> |
| thumb, when your application is in production the default level of all loggers<br /> |
| should be at the INFO level.</p> |
| <p>Subsystems help to classify the data as well. In Java, this is generally done<br /> |
| by the package that a class is in. Being able to set a particular subsystem<br /> |
| that you are debugging to the DEBUG level(and not just a single class) is an<br /> |
| important part of being able to easily filter information and to not overload<br /> |
| the programmer who is debugging the application.</p> |
| <p>Within the Apache Logging Services projects(log4j2, log4cxx, and log4net) this<br /> |
| subsystem classification follows the Java hierarchical approach. If you have a<br /> |
| logger org.apache.Foo and org.apache.Bar, you can set the level of org.apache<br /> |
| to DEBUG and both loggers will be at the DEBUG level, but can also be<br /> |
| individually set if required. This hierarchical way of logging is not a<br /> |
| feature that all logging frameworks have, however it is very useful if your<br /> |
| code is organized in a way such that all classes have individual loggers and<br /> |
| are logically separated into subsystems appropriately. This also allows for<br /> |
| more granular control over your debug statements.</p> |
| <h1>Where to put logs?</h1> |
| <p>Logging to different locations(sometimes called sinks) is an important part of<br /> |
| logging frameworks. For simple applications, you may not need to do anything<br /> |
| more complicated than just send data to stdout and/or a file. However, more<br /> |
| complicated applications quickly need to have more flexibility in how and where<br /> |
| they log information. Modern applications can log to web-based log aggregators<br /> |
| in addition to a local log mechanism such as syslog.</p> |
| <p>By configuring these log locations through an external source such as a config<br /> |
| file, it also makes it possible for the end-user to configure the system for<br /> |
| their particular use-case.</p> |
| <h1>Transparent Logging</h1> |
| <p>One of the most basic tenets of logging is that it needs to be completely<br /> |
| transparent to your application. Your application must not care if logging is<br /> |
| enabled or disabled: all it does is send messages to the logging framework,<br /> |
| which then handles all of the filtering and routing required to get the message<br /> |
| to its final destination. This also makes it possible to write unit tests that<br /> |
| don't care about logging at all. If the logging system is not initialized, the<br /> |
| worst that should happen is that nothing gets logged.</p> |
| <h1>How to do proper logging</h1> |
| <p>Now that we understand what the normal features of logging libraries are,<br /> |
| it’s time to talk about how to do proper logging. As we’ve mentioned<br /> |
| before, the two main things to worry about when logging are what the level of<br /> |
| the message is, and the classification of the log message. For the<br /> |
| classification of the log message, this will often be the name of the class<br /> |
| that is doing the logging. Assuming that you have a good design already, then<br /> |
| the classification derives clearly from the name of the class and the<br /> |
| package/namespace the class is in.</p> |
| <p>Choosing the level of the log message can be a bit trickier. A good rule of<br /> |
| thumb is to leave your log messages at INFO level during normal operation, so<br /> |
| what should we put at that level and what should be more verbose? Let’s<br /> |
| assume that we are opening a network socket for remote communications. At the<br /> |
| INFO level we may inform that the network subsystem is starting up and ready<br /> |
| for work. DEBUG information could include new connections from clients with<br /> |
| their IP/port combination, while TRACE information could be output whenever a<br /> |
| packet comes in from a client. In addition, we may have ERROR messages if we<br /> |
| are unable to open a socket for reading/writing.</p> |
| <p>By having different pieces of the data flow at different log levels, it makes<br /> |
| it easy to quickly look at the logs and determine how serious a problem is and<br /> |
| what the system is doing during operation.</p> |
| <h1>Other things to worry about when logging</h1> |
| <p>As we have seen, having a good logging framework is critical to being able to<br /> |
| find and fix errors in applications. However, just because we have logging<br /> |
| doesn’t mean that it is infallible. Since logging code that you insert into<br /> |
| your application is still code that you have written, it is always possible<br /> |
| that the log messages you get out are lying to you due to a bug in a log<br /> |
| statement.</p> |
| <h1>Features that the Apache Logging Services projects have</h1> |
| <p>While there are many different logging frameworks that exist for Java, C++, and<br /> |
| .NET, there are a number of built-in features that Log4j2, Log4cxx, and Log4net<br /> |
| have that are generally useful.</p> |
| <h2>Hierarchichal Logging</h2> |
| <p>As mentioned previously, hierarchical logging allows for easy grouping of<br /> |
| subsystem information. This allows you to have fine-grained control over the<br /> |
| information that you are logging and easily allows for one logger per-class.</p> |
| <p>This hierarchical logging also means that you don't need to explicitly share<br /> |
| a sink between loggers. While it is possible to configure Log4j2 and Log4cxx<br /> |
| to send each logger to a separate location, the parent/child relationship means<br /> |
| that children will log their messages to any sinks that their parents have.</p> |
| <h2>Location Information</h2> |
| <p>Knowing exactly where a log statement is can be vital in order to track down<br /> |
| the location of a log statement. Both Log4j2 and Log4cxx are able to determine<br /> |
| the filename, class name, method name, and line number where the log message<br /> |
| is coming from. With Log4cxx, this is able to be done at compile-time.</p> |
| <h2>Static and Single-instance Loggers</h2> |
| <p>All loggers that are created with Log4j2 and Log4cxx are able to be declared<br /> |
| as static variables in your source file, eliminating the need for a dedicated<br /> |
| instance variable of a logger per-class. A side effect of this is that there<br /> |
| is a global logger registry, so that you can access the same logger via a<br /> |
| static LogManager in different classes without having to pass the logger around.</p> |
| <h2>Nested and Mapped Diagnostic Contexts</h2> |
| <p>When you have multiple objects of the same type, using a static logger can be<br /> |
| problematic when you need to only view data for one instance of the class. By<br /> |
| providing a Nested Diagnostic Context and a Mapped Diagnostic Context, it is<br /> |
| possible to add context information to your log statements.</p> |
| <h2>Flexible Log Message Formatting</h2> |
| <p>When sending a log message to a flat text file, it is often desirable to have<br /> |
| the messages in a simple to understand format. This information can include<br /> |
| data such as the date/time of the log message, the level of the message, the<br /> |
| logger that produced the message, and the message itself. With the Log4j2<br /> |
| and Log4cxx PatternLayout classes, it is possible to quickly configure the<br /> |
| logging system to output information in a convenient format.</p> |
| <p>Different types of log message formatting is also important when you need<br /> |
| to send messages to different locations. The code that creates the log messages<br /> |
| should not know anything about how the message is formatted on the backend.<br /> |
| This allows for the same log message to be formatted in different ways with<br /> |
| potentially different metadata - for example, JSON format for a log aggregating<br /> |
| service, or plain text for a local configuration file.</p> |
| <h2>Configuration via config file</h2> |
| <p>Both Log4j2 and Log4cxx can be configured with a configuration file in one of<br /> |
| several different formats. While it is always possible to configure via code,<br /> |
| configuration files make it easy to reconfigure the system without having to<br /> |
| recompile your code. This also means it is possible to edit a configuration<br /> |
| file and dynamically change the configuration at runtime. For example, you<br /> |
| can turn on a logger that was previously off if you are debugging a live<br /> |
| system.</p> |
| <h2>Garbage-free(Log4j2)</h2> |
| <p>In Java, it is important to reduce the amount of time that the garbage<br /> |
| collector takes to run. By not allocating and freeing objects, your<br /> |
| log statements will add very little to the runtime overhead of your application.</p> |
| <h2>Formatting with replacements</h2> |
| <p>When creating a log statement, it is often slow and annoying to perform string<br /> |
| concatenation to create a log statement. In Java, the simplest way to<br /> |
| concatenate a string is to simply use the + operator:</p> |
| <pre><code>log("Logging information: " + someVariable + " and the other variable is " + otherVariable); |
| </code></pre> |
| <p>While in C++, you can get into a chevron overload:</p> |
| <pre><code>log("Logging information: " << someVariable << " and the other variable is " << otherVariable); |
| </code></pre> |
| <p>Both Log4j2 and Log4cxx allow for variable replacements in strings, such that<br /> |
| the above log statements can both be written similar to the following:</p> |
| <pre><code>log("Logging information: {} and the other variable is {}", someVariable, otherVariable); |
| </code></pre> |
| <h2>Filtering</h2> |
| <p>When you have many different log messages that you are trying to make sense of,<br /> |
| it can be difficult to focus on the correct piece of information. Because of<br /> |
| this, it is possible to configure both Log4j2 and Log4cxx to filter certain<br /> |
| messages based off of various attributes, such as a text string that is contained<br /> |
| within the log message. Since these filters are also able to be configured<br /> |
| through the confgiuration file, adding or removing filters is a simple operation.</p> |
| <h1>Conclusion</h1> |
| <p>Logging is a rather complicated topic that covers many different aspects. While<br /> |
| different applications will have different requirements for their log statements,<br /> |
| the projects of the Apache Logging Services Commitee provide a generic and<br /> |
| widely applicable implemenation of logging for all kinds of applications.</p> |
| |
| </div> |
| |
| <div class="footer"> |
| <p> |
| Copyright © 2017-2022 <a href="https://www.apache.org" target="external">The Apache Software Foundation</a>. |
| Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0" |
| target="external">Apache Software License, Version 2.0</a> Please read our <a href="https://privacy.apache.org/policies/privacy-policy-public.html">privacy policy</a>. |
| </p><p> |
| Apache, Apache chainsaw, Apache log4cxx, Apache log4j, Apache log4net, Apache log4php and the Apache |
| feather logo are trademarks of The Apache Software Foundation. Oracle and Java are registered trademarks |
| of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. |
| </p><p> |
| Site powered by <a href="https://getbootstrap.com/" target="external">Bootstrap</a> |
| and <a href="https://jquery.com/" target="external">jQuery</a>. |
| </p> |
| </div> |
| </div> |
| </body> |
| </html> |