Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > 1a36150950432897706b8940120efbe4 > files > 96

logback-1.0.9-2.fc18.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <title>Chapter 7: Filters</title>
    <link rel="stylesheet" type="text/css" href="../css/common.css" />
    <link rel="stylesheet" type="text/css" href="../css/screen.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="../css/_print.css" media="print" />
    <link rel="stylesheet" type="text/css" href="../css/prettify.css" media="screen" /> 

  </head>
  <body onload="prettyPrint(); decorate();">
    <script type="text/javascript">prefix='../';</script>
    <script type="text/javascript" src="../js/prettify.js"></script>
    <script type="text/javascript" src="../templates/header.js"></script>
    <script type="text/javascript" src="../js/dsl.js"></script>
    <script type="text/javascript" src="../js/jquery-min.js"></script>
    <script type="text/javascript" src="../js/decorator.js"></script>

    <div id="left">
      <noscript>Please turn on Javascript to view this menu</noscript>
      <script src="../templates/left.js" type="text/javascript"></script>
    </div>
    <div id="right">
      <script src="menu.js" type="text/javascript"></script>
    </div>
    <div id="content">
	
    <h1>Chapter 7: Filters</h1>

    <div class="quote">
      <p><em>Have lots of ideas and throw away the bad ones. You aren't
      going to have good ideas unless you have lots of ideas and some
      sort of principle of selection.</em></p>
      
      <p>&mdash;LINUS PAULING</p>
    </div>

    <script src="../templates/creative.js" type="text/javascript"></script>

		
		<p>In the preceding chapters, the <a
		href="architecture.html#basic_selection">basic selection rule</a>,
		which lies at the heart of logback-classic, has been presented. In
		this chapter, additional filtering methods will be introduced.
    </p>
	

    <p>Logback filters are based on ternary logic allowing them to be
    assembled or chained together to compose an arbitrarily complex
    filtering policy.  They are largely inspired by Linux's iptables.
		</p>

    <script src="../templates/setup.js" type="text/javascript"></script>

		<h2>In logback-classic</h2>


		<p>Logback-classic offers two types of filters, regular filters
		and turbo filters.
		</p>
		
    <h3 class="doAnchor" name="filter">Regular filters</h3>

		<p>Regular logback-classic filters extend the <a
		href="../xref/ch/qos/logback/core/filter/Filter.html"><code>Filter</code></a>
		abstract class which essentially consists of a single
		<code>decide()</code> method taking an <code>ILoggingEvent</code>
		instance as its parameter.
		</p>
		

		<p>Filters are organized as an ordered list and are based on
		ternary logic. The <code>decide(ILoggingEvent event)</code> method
		of each filter is called in sequence.  This method returns one of
		the <a
		href="../xref/ch/qos/logback/core/spi/FilterReply.html"><code>FilterReply</code></a>
		enumeration values, i.e. one of <code>DENY</code>,
		<code>NEUTRAL</code> or <code>ACCEPT</code>.  If the value
		returned by <code>decide</code>() is <code>DENY</code>, then the
		log event is dropped immediately without consulting the remaining
		filters. If the value returned is <code>NEUTRAL</code>, then the
		next filter in the list is consulted. If there are no further
		filters to consult, then the logging event is processed normally.
		If the returned value is <code>ACCEPT</code>, then the logging
		event is processed immediately skipping the invocation of the
		remaining filters.
    </p>
    
    <p>In logback-classic, filters can be added to
    <code>Appender</code> instances. By adding one or more filters to
    an appender, you can filter events by arbitrary criteria, such as
    the contents of the log message, the contents of the MDC, the time
    of day or any other part of the logging event.
    </p>
    
		<h3 class="doAnchor" name="yourOwnFilter">Implementing your own
		Filter</h3>
		
		<p>Creating your own filter is easy. All you have to do is extend
		the <code>Filter</code> abstract class and implement the
		<code>decide()</code> method.
		</p>
		
		<p>The SampleFilter class shown below provides an example. Its
		<code>decide</code> method returns ACCEPT for logging events
		containing the string "sample" in its message field. For other
		events, the value NEUTRAL is returned.
		</p>
		
    <em>Example: Basic custom filter (<a
    href="../xref/chapters/filters/SampleFilter.html">logback-examples/src/main/java/chapters/filters/SampleFilter.java</a>)</em>
    <pre class="prettyprint source">package chapters.filters;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleFilter extends Filter&gt;ILoggingEvent> {

  @Override
  public FilterReply decide(ILoggingEvent event) {    
    if (event.getMessage().contains("sample")) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }
}</pre>

		<p>The configuration files shown next attaches a
		<code>SampleFilter</code> to a <code>ConsoleAppender</code>.
		</p>

    <em>Example: SampleFilter configuration
    (logback-examples/src/main/java/chapters/filters/SampleFilterConfig.xml)</em>
    <span class="asGroovy" onclick="return asGroovy('SampleFilterConfig');">View as .groovy</span>
    <pre id="SampleFilterConfig" class="prettyprint source">&lt;configuration>
  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <b>&lt;filter class="chapters.filters.SampleFilter" /></b>

    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>
	
  &lt;root>
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre>

		<p>With the help of Joran, logback's configuration framework,
		specifying properties or sub-components to filters is also
		easy. After adding the corresponding setter method in the filter
		class, specify the value of the property in an xml element named
		after the property, nesting it within a <code>&lt;filter></code>
		element. 
		</p>
		
		<p>Often, the desired filter logic consists of two
		orthogonal parts, a match/mismatch test and a response depending
		on the match/mismatch. For example, for a given test, e.g. message
		equals "foobar", one filter might respond ACCEPT on match and
		NEUTRAL on mismatch, and another filter might respond NEUTRAL on
		match and DENY on mismatch. 
    </p>

    <p>Taking notice of this orthogonality, logback ships with the <a
    href="../xref/ch/qos/logback/core/filter/AbstractMatcherFilter.html">
    <code>AbstractMatcherFilter</code></a> class which provides a
    useful skeleton for specifying the appropriate response on match
    and on mismatch, with the help of two properties, named
    <em>OnMatch</em> and <em>OnMismatch</em>. Most of the regular
    filters included in logback are derived from
    <code>AbstractMatcherFilter</code>.
    </p>
		
		<h3 class="doAnchor" name="levelFilter">LevelFilter</h3>
		
		<p><a href="../xref/ch/qos/logback/classic/filter/LevelFilter.html">
		<code>LevelFilter</code></a> filters events based on exact level
		matching. If the event's level is equal to the configured level,
		the filter accepts or denies the event, depending on the
		configuration of the <span class="option">onMatch</span> and <span
		class="option">onMismatch</span> properties. Here is a sample
		configuration file.
		</p>
		
    <em>Example: Sample LevelFilter configuration
    (logback-examples/src/main/java/chapters/filters/levelFilterConfig.xml)</em>
    <span class="asGroovy" onclick="return asGroovy('levelFilterConfig');">View as .groovy</span>
    <pre id="levelFilterConfig" class="prettyprint source">&lt;configuration>
  &lt;appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.classic.filter.LevelFilter">
      &lt;level>INFO&lt;/level>
      &lt;onMatch>ACCEPT&lt;/onMatch>
      &lt;onMismatch>DENY&lt;/onMismatch>
    &lt;/filter></b>
    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>
  &lt;root level="DEBUG">
    &lt;appender-ref ref="CONSOLE" />
  &lt;/root>
