Logback Demo
Welcome to the logback demo! This document will take you to a tour that will show you some of the major possibilities of logback.
Installation
First, please download the logback demo. You will need to install a Subversion client and issue the following line in a command/terminal window:
svn co http://svn.qos.ch/repos/logback-demo/trunk logback-demo
This will checkout a copy of the logback demonstration web-app to a directory called logback-demo. The logback demo can be packaged as a war file and deployed to an application server. We strongly recommand the use of Maven 2 to do this task, since all it will take to compile, package and run a server with the demo is a single command.
Using Maven, let's package the files and run the demo for the first time. From the logback-demo directory, issue the following command:
mvn package jetty:run
Then, visit http://localhost:8080/logback-demo/ to view the main page of the logback demo.
Logback Classic
For now, logback uses two components: one ConsoleAppender
and one
RollingFileAppender
. The RollingFileAppender
sends logging events
to a file called logFile.log and will rollover
the active file every minute. The old file will be renamed and compressed to zip
file. The ConsoleAppender
will output the logging requests to the console,
and shorten the logger names to gain some space in the console window, without making the
names unreadable. For example, ch.qos.logback.demo.prime.NumberCruncherImpl
will be displayed as c.q.l.d.prime.NumberCruncherImpl
.
You can study the configuration file that is used by editing the file called logback.xml, located in the src/main/resources/ directory of the demo. You might want to keep this file in an editor window, since we will modify its content several times thoughout the demo.
Let's now visit the ViewStatii page, via the navigation menu on the left hand
of the navigator window. This page contains the content of the Status
objects that were
created until now. Status
objects are a part of logback's powerful internal
reporting framework. They allow you to see what is going on in logback, and check
that a configuration file has been parsed correctly, or that a rollover has occured as
expected.
After you're back to the main window, visiting the View logs page does
not impress much at the moment. Let us uncomment
the two parts of the config file that are below the Cyclic buffer comment.
A CyclicBuffer
is a class that keeps track of logging events and holds these
objects for immediate or differed display. The first element that you will need to uncomment
is the appender element. This element describes and configures the CyclicBuffer
.
The second element, found at the end of the configuration file, is a appender-ref element.
It is used to link the appender to a given logger.
Now reload the web-app by exiting the previous command with CTRL-C and issuing it
again: mvn package jetty:run.
Now, the View logs page looks prettier. By virtue of the CyclicBufferAppender
,
this page can fetch the last events and present them through a servlet. We see that each 3 seconds
a line is added to the logs. The formatting of this page is made with
a HTMLLayout
. This component creates a nice and readable table containing the logging
events, based on a pattern that describes the information one wants to see in the table.
Having the logs that we see on the web page cluttered with scheduled
Howdydy-diddly-ho messages
is not very comfortable. To get rid of these logs, now that we've verified that they
work, we can add an EvaluatorFilter
to the Appender. Uncomment the
part named Cyclic buffer with Evaluator. You may then
comment or delete the first Basic Cyclic buffer appender element.
Let's take a look at the filter we've just added:
<filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator name="loggingTaskEval"> <expression> logger.getName().contains("LoggingTask") && message.contains("Howdydy-diddly-ho") && (timeStamp - event.getStartTime()) >= 20000 </expression> </evaluator> <OnMatch>DENY</OnMatch> </filter>
The expression element contains a familiar java statement. This expression
checks that the name of the logger contains the String LoggingTask, but
also that the message accompagnying the log contains Howdydy-diddly-ho.
Moreover, in order to be sure that the Howdydy-diddly-ho task actually
works, we add to the expression a last statement that allows logs to be processed
for the first 20 seconds after the application launch.
The variables used in this statement (logger
, message
and
event
) are made available by logback before the filter
evaluates the expression.
The OnMatch element allows the user to choose the filter's behaviour once
the expression was evaluated to true. A similar OnMismatch element exists.
After a restart, the Vew logs page shows the Howdydy-diddly-ho logs for the first 20 seconds only. Trying a prime calculations on the Prime number page will add several lines to the View logs page.
Turbo Filters
Logback ships with a special category of filters: TurboFilter
objects
are ultra-fast, context-wide filters. They reveals themselves very useful to
test MDC values, for examples and to add context-wide conditions to allow or deny
logging events. Let's uncomment the part named
TurboFilter: MDC value in the logback.xml file.
This part adds a TurboFilter
object to the context. It allows to
have a typical output for every client that uses the demo application, but a different
one for one given user. Here, the filter will accept all the requests that are
associated with a MDC value of sebastien bound to the username key.
To view the consequences of such a TurboFilter
, we are going to
stop all logging activity, except for a specific user. To achieve that, the simplest
way is to set the root logger's level to OFF
. Modify the level
element, nested inside the root element of logback.xml. Its value
attribute should be OFF instead of DEBUG. Next, restart the server
as we've done previously.
Once on the demo main webpage again, perform a few actions (i.e. calculate a few prime numbers) and watch the View logs page. The table should be empty.
Now log in the application using the username sebastien and perform a few prime calculations again. The View logs page now shows the logs that were generated by the calculation classes. Moreover, each log is associated with the name of the user who provoked the logging event. Please log off before continuing the demo, using the logout button on the left.
Parametrized logging
Parametrized logging is a feature that will be a great asset for any performance-critical system. Usually, a logging request is issued like this:
logger.debug("Hello, my name is" + username + ", I am " + age + " years old.");
By issuing this line, the cost of constructing the String cannot be saved when the
log request is not processed. For example, using the debug()
method
when, as we've just done, the root level is any value higher that DEBUG will
result in a loss of time because all calls to the debug()
method will
eventually be dropped.
Logback offers the following method:
logger.debug("Hello, my name is {}, I am {} years old", username, age);
As you can see, the variables are not inserted in the message yet. Both the message and the values will be saved and used later, if the logging event is processed.
Let us now run a test to see what kind of gain can we expect from this different message formatting approach. First, go to the Prime number page and run a few calculations. Check the time it takes to compute the results. To see a clearer difference between the two formatting methods, you might want to try the two big integers that are listed below the prime number textbox.
Now let us edit the NumberCruncherImpl
class, to switch the log methods.
You will find this class in the src/main/java/ch/qos/logback/demo/prime/
directory. On line 54 and 55, just uncomment the parametrized logging line and
comment out the other line. Restart the server with mvn package jetty:run
and re-run the calculations you tried beforehand.
The durations should be obviously different. Remember that we had turned off all logging in the previous step of this demo. With the initial formatting method, we were constructing the logging message ("Trying "+i+" as a factor.") a huge amount of times, actually each time a factor was tried for these big numbers. With the paramatrized logging, the construction of the message was postponed and, since logging was turned off, not processed. We see here that the cost of the non-logging was taken down to a very small figure, dividing the total cost of the calculation by a non-negligeable factor.
Markers
SLF4J allows the use of Marker objects.
For example, one could use TRACE markers, to enrich some
specific logging statements. In our demo applications, the Howdydy-diddly-ho
logging statements are bound to a TRACE marker.
On the other hand, one could want that such
marked statements be dropped and not logged anywhere. TurboFilter
objects can do that in an elegant and flexible way. Let us uncomment the
TurboFilter: Marker value section in the logback.xml file as
well as set the root logger's level back to DEBUG,
and reload via the Reload configuration page.
The logging statements that contained the Howdydy-diddly-ho do not appear anymore because they were associated with a TRACE marker. You can check that by visiting the View Logs page and reloading it every three seconds for several times.
Logback Access
Access logging is another important feature offered by logback. Give a look at what appears on the console while browsing the logback-demo website. Each access is logged to the console, with some information about the event. The configuration file that we will edit in the next few steps is called logback-access.xml and is located in the src/etc/ directory. The necessary configuration is listed below:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.access.PatternLayout"> <Pattern>%h %l %u %t \"%r\" %s %b</Pattern> </layout> </appender> <appender-ref ref="STDOUT" /> </configuration>
To see more clearly the output produced by logback access, you might want set the root logger's level to OFF, in the first logback configuration file, called logback.xml and located in src/main/resources/. It will clear the console from the logs made by the demo application and only display those that are generated by logback access.
To see the logs produced by logback access, just visit a few pages and
look at your console. The information contained in each line has been
specified in the configuration file. The ConsoleAppender
named STDOUT contains a PatternLayout
component.
This very component that one uses in logback classic to display either
the message, logger name or level of the request is used in logback
access to display the request method, requested page, status code and many others.
Here is a sample output of this appender.
127.0.0.1 - - 22/01/2007:14:35:40 +0100 GET /logback-demo/ViewStatii.do HTTP/1.1 200 3660 127.0.0.1 - - 22/01/2007:14:35:41 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389 127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/lastLog/ HTTP/1.1 200 948 127.0.0.1 - - 22/01/2007:14:35:42 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389 127.0.0.1 - - 22/01/2007:14:35:43 +0100 GET /logback-demo/prime.jsp HTTP/1.1 200 1296 127.0.0.1 - - 22/01/2007:14:35:44 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389 127.0.0.1 - - 22/01/2007:14:35:45 +0100 GET /logback-demo/lottery.jsp HTTP/1.1 200 1209 127.0.0.1 - - 22/01/2007:14:35:46 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389 127.0.0.1 - - 22/01/2007:14:35:48 +0100 GET /logback-demo/reload.jsp HTTP/1.1 200 1335 127.0.0.1 - - 22/01/2007:14:35:49 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389 127.0.0.1 - - 22/01/2007:14:35:54 +0100 GET /logback-demo/login.jsp HTTP/1.1 200 1214 127.0.0.1 - - 22/01/2007:14:35:55 +0100 GET /logback-demo/Logout.do HTTP/1.1 200 1000
Filtering
In this next part, we are going to add some information to the console.
Let us imagine that we want to log the numbers that are tried on the
Lottery page. We will need a second ConsoleAppender
that will only print a given information (e.g. the guessed number, along
with some hints about the player). The appender will also have to
print that information only when a certain page is accessed.
The configuration lines that are necessary are listed below.
<appender name="STDOUT_LOTTERY" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator name="lotto_eval"> <Expression> url.matches(event.getRequestURL().toString()) </Expression> <matcher name="url"> <regex>Lottery.do</regex> <caseSensitive>false</caseSensitive> </matcher> </evaluator> <OnMatch>ACCEPT</OnMatch> <OnMismatch>DENY</OnMismatch> </filter> <layout class="ch.qos.logback.access.PatternLayout"> <Pattern> LOTTERY: %A [%r] Guess=%reqParameter{guessed_number} </Pattern> </layout> </appender>
This appender will use a PatternLayout
to format its output.
The %reqParameter conversion word is used to extract the guessed number
from the request, and print it.
It also uses an EvaluatorFilter
that will prevent the appender
to display anything when the access' request url does not match the
given expression. You can see that it is easy to specify a RegExp, name
it and use it in the expression that will be evaluated. In that case, we only
entered the name of the lottery.do action.
Let us uncomment the two elements with the Lottery to Console comments and restart the server. Now, try to play the lottery. You will see more lines in the Console that you've seen until now. At every try, logback will produce a log as shown below:
LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321
Sending emails
Logback access provides several components that are usually used by the classic
module. For example, a SMTPAppender
can be used to send an email when
a specific event occurs. Here, we will contact the lottery administrator each time
a winner is detected. To achieve this, we will add a SMTPAppender
to
the existing configuration. Please uncomment the part of logback-access.xml
named Lottery to Email. Do not forget to uncomment the
appender-ref element, at the end of the configuration file, referencing
the appender called SMTP. In the appender element, notice the use of a
URLEvaluator
. This evaluator allows us to only specify one or more URLs
that have to be watched. When one of them are accessed, an email is sent.
A reload of the configuration has to be done before we can test this new component. Once done, try to play the lottery with the number 99. You should see a congratulation message but, most importantly, the specified recipients should have a new mail in their mailbox. The content of the email is a nicely formatted HTML table with informations about the access that have occured before the triggering event.
JMX
Logback publishes several components via JMX. This allows you to see the status of certain objects, and change several configuration parameters. Publishing logback's components via JMX is possible with Jetty and Tomcat.
To see logback access' components, visit the following page:
http://localhost:8082/
The domain ch.qos.logback.access.jetty contains an entry that allows you to see the RequestLogImpl component. This component is used to plug logback in Jetty's internal achitecture. Clicking on it reveals the status of several parameters, such as the started status, and two methods are available to start and stop the RequestLogImpl.
To see the influence of the available operations, place the terminal window and your web browser such that you can see them both. Stop the RequestLogImlp and reload a few times the main page of the demo. Nothing should be displayed. If you start the RequestLogImpl again, the requests will be shown in the terminal window.
In the logback-access.xml configuration file, uncomment the JMX
part and restart the server. A CountingFilter
will now be available in
the ch.qos.logback.access domain. Clicking on it will display several statistical
figures corresponding to server accesses. Loading some application pages will make
these figures grow and show a time-sensitive picture of the server activity.
These is more to discover with logback and JMX. In the logback.xml file,
placed in the src/main/resources directory, uncomment the JMXConfigurator
element. Once done, restart the server.
By refreshing the previously loaded JMX page, you should see a new component,
under the domain ch.qos.logback.classic. It is the JMXConfigurator
.
Clicking on it reveals its content. Its possibilities are listed below:
Reload the configuration using the same file that was previously used.
Reload the configuration using a file whose path is passed as a parameter.
Reload the configuration using a file whose URL is passed as a parameter.
Get the level of a logger
Change the level setting of a specified logger.
Change a list of all declared loggers.
Change the level setting of a specified logger.
In the last case, you must specify the name of the logger you wish to alter, and its new level.
Checking the level of a logger is an easy task. Enter the name of the logger in the appropriate field and click the Invoke button. You should be able to verify that the logger named root has its level set to OFF.
Let us test the level setting possibility of the configurator. The Prime Number page requests two types of logs. When the calculation checks if a number is a factor, a DEBUG log is displayed. When the calculation has found a factor, a INFO log is displayed.
Let us first set the level of the logger named ch.qos.logback.demo.prime to DEBUG. Run a prime calculation directly, without restarting the server. The View logs page should show the DEBUG and INFO logs.
Now, if you set the level of the ch.qos.logback.demo.prime logger to INFO, and run a prime calculation again, you should not see the DEBUG level logs anymore.
This demo of logback is now over. Do not hesitate to play around with the configuration files. You might want to check the logback documentation page for more information about any component you'd like to test.