&lt;/configuration></pre>

    <h3 class="doAnchor" name="thresholdFilter">ThresholdFilter</h3>

		<p>The <a
		href="../xref/ch/qos/logback/classic/filter/ThresholdFilter.html">
		<code>ThresholdFilter</code></a> filters events below the
		specified threshold. For events of level equal or above the
		threshold, <code>ThresholdFilter</code> will respond NEUTRAL when
		its <code>decide</code>() method is invoked. However, events with
		a level below the threshold will be denied. Here is a sample
		configuration file.
		</p>

    <em>Example: Sample ThresholdFilter configuration
    (logback-examples/src/main/java/chapters/filters/thresholdFilterConfig.xml)</em>
    <span class="asGroovy" onclick="return asGroovy('thresholdFilterConfig');">View as .groovy</span>
    <pre id="thresholdFilterConfig"  class="prettyprint source">&lt;configuration>
  &lt;appender name="CONSOLE"
    class="ch.qos.logback.core.ConsoleAppender">
    &lt;!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
    <b>&lt;filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      &lt;level>INFO&lt;/level>
    &lt;/filter></b>
    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>
  &lt;root level="DEBUG">
    &lt;appender-ref ref="CONSOLE" />
  &lt;/root>
&lt;/configuration></pre>


    <h2 class="doAnchor" name="evalutatorFilter">EvaluatorFilter</h2>

    <p><a
    href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html"><code>EvaluatorFilter</code></a>
    is a generic filter encapsulating an
    <code>EventEvaluator</code>. As the name suggests, an
    <a
    href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html">
    <code>EventEvaluator</code></a> evaluates whether a given criteria
    is met for a given event. On match and on mismatch,
    the hosting <code>EvaluatorFilter</code> will return the value
    specified by the <span class="option">onMatch</span>
    or <span class="option">onMismatch</span> properties respectively.
    </p>


    <p>Note that <code>EventEvaluator</code> is an abstract class. You
    can implement your own event evaluation logic by sub-classing
    <code>EventEvaluator</code>.
    </p>
    

    <!-- ======================== GEventEvaluator ========================= -->

    <h3 class="doAnchor" name="GEventEvaluator">GEventEvaluator</h3>
    
    <p><a
    href="../xref/ch/qos/logback/classic/boolex/GEventEvaluator.html">GEventEvaluator</a>
    is a concrete <a
    href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html"><code>EventEvaluator</code></a>
    implementation taking arbitrary Groovy language boolean
    expressions as the evaluation criteria.  We refer such Groovy
    language boolean expressions as "groovy evaluation
    expressions". Groovy evaluation expressions enable hitherto
    unprecedented flexibility in event
    filtering. <code>GEventEvaluator</code> requires the Groovy
    runtime. Please see the <a
    href="../setup.html#groovy">corresponding section</a> of
    the setup document on adding the Groovy runtime to your class
    path.
    </p>

    <p>Evaluation expressions are compiled on-the-fly during the
    interpretation of the configuration file. As a user, you do not
    need to worry about the actual plumbing. However, it is your
    responsibility to ensure that the groovy-language expression is
    valid.
    </p>

    <p>The evaluation expression acts on the current logging event.
    Logback automatically inserts the current logging event of type <a
    href="../apidocs/ch/qos/logback/classic/spi/ILoggingEvent.html">ILoggingEvent</a>
    as a variable referred to as '<em>event</em>' as well as its
    shorthand referred to as '<em>e</em>'. The variables TRACE, DEBUG,
    INFO, WARN and ERROR are also exported into the scope of the
    expression. Thus, "event.level == DEBUG" and "e.level == DEBUG"
    are equivalent and valid groovy expressions which will return
    <code>true</code> only if the current logging event's level is
    identical to DEBUG. For other comparison operators on levels, the
    level field should be converted to integer with the
    <code>toInt()</code> operator.
    </p>

    <p>Here is a more complete example.</p>

    <span class="asGroovy" onclick="return asGroovy('GEventEvaluator');">View as .groovy</span>
    <pre id="GEventEvaluator"  class="prettyprint source">&lt;configuration>
    
  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
      &lt;evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator"> 
        &lt;expression>
           e.level.toInt() >= WARN.toInt()
             &amp;amp;&amp;amp;  &lt;!-- Stands for &amp;&amp; in XML -->
           !(e.mdc?.get("req.userAgent") ~= /Googlebot|msnbot|Yahoo/ )
        &lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>DENY&lt;/OnMismatch>
      &lt;OnMatch>NEUTRAL&lt;/OnMatch>
    &lt;/filter></b>
    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root level="DEBUG">
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre>


    <p>The above filter will let events of level WARN and higher go
    through onto the console unless the error is generated by Web
    crawlers associated with Google, MSN or Yahoo. It does so by
    checking whether the MDC associated with the event contains a
    value for "req.userAgent" matching the
    <code>/Googlebot|msnbot|Yahoo/</code> regular expression. Note
    that since the MDC map can be null, we are also using Groovy's <a
    href="http://groovy.codehaus.org/Null+Object+Pattern">safe
    dereferencing operator</a>, that is the ?. operator. The equivalent
    logic would have been much longer if expressed in Java.
    </p>
    
    <p>If you are wondering how the identifier for the user agent was
    inserted into the MDC under the 'req.userAgent' key, it behooves
    us to mention that logback ships with a servlet filter named <a
    href="mdc.html#mis"><code>MDCInsertingServletFilter</code></a>
    designed for this purpose. It will be described in a later
    chapter.
    </p>

    <!-- ==================== JaninoEventEvaluator ======================== -->
    
    <h3 class="doAnchor"
    name="JaninoEventEvaluator">JaninoEventEvaluator</h3>
    

    <p>Logback-classic ships with another concrete
    <code>EventEvaluator</code> implementation called <a
    href="../xref/ch/qos/logback/classic/boolex/JaninoEventEvaluator.html">JaninoEventEvaluator</a>
    taking an arbitrary Java language block returning a boolean value
    as the evaluation criteria. We refer to such Java language boolean
    expressions as "<em>evaluation expressions</em>". Evaluation
    expressions enable great flexibility in event
    filtering. <code>JaninoEventEvaluator</code> requires the <a
    href="http://docs.codehaus.org/display/JANINO/Home">Janino
    library</a>. Please see the <a
    href="../setup.html#janino">corresponding section</a> of the setup
    document.  Compared to <code>JaninoEventEvaluator</code>,
    <code>GEventEvaluator</code>, by virtue of the Groovy language, is
    significantly more convenient to use, but
    <code>JaninoEventEvaluator</code> will usually run (much) faster
    for equivalent expressions.
    </p>

    <p>Evaluation expressions are compiled on-the-fly during the
    interpretation of the configuration file. As a user, you do not
    need to worry about the actual plumbing. However, it is your
    responsibility to ensure that the Java language expression returns
    a boolean, i.e. that it evaluates to true or false. </p>


    <p>The evaluation expression is evaluated on the current logging
    event. Logback-classic automatically exports various fields of the
    logging event as variables accessible from the evaluation
    expression. The case-sensitive names of these exported variables
    are listed below.
    </p>

		<table class="bodyTable">
      <tr>
        <th>Name</th>
        <th>Type</th>
        <th>Description</th>
			</tr>
      <tr>
				<td>event</td>
				<td><code>LoggingEvent</code></td>

        <td>The raw logging event associated with the logging
        request. All of the following variables are also available
        from the event. For example, <code>event.getMessage()</code>
        returns the same String value as the <em>message</em> variable
        described next.
        </td>
			</tr>

      <tr class="alt">
				<td>message</td>
        <td><code>String</code></td>
        <td>The raw message of the logging request. For some logger
        <em>l</em>, when you write l.info("Hello {}", name); where
        name is assigned the value "Alice", then "Hello {}" is the
        message.</td> </tr>
		
      <tr>
				<td>formattedMessage</td>
        <td><code>String</code></td>
        <td>The formatted message in the logging request. For some
        logger <em>l</em>, when you write l.info("Hello {}", name);
        where name is assigned the value "Alice", then "Hello Alice"
        is the formatted message.</td>
			</tr>
		
      <tr class="alt">
				<td>logger</td>
				<td><code>String</code></td>
				<td>The name of the logger.
        </td>
			</tr>

      <tr>
        <td>loggerContext</td>
				<td><a
				href="../xref/ch/qos/logback/classic/spi/LoggerContextVO.html"><code>LoggerContextVO</code></a></td>
				<td>A restricted (value object) view of the logger context to which the logging event belongs to.
        </td>
			</tr>


			<tr class="alt">
				<td>level</td>
				<td><code>int</code></td>
				<td>The int value corresponding to the level. To help create
				easily expressions involving levels, the default value
				<em>DEBUG</em>, <em>INFO</em>, <em>WARN</em> and
				<em>ERROR</em> are also available. Thus, using <em>level &gt;
				INFO</em> is a correct expression.
				</td>
			</tr>

			<tr>
				<td>timeStamp
				</td>
				<td><code>long</code></td>
				<td>The timestamp corresponding to the logging event's
				creation.
				</td>
			</tr>
			<tr class="alt">
				<td>marker</td>
				<td><code>Marker</code></td>
        <td>The <code>Marker</code> object associated with the logging
        request. Note that marker can be null and it is your
        responsibility to check for this condition in order to avoid
        <code>NullPointerException</code>.
				</td>
			</tr>
			<tr>
				<td>mdc</td>
				<td><code>Map</code></td>
				<td>A map containing all the MDC values at the time of the
				creation of the logging event. A value can be accessed by
				using the following expression: <em>mdc.get("myKey")</em>. As
				of logback-classic version 0.9.30, the 'mdc' variable will
				never be null.

        <p>The <code>java.util.Map</code> type is non-parameterized
        because Janino does not support generics. It follows that the
        type returned by <code>mdc.get()</code> is <code>Object</code>
        and not <code>String</code>. To invoke <code>String</code>
        methods on the returned value, it must be cast as
        <code>String</code>. For example,
        <code>((String)&nbsp;mdc.get("k")).contains("val")</code>.
        </p>
				</td>
			</tr>

      <tr class="alt">
				<td>throwable</td>
        <td>java.lang.Throwable</td>
				<td>If no exception is associated with the event, then the
				value of the "throwable" variable will be null. Unfortunately,
				"throwable" does not survive serialization. Thus, on remote
				systems, its value will always be null. For location
				independent expressions, use the <code>throwableProxy</code>
				variable described next.
				</td>
			</tr>

			<tr>
				<td>throwableProxy</td>
				<td><a
				href="../xref/ch/qos/logback/classic/spi/IThrowableProxy.html"><code>IThrowableProxy</code></a></td>
				<td>A proxy for the exception associated with the logging
				event. If no exception is associated with the event, then the
				value of the "throwableProxy" variable will be null. In
				contrast to "throwable", when an exception is associated with
				an event, the value of "throwableProxy" will be non-null even
				on remote systems, that is even after serialization.
				</td>
			</tr>

    

		</table>

    <p>Here is a concrete example.</p>

    <em>Example: Basic event evaluator usage
    (logback-examples/src/main/java/chapters/filters/basicEventEvaluator.xml)</em>

    <span class="asGroovy" onclick="return asGroovy('basicEventEvaluator');">View as .groovy</span>
    <pre id="basicEventEvaluator" class="prettyprint source longline">&lt;configuration>

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
      &lt;evaluator> &lt;!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
        &lt;expression><span class="green">return message.contains("billing");</span>&lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>DENY&lt;/OnMatch>
    &lt;/filter></b>
    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root level="INFO">
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre>

		<p>The bold part in the above configuration file adds an
		<code>EvaluatorFilter</code> to a <code>ConsoleAppender</code>. An
		evaluator of type <code>JaninoEventEvaluator</code> is then
		injected into the <code>EvaluatorFilter</code>. In the absence of
		<span class="attr">class</span> attribute in the
		<code>&lt;evaluator></code> element specified by the user, Joran
		will infer a default type of <code>JaninoEventEvaluator</code>
		for the evaluator. This is one of the <a
		href="onJoran.html#defaultClassMapping">few occurrences</a> where
		Joran implicitly infers the type of a component.
    </p>

    <p>The <em>expression</em> element corresponds to the evaluation
    expression just discussed. The expression
    <code>return message.contains("billing");</code> returns a boolean
    value. Notice that the <em>message</em> variable is exported
    automatically by <code>JaninoEventEvaluator</code>.
    </p>

		<p>Given that the <span class="option">OnMismatch</span> property is
		set to NEUTRAL and the <span class="option">OnMatch</span>
		property set to DENY, this evaluator filter will drop all logging
		events whose message contains the string "billing".
    </p>

    <p>The <a
    href="../xref/chapters/filters/FilterEvents.html"><code>FilterEvents</code></a>
    application issues ten logging requests, numbered 0 to 9. Let us
    first run <code>FilterEvents</code> class without any filters:
		</p>
		
<div class="source"><pre>
java chapters.filters.FilterEvents src/main/java/chapters/filters/basicConfiguration.xml
</pre></div>
		
		<p>All requests will be displayed, as shown below:</p>

<div class="source"><pre>0    [main] INFO  chapters.filters.FilterEvents - logging statement 0
0    [main] INFO  chapters.filters.FilterEvents - logging statement 1
0    [main] INFO  chapters.filters.FilterEvents - logging statement 2
0    [main] DEBUG chapters.filters.FilterEvents - logging statement 3
0    [main] INFO  chapters.filters.FilterEvents - logging statement 4
0    [main] INFO  chapters.filters.FilterEvents - logging statement 5
0    [main] ERROR chapters.filters.FilterEvents - <b>billing statement 6</b>
0    [main] INFO  chapters.filters.FilterEvents - logging statement 7
0    [main] INFO  chapters.filters.FilterEvents - logging statement 8
0    [main] INFO  chapters.filters.FilterEvents - logging statement 9</pre></div>



		<p>Suppose that we want to get rid of the "billing statement".
		The <em>basicEventEvaluator.xml</em> configuration file listed
		above filters messages containing the string "billing" which is
		precisely the desired outcome.</p>

    <p>Running with <em>basicEventEvaluator.xml</em>:</p>
    <p class="source">java chapters.filters.FilterEvents src/main/java/chapters/filters/basicEventEvaluator.xml</p>
    <p>we obtain:
		</p>
		
    <p class="source">0    [main] INFO  chapters.filters.FilterEvents - logging statement 0
0    [main] INFO  chapters.filters.FilterEvents - logging statement 1
0    [main] INFO  chapters.filters.FilterEvents - logging statement 2
0    [main] DEBUG chapters.filters.FilterEvents - logging statement 3
0    [main] INFO  chapters.filters.FilterEvents - logging statement 4
0    [main] INFO  chapters.filters.FilterEvents - logging statement 5
0    [main] INFO  chapters.filters.FilterEvents - logging statement 7
0    [main] INFO  chapters.filters.FilterEvents - logging statement 8
0    [main] INFO  chapters.filters.FilterEvents - logging statement 9</p>
		

    <p>Evaluation expressions can be Java blocks. For example, the
    following is a valid expression.</p>

    <pre class="prettyprint source">&lt;evaluator>
  &lt;expression>
    if(logger.startsWith("org.apache.http"))
      return true;

    if(mdc == null || mdc.get("entity") == null)
      return false;

    String payee = (String) mdc.get("entity");

    if(logger.equals("org.apache.http.wire") &amp;amp;&amp;amp; &lt;!-- &amp; encoded as &amp;amp; -->
        payee.contains("someSpecialValue") &amp;amp;&amp;amp;
        !message.contains("someSecret")) {
      return true;
    }

    return false;
  &lt;/expression>
&lt;/evaluator></pre>


 	  <h2 class="doAnchor" name="matcher">Matchers</h2>

    <p>While it is possible to do pattern matching by invoking the <a
    href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#matches%28java.lang.String%29">matches()</a>
    method in the <code>String</code> class, this incurs the cost of
    compiling of a brand new <code>Pattern</code> object each time the
    filter is invoked. To eliminate this overhead, you can predefine
    one or more <a
    href="../xref/ch/qos/logback/core/boolex/Matcher.html">Matcher</a>
    objects. Once a matcher is defined, it can be repeatedly
    referenced by name in the evaluator expression.</p>

    <p>An example should clarify the point:</p>

    <em>Example: Defining matchers in an event evaluator (logback-examples/src/main/java/chapters/filters/evaluatorWithMatcher.xml)</em>
    <span class="asGroovy" onclick="return asGroovy('evaluatorWithMatcher');">View as .groovy</span>

    <pre id="evaluatorWithMatcher" class="prettyprint source">&lt;configuration debug="true">

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator>        
        <b>&lt;matcher>
          &lt;Name>odd&lt;/Name>
          &lt;!-- filter out odd numbered statements -->
          &lt;regex>statement [13579]&lt;/regex>
        &lt;/matcher>
        
        &lt;expression>odd.matches(formattedMessage)&lt;/expression></b>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>DENY&lt;/OnMatch>
    &lt;/filter>
    &lt;encoder>
      &lt;pattern>%-4relative [%thread] %-5level %logger - %msg%n&lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root level="DEBUG">
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre>

    <p>Running with <em>evaluatorWithMatcher.xml</em>:</p>
    <p class="source">java chapters.filters.FilterEvents src/main/java/chapters/filters/evaluatorWithMatcher.xml</p>
    <p>we obtain:
		</p>
		
    <p class="source">260  [main] INFO  chapters.filters.FilterEvents - logging statement 0
264  [main] INFO  chapters.filters.FilterEvents - logging statement 2
264  [main] INFO  chapters.filters.FilterEvents - logging statement 4
266  [main] ERROR chapters.filters.FilterEvents - billing statement 6
266  [main] INFO  chapters.filters.FilterEvents - logging statement 8</p>

    <p>If you need to define additional matchers, you can do so by
    adding further <code>&lt;matcher></code> elements.</p>





    <!-- ================================================================ -->
    <!-- ===================== TURBO FILTER ============================= -->
    <!-- ================================================================ -->

    <h2 class="doAnchor" name="TurboFilter">TurboFilters</h2>
    
    <p><code>TurboFilter</code> objects all extend the
    	<a href="../xref/ch/qos/logback/classic/turbo/TurboFilter.html">
    	<code>TurboFilter</code></a> abstract class. Like the regular
    	filters, they use ternary logic to return their evaluation of
    	the logging event.
    </p>
    
    <p>Overall, they work much like the previously mentioned
    filters. However, there are two main differences between
    <code>Filter</code> and <code>TurboFilter</code> objects.
    </p>
    
   	<p><code>TurboFilter</code> objects are tied to the logging
   	context. Hence, they are called not only when a given appender is
   	used, but each and every time a logging request is issued. Their
   	scope is wider than appender-attached filters.
   	</p>
   	
   	<p>More importantly, they are called before the
   	<code>LoggingEvent</code> object creation.
   	<code>TurboFilter</code> objects do not require the instantiation
   	of a logging event to filter a logging request. As such, turbo
   	filters are intended for high performance filtering of logging
	events, even before the events are created.
    </p>

   	
   	<h3 class="doAnchor" name="yourOwnTurboFilter">Implementing your
   	own TurboFilter</h3>
    
    <p>To create your own <code>TurboFilter</code> component, just
    extend the <code>TurboFilter</code> abstract class. As previously,
    when implementing a customized filter object, developing a custom
    <code>TurboFilter</code> only asks that one implement the
    <code>decide()</code> method. In the next example, we create a
    slightly more complex filter:
    </p>
    
<em>Example: Basic custom <code>TurboFilter</code> (<a href="../xref/chapters/filters/SampleTurboFilter.html">logback-examples/src/main/java/chapters/filters/SampleTurboFilter.java</a>)</em>		
<pre class="prettyprint source">package chapters.filters;

import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleTurboFilter extends TurboFilter {

  String marker;
  Marker markerToAccept;

  @Override
  public FilterReply decide(Marker marker, Logger logger, Level level,
      String format, Object[] params, Throwable t) {

    if (!isStarted()) {
      return FilterReply.NEUTRAL;
    }

    if ((markerToAccept.equals(marker))) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }

  public String getMarker() {
    return marker;
  }

  public void setMarker(String markerStr) {
    this.marker = markerStr;
  }

  @Override
  public void start() {
    if (marker != null &amp;&amp; marker.trim().length() > 0) {
      markerToAccept = MarkerFactory.getMarker(marker);
      super.start(); 
    }
  }
}
</pre>

		<p>The <code>TurboFilter</code> above accepts events that contain
		a specific marker.  If said marker is not found, then the filter
		passes the responsibility to the next filter in the chain.
		</p>
		
		<p>To allow more flexibility, the marker that will be tested can
		be specified in the configuration file, hence the getter and
		setter methods. We also implemented the <code>start()</code>
		method, to check that the option has been specified during the
		configuration process.
		</p>
		
		<p>Here is a sample configuration that makes use of our newly
		created <code>TurboFilter</code>.
		</p>
		
    <em>Example: Basic custom <code>TurboFilter</code> configuration
    (logback-examples/src/main/java/chapters/filters/sampleTurboFilterConfig.xml)</em>

    <span class="asGroovy" onclick="return asGroovy('sampleTurboFilterConfig');">View as .groovy</span>

    <pre id="sampleTurboFilterConfig"  class="prettyprint source">&lt;configuration>
  <b>&lt;turboFilter class="chapters.filters.SampleTurboFilter">
    &lt;Marker>sample&lt;/Marker>
  &lt;/turboFilter></b>

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    &lt;encoder>
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root>
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre>  

   	<p>Logback classic ships with several <code>TurboFilter</code>
   	classes ready for use.  The <a
   	href="../xref/ch/qos/logback/classic/turbo/MDCFilter.html"><code>MDCFilter</code></a>
   	checks the presence of a given value in the MDC whereas <a
   	href="../apidocs/ch/qos/logback/classic/turbo/DynamicThresholdFilter.html"><code>DynamicThresholdFilter</code></a>
   	allows filtering based on MDC key/level threshold associations. On
   	the other hand, <a
   	href="../xref/ch/qos/logback/classic/turbo/MarkerFilter.html"><code>MarkerFilter</code></a>
   	checks for the presence of a specific marker associated with the
   	logging request.
   	</p>
   	
   	<p>Here is a sample configuration, using both
   	<code>MDCFilter</code> and <code>MarkerFilter</code>.
   	</p>
   	
    <em>Example: <code>MDCFilter</code> and <code>MarkerFilter</code>
    configuration
    (logback-examples/src/main/java/chapters/filters/turboFilters.xml)</em>

    <span class="asGroovy" onclick="return asGroovy('turboFilters');">View as .groovy</span>
    <pre id="turboFilters" class="prettyprint source">&lt;configuration>

  &lt;turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
    &lt;MDCKey>username&lt;/MDCKey>
    &lt;Value>sebastien&lt;/Value>
    &lt;OnMatch>ACCEPT&lt;/OnMatch>
  &lt;/turboFilter>
	
  &lt;turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    &lt;Marker>billing&lt;/Marker>
    &lt;OnMatch>DENY&lt;/OnMatch>
  &lt;/turboFilter>

  &lt;appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    &lt;encoder>
      &lt;pattern>%date [%thread] %-5level %logger - %msg%n&lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root level="INFO">
    &lt;appender-ref ref="console" />
  &lt;/root>  
&lt;/configuration></pre>

		<p>You can see this configuration in action by issuing the
		following command:
		</p>
    
    <p class="source">java chapters.filters.FilterEvents src/main/java/chapters/filters/turboFilters.xml</p>

		<p>As we've seen previously, the <a
		href="../xref/chapters/filters/FilterEvents.html"><code>FilterEvents</code></a>
		application issues 10 logging requests, numbered 0 to 9. Except
		for requests 3 and 6, all of the requests are of level
		<em>INFO</em>, the same level as the one assigned to the root
		logger. The 3rd request, is issued at the the <em>DEBUG</em>
		level, which is below the effective level. However, since the MDC
		key "username" is set to "sebastien" just before the 3rd request
		and removed just afterwards, the <code>MDCFilter</code>
		specifically accepts the request (and only that request). The 6th
		request, issued at the <em>ERROR</em> level, is marked as
		"billing". As such, it is denied by the MarkerFilter (the second
		turbo filter in the configuration).
		</p>
		
		<p>Thus, the output of <code>FilterEvents</code> application
		configured with <em>turboFilters.xml</em> file shown above is:
		</p>

    <p class="source">2006-12-04 15:17:22,859 [main] INFO  chapters.filters.FilterEvents - logging statement 0
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 1
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 2
2006-12-04 15:17:22,875 [main] DEBUG chapters.filters.FilterEvents - logging statement 3
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 4
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 5
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 7
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 8
2006-12-04 15:17:22,875 [main] INFO  chapters.filters.FilterEvents - logging statement 9</p>
			
			
		<p>One can see that the 3rd request, which should not be displayed
		if we only followed the overall <em>INFO</em> level, appears
		anyway, because it matched the first <code>TurboFilter</code>
		requirements and was accepted.
		</p>    
		
		<p>On the other hand, the 6th request, that is an <em>ERROR</em>
		level request should have been displayed. But it satisfied the
		second <code>TurboFilter</code> whose <span
		class="option">OnMatch</span> option is set to <em>DENY</em>.
		Thus, the 6th request was not displayed.
		</p>
		


		  
    <h3 class="doAnchor"
    name="DuplicateMessageFilter">DuplicateMessageFilter</h3>

    <p>The <code>DuplicateMessageFilter</code> merits a separate
    presentation.  This filter detects duplicate messages, and beyond
    a certain number of repetitions, drops repeated messages.
    </p>

    <p>To detect repetition, this filter uses simple String equality
    between messages. It does not detect messages which are very
    similar, varying only by few characters. For example, if you
    write:
    </p>

    <pre class="prettyprint source">logger.debug("Hello "+name0);
logger.debug("Hello "+name1);</pre>
  
    <p>Assuming <code>name0</code> and <code>name1</code> have
    different values, the two "Hello" messages will be considered as
    unrelated. Depending on user demand, future releases may check for
    string similarity, eliminating repetitions of similar but not
    identical messages.
    </p>

    <p>Note that in case of parameterized logging, only the raw
    message is taken into consideration. For example, in the next two
    requests, the raw messages, i.e. "Hello {}.", are identical, and
    thus considered as repetitions.
    </p>

    <pre class="prettyprint source">logger.debug("Hello {}.", name0);
logger.debug("Hello {}.", name1);</pre>
  
    <p>The number of allowed repetitions can be specified by the <span
    class="option">AllowedRepetitions</span> property. For example, if
    the property is set to 1, then the 2nd and subsequent
    occurrences of the same message will be dropped. Similarly, if the
    property is set to 2, then the 3rd and subsequent occurrences
    of the same message will be dropped. By default, the <span
    class="option">AllowedRepetitions</span> property is set to 5.
    </p>

    <p>In order to detect repetitions, this filter needs to keep
    references to old messages in an internal cache. The size of this
    cache is determined by the <span class="option">CacheSize</span>
    property. By the default, this is set to 100.
    </p>

    
    <em>Example: <code>DuplicateMessageFilter</code> 
    configuration (logback-examples/src/main/java/chapters/filters/duplicateMessage.xml)</em>

    <span class="asGroovy" onclick="return asGroovy('duplicateMessage');">View as .groovy</span>
    <pre id="duplicateMessage" class="prettyprint source">&lt;configuration>

  <b>&lt;turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter"/></b>

  &lt;appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    &lt;encoder>
      &lt;pattern>%date [%thread] %-5level %logger - %msg%n&lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;root level="INFO">
    &lt;appender-ref ref="console" />
  &lt;/root>  
&lt;/configuration></pre>

  <p>Thus, the output for <code>FilterEvents</code> application
  configured with <em>duplicateMessage.xml</em> is:
  </p>

    <p class="source">2008-12-19 15:04:26,156 [main] INFO  chapters.filters.FilterEvents - logging statement 0
2008-12-19 15:04:26,156 [main] INFO  chapters.filters.FilterEvents - logging statement 1
2008-12-19 15:04:26,156 [main] INFO  chapters.filters.FilterEvents - logging statement 2
2008-12-19 15:04:26,156 [main] INFO  chapters.filters.FilterEvents - logging statement 4
2008-12-19 15:04:26,156 [main] INFO  chapters.filters.FilterEvents - logging statement 5
2008-12-19 15:04:26,171 [main] ERROR chapters.filters.FilterEvents - billing statement 6</p>

    <p>"logging statement 0" is the first <em>occurrence</em> of the
    message "logging statement {}". "logging statement 1" is the first
    <em>repetition</em>, "logging statement 2" is the second
    repetition. Interestingly enough, "logging statement 3" of level
    DEBUG, is the <em>third</em> repetition, even though it is later
    dropped by virtue of the <a
    href="architecture.html#basic_selection">basic selection
    rule</a>. This can be explained by the fact that turbo filters are
    invoked before other types of filters, including the basic
    selection rule. Thus, <code>DuplicateMessageFilter</code>
    considers "logging statement 3" as a repetition, oblivious to the
    fact that it will be dropped further down in the processing
    chain. "logging statement 4" is the fourth repetition and "logging
    statement 5" the fifth. Statements 6 and beyond are dropped
    because only 5 repetitions are allowed by default.
    </p>

    <h1 class="doAnchor" name="logbac-access">In logback-access</h1>
    
    <p>Logback-access offers most of the features available with
    logback-classic. In particular, <code>Filter</code> objects are
    available and work in the same way as their logback-classic
    counterparts, with one notable difference. Instead of
    <code>LoggingEvent</code> instances logback-access filters act
    upon <a
    href="../xref/ch/qos/logback/access/spi/AccessEvent.html"><code>AccessEvent</code></a>
    instances. At present time, logback-access ships with a limited
    number of filters described below. If you would like to suggest
    additional filters, please contact the logback-dev mailing list.
    </p>

		<h2 class="doAnchor"
		name="countingFilter"><code>CountingFilter</code></h2>
		
		<p>With the help of <a
		href="xref/ch/qos/logback/access/filter/CountingFilter.html"><code>CountingFilter</code></a>
		class, logback-access can provide statistical data about access to
		the web-server. Upon initialization, <code>CountingFilter</code>
		registers itself as an MBean onto the platform's JMX server. You
		can then interrogate that MBean for statistical data,
		e.g. averages by minute, hour, day, week, or month. Other
		statistics such the count for the preceding week, day, hour or
		month as well as the total count are also available.
		</p>
		
		<p>The following <em>logback-access.xml</em> configuration file
		declares a <code>CountingFilter</code>.  </p>

    <pre class="prettyprint source">&lt;configuration>
  &lt;statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  <b>&lt;filter class="ch.qos.logback.access.filter.CountingFilter">
    &lt;name>countingFilter&lt;/name>
  &lt;/filter></b>

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    &lt;encoder>
      &lt;pattern>%h %l %u %t \"%r\" %s %b&lt;/pattern>
    &lt;/encoder>
  &lt;/appender>

  &lt;appender-ref ref="STDOUT" />
&lt;/configuration></pre>

    <p>You can examine the various statistics maintained by
    <code>CountingFilter</code> on your platform's JMX server via the
    <code>jconsole</code> application. </p>


    <img alt="CountingFilter via jconsole" src="images/chapters/filters/countingFilter.png" />
	

    <h3 class="doAnchor" name="access_EvalutorFilter">EvaluatorFilter</h3>

    
    <p><a
    href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html"><code>EvaluatorFilter</code></a>
    is a generic filter encapsulating an
    <code>EventEvaluator</code>. As the name suggests, an
    <a
    href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html">
    <code>EventEvaluator</code></a> evaluates whether a given criteria
    is met for a given event. On match and on mismatch,
    the hosting <code>EvaluatorFilter</code> will return the value
    specified by the <span class="option">onMatch</span> or
    <span class="option">onMismatch</span> properties respectively. Note that
    <code>EvaluatorFilter</code> has been previously discussed in the
    context of logback-classic (<a href="#evalutatorFilter">see
    above</a>). The present text is mostly a repetition of the
    previous discussion.</p>


    <p>Note that <code>EventEvaluator</code> is an abstract class. You
    can implement your own event evaluation logic by sub-classing
    <code>EventEvaluator</code>. Logback-access ships with a concrete
    implementation named <a
    href="../xref/ch/qos/logback/access/boolex/JaninoEventEvaluator.html">JaninoEventEvaluator</a>.
    It takes arbitrary Java language boolean expressions as the
    evaluation criteria. We refer to such Java language blocks as
    "<em>evaluation expressions</em>". Evaluation expressions enable
    great flexibility in event
    filtering. <code>JaninoEventEvaluator</code> requires the <a
    href="http://docs.codehaus.org/display/JANINO/Home">Janino
    library</a>. Please see the <a
    href="../setup.html#janino">corresponding section</a> of the setup
    document.
    </p>

    <p>Evaluation expressions are compiled on-the-fly during the
    interpretation of the configuration file. As a user, you do not
    need to worry about the actual plumbing. However, it is your
    responsibility to ensure that the Java language expression returns
    a boolean, i.e. that it evaluates to true or false. </p>


    <p>The evaluation expression is evaluated on the current access
    event. Logback-access automatically exports the current
    <code>AccessEvent</code> instance under the variable name
    <b><code>event</code></b>. You can read the various data
    associated with the HTTP request as well as the HTTP response via
    the <code>event</code> variable. Please refer to the <a
    href="../xref/ch/qos/logback/access/spi/AccessEvent.html"><code>AccessEvent</code>
    class source code</a> for the exact list.
    </p>
    
    <p>The next logback-access configuration file illustrates
    filtering based on the <a
    href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">404
    (Not Found)</a> HTTP response code. Every request resulting in a
    404 will be printed on the console.</p>
   	
<em>Example: Access Evaluator (logback-examples/src/main/java/chapters/filters/accessEventEvaluator.xml)</em>
<pre class="prettyprint source">&lt;configuration>
  &lt;statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator>
        &lt;expression>event.getStatusCode() == 404&lt;/expression>
      &lt;/evaluator>
      &lt;onMismatch>DENY&lt;/onMismatch>
    &lt;/filter></b>
   &lt;encoder>&lt;pattern>%h %l %u %t %r %s %b&lt;/pattern>&lt;/encoder>
  &lt;/appender>

  &lt;appender-ref ref="STDOUT" />
&lt;/configuration></pre>

		<p>In the next example, we still log requests resulting in 404 errors,
		except those requests asking for CSS files.
		</p>	


    <em>Example 6.10: Access Evaluator (logback-examples/src/main/java/chapters/filters/accessEventEvaluator2.xml)</em>
    <pre class="prettyprint source">&lt;configuration>
  &lt;statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator name="Eval404">
        &lt;expression>
         <b>(event.getStatusCode() == 404)</b>
           <b>&amp;amp;&amp;amp;</b>  &lt;!-- ampersand characters need to be escaped -->
         <b>!(event.getRequestURI().contains(".css"))</b>
        &lt;/expression>
      &lt;/evaluator>
      &lt;onMismatch>DENY&lt;/onMismatch>
    &lt;/filter>

   &lt;encoder>&lt;pattern>%h %l %u %t %r %s %b&lt;/pattern>&lt;/encoder>
  &lt;/appender>

  &lt;appender-ref ref="STDOUT" />
&lt;/configuration>
    </pre>
	
    <script src="../templates/footer.js" type="text/javascript"></script>

  </div>
</body>
</html>