<document>
<!-- 
		
		Warning: do not use any auto-format function on this file.
		Since "source" divs use pre as white-space, it affects the
		look of the code parts in this document.
		
-->

	<body>
		<h2>Chapter 6: Filter chains</h2>
		<div class="author">
			Authors: Ceki G&#252;lc&#252;, S&#233;bastien Pennec
		</div>

		<table>
			<tr>
				<td valign="top" align="top">
						<a rel="license"
							href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
							<img alt="Creative Commons License"
								style="border-width: 0"
								src="http://creativecommons.org/images/public/somerights20.png" />
						</a>
				</td>
				<td>
					<p>Copyright &#169; 2000-2006, QOS.ch</p>

					<p>
						<!--Creative Commons License-->
						This work is licensed under a
						<a rel="license"
							href="http://creativecommons.org/licenses/by-nc-sa/2.5/">
							Creative Commons
							Attribution-NonCommercial-ShareAlike 2.5
							License
						</a>.
						<!--/Creative Commons License-->
					</p>
				</td>
			</tr>
		</table>
		
		<p>
			As we have seen, logback has several built-in ways for filtering log requests, 
			including the context-wide filter, logger-level selection rule and appender filters. 
			These provide high performance filtering for the most commonly encountered 
			cases. These filters are largely inspired from Linux ipchains or 
			iptables as they are called in more recent Linux kernels. 
			Logback filters are based on ternary logic allowing them to be assembled or chained 
			together to compose an arbitrarily complex filtering policy.
		</p>
	
		<div class="highlight">
    <p>
      In order to run the examples in this chapter, you need
      to make sure that certain jar files are present on the
      classpath.
    	Please refer to the <a href="../setup.html">setup page</a>
    	for further details.
    </p>
    </div>
    
		<p>
			There are two main types of filters, namely <code>Filter</code> and 
			<code>TurboFilter</code>.
		</p>
		
		<h2>Logback Classic</h2>
		
		<a name="Filter" />
		<p><code>Filter</code> objects all implement the 
		<a href="../xref/ch/qos/logback/core/filter/Filter.html"><code>Filter</code></a> 
		abscract class. The <code>decide(Object event)</code> method is passed a
		newly created <code>LoggingEvent</code> object.
		</p>
		
		<h3>Filter chains</h3>
		<p>
			This abstract class assumes that filters be organized in a linear chain. 
			Its member field next points to the next filter in the chain, or 
			<code>null</code> if there are no further filters in the chain. 
			Figure 6.1 depicts a sample filter chain consisting of three filters.
		</p>
		
		<img src="images/chapter6/filterChain.gif" alt="A sample filter chain"/>

    <p>
    	Filters are based on ternary logic. The <code>decide(Object event)</code> 
    	method of each filter is called in sequence. This method returns one of the 
    	enumerations <code>FilterReply.DENY</code>, <code>FilterReply.NEUTRAL</code> or 
    	<code>FilterReply.ACCEPT</code>. If the returned value is <code>FilterReply.DENY</code>, 
    	then the log event is dropped immediately without consulting the 
    	remaining filters. If the value returned is <code>FilterReply.NEUTRAL</code>, 
    	then the next filter in the chain is consulted. If there are no further filters 
    	to consult, then the logging event is processed normally. 
    	If the returned value is <code>FilterReply.ACCEPT</code>, then the logging 
    	event is processed immediately skipping the remaining filters.
    </p>
    
    <p>
    	In logback-classic, <code>Filter</code> objects can only be added to <code>Appender</code>
    	instances. By adding filters to an appender you can filter events by various 
    	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>Implementing your own Filter</h3>
		
		<p>
			Creating your own filter is not difficult. All you have to do is extend the <code>Filter</code> 
			abstract class. The only method that you will have to implement is the <code>decide()</code> 
			method, allowing you to contentrate only on the behaviour of your filter.
		</p>
		
		<p>
			The next class is all it takes to implement one's own filter. All it does is accept
			logging events who's message contains the String <em>sample</em>. The filter will give a 
			neutral response to any logging event who's message does not contain this String.
		</p>
		
<em>Example 6.1: Basic custom filter (<a href="../xref/chapter6/SampleFilter.html">logback-examples/src/main/java/chapter6/SampleFilter.java</a>)</em>		
<div class="source"><pre>package chapter6;

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

public class SampleFilter extends Filter {

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

		<p>
			What is shown above might be the simplest filter. Like any filter, it
			can be attached to any appender using the &lt;Filter&gt; element, as
			shown below:
		</p>

<em>Example 6.2: SampleFilter configuration (logback-examples/src/main/java/chapter6/SampleFilterConfig.xml)</em>				
<div class="source"><pre>&lt;configuration>
  &lt;appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;Filter class="chapter6.SampleFilter" /></b>

    &lt;layout class="ch.qos.logback.classic.PatternLayout">
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>
	
  &lt;root>
    &lt;appender-ref ref="STDOUT" />
  &lt;/root>
&lt;/configuration></pre></div>

		<p>
			Thanks to Joran, logback's powerful configuration framework, adding
			an option to such a filter is very easy. Just add the corresponding
			getter and setter methods in the class, and you can specify the
			option's value in an xml element, nested within the <em>filter</em> element.
		</p>
		
		<p>
			In case you want to implement a filter that provides different behaviour
			depending on the result of its test (say, a filter that would accept or deny
			an event depending on the content of its message), you can extend the
			<a href="../xref/ch/qos/logback/core/filter/AbstractMatcherFilter.html">
			<code>AbstractMatcherFilter</code></a> class. It will provide your filter with 
			two attribute: <em>OnMatch</em> and <em>OnMismatch</em>, that can be configured
			like any other option.
		</p>
		
		<h3>Logback Filters</h3>
		
		<p>
			As the moment, there are two filters that ship with logback.
			<a href="../xref/ch/qos/logback/classic/LevelFilter.html">
			<code>LevelFilter</code></a> provides event filtering based on a <code>Level</code> value. 
			It the event's level is equal to the configured level, the filter accepts of denies
			the event, depending on its configuration. It allows you to choose the
			behaviour of logback for a precise given level. Here is a sample configuration that
			uses <code>LevelFilter</code>.
		</p>
		
<em>Example 6.3: Sample LevelFilter configuration (logback-examples/src/main/java/chapter6/LevelFilterConfig.xml)</em>				
<div class="source"><pre>&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;layout class="ch.qos.logback.classic.PatternLayout">
      &lt;pattern>
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>
  &lt;root>
    &lt;level value="DEBUG" />
    &lt;appender-ref ref="CONSOLE" />
  &lt;/root>
&lt;/configuration></pre></div>

		<p>
			The second filter that ships with logback is 
			<a href="../xref/ch/qos/logback/classic/ThresholdFilter.html">
			<code>ThresholdFilter</code></a>.
			It is also based on level value, but acts as a threshold to deny any request
			whose level is not equal or greater to the configured level. A sample
			use of the <code>ThresholdFilter</code> is shown below.
		</p>

<em>Example 6.4: Sample ThresholdFilter configuration (logback-examples/src/main/java/chapter6/ThresholdFilterConfig.xml)</em>				
<div class="source"><pre>&lt;configuration>
  &lt;appender name="CONSOLE"
    class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      &lt;level>INFO&lt;/level>
    &lt;/filter></b>
    &lt;layout class="ch.qos.logback.classic.PatternLayout">
      &lt;pattern>
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>
  &lt;root>
    &lt;level value="DEBUG" />
    &lt;appender-ref ref="CONSOLE" />
  &lt;/root>
&lt;/configuration></pre></div>

		<h3>Evaluator Filters</h3>
		    
		<p>
			A special category of filters ships with logback. The
    	<a href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html">
    	<code>EvaluatorFilter</code></a> objects use an 
    	<a href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html">
    	<code>EventEvaluator</code></a>
    	to decide wether to accept or deny the request. This allows unprecedented
    	flexibility in the way that you can affect the logging event's filtering.
    </p>
    
    <p>
			Creating a customized filter that makes use of <code>EventEvaluator</code> objects
			works the same way as seen previously, except that one must extend the 
			<code>EvaluatorFilter</code> class, instead of the <code>Filter</code>
			or <code>AbstractMatcherFilter</code> classes.
		</p>
    
    <a name="EventEvaluator" />
    <h3>Event Evaluators</h3>
    
    <p>
    	Events evaluators allow the user to enter java expressions, using 
    	components of a logging event, and to check each logging event
    	against the compiled expression.
    </p>
    
    <p>
    	Let's see a sample configuration.
    </p>
    
<em>Example 6.5: Basic event evaluator usage (logback-examples/src/main/java/chapter6/basicEventEvaluator.xml)</em>
<div class="source"><pre>&lt;configuration>

  &lt;appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator name="myEval">
        &lt;expression>message.contains("billing")&lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>DENY&lt;/OnMatch>
    &lt;/filter></b>
    &lt;layout class="ch.qos.logback.classic.PatternLayout">
      &lt;pattern>
        %-4relative [%thread] %-5level %logger - %msg%n
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>

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

		<p>
			The bold part in the previous configuration adds an <code>EvaluatorFilter</code>
			to a <code>ConsoleAppender</code>. An <code>EventEvaluator</code> is then given to
			the filter. The <em>expression</em> element contains a recognizable java expression.
			Notice that the <em>message</em> variable is defined implicitly. Logback provides
			access to the internal components of a logging event and lets the user build her
			expression at will.
		</p>
		
		<p>
			The implicit variables available to the <code>EventEvaluator</code> are described below:
		</p>
		
		<table>
			<tr>
				<th>Name</th>
				<th>Type</th>
				<th>Description</th>
			</tr>
			<tr>
				<td>event
				</td>
				<td><code>LoggingEvent</code></td>
				<td>The 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.
				</td>
			</tr>
			<tr>
				<td>message
				</td>
				<td><code>String</code></td>
				<td>The message created with the logging request.
				</td>
			</tr>
			<tr>
				<td>logger
				</td>
				<td><code>LoggerRemoteView</code></td>
				<td>This object can be treated like a usual logger. In case the logging event
				is serialized and sent to a remote machine, the usual logger object is
				dropped and replaced by a <code>LoggerRemoteView</code> object, which
				performs much better when serialized.
				</td>
			</tr>
			<tr>
				<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>
				<td>marker
				</td>
				<td><code>Marker</code></td>
				<td>The <code>Marker</code> object associated with the logging request.
				</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 access by using the
				following expression: <em>mdc.get("myKey")</em>.
				</td>
			</tr>
			<tr>
				<td>throwable
				</td>
				<td><code>Throwable</code></td>
				<td>The exception that was passed to the logger when it
				was requested.
				</td>
			</tr>
		</table>
		
		<p>
			The behaviour of the filter is also defined by its <span class="option">OnMatch</span>
			and <span class="option">OnMismatch</span> options. The configuration specifies thanks
			to these elements the replies that the <code>EvaluatorFilter</code> must give once its
			expression has been evaluated. The example above returns the value <code>FilterReply.ACCEPT</code> 
			when the message of the logging event contains the String <em>important</em>. 
			If <em>important</em> is not contained in the message, then the filter lets the next filter 
			evaluate this logging event.
		</p>
		
		<p>
			Let us see an example of <code>EvaluatorFilter</code>. The <code>FilterEvents</code>
			class issues ten logging requests, numbered from 0 to 9.
		</p>
		
		<p>
			First, let us run the <code>FilterEvents</code> class with a configuration that does
			not contain any filters. This can be done by issuing the following command:
		</p>
		
<div class="source"><pre>
java chapter6.FilterEvents src/main/java/chapter6/basicConfiguration.xml
</pre></div>
		
		<p>
			All requests will be displayed, as shown below:
		</p>

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

		<p>
		Suppose that we want to get rid of the billing information. We
		can use an <code>EvaluatorFilter</code> configured as follows:
		</p>

<div class="source"><pre>&lt;configuration>
  ...
  &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
    &lt;evaluator name="myEval">
      &lt;expression>message.contains("billing")&lt;/expression>
    &lt;/evaluator>
    &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
    &lt;OnMatch>DENY&lt;/OnMatch>
  &lt;/filter>
  ...
&lt;/configuration></pre></div>

		<p>
			This filter will deny any logging event whose message
			contains the String <em>billing</em>. If we run the <code>FilterEvents</code> 
			class again, we obtain the following output:
		</p>
		
<div class="source"><pre>0    [main] INFO  chapter6.FilterEvents - logging statement 0
0    [main] INFO  chapter6.FilterEvents - logging statement 1
0    [main] INFO  chapter6.FilterEvents - logging statement 2
0    [main] DEBUG chapter6.FilterEvents - logging statement 3
0    [main] INFO  chapter6.FilterEvents - logging statement 4
0    [main] INFO  chapter6.FilterEvents - logging statement 5
0    [main] INFO  chapter6.FilterEvents - logging statement 7
0    [main] INFO  chapter6.FilterEvents - logging statement 8
0    [main] INFO  chapter6.FilterEvents - logging statement 9</pre></div>
		
		
		<a name="TurboFilter" />
		<h3>TurboFilters</h3>
    
    <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 usual filters, they
    	use ternary logic to return their evaluation of the logging event.
    </p>
    
    <p>
    	Overall, they work much like the previously mentionned 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. 
   		Their decision is made based on some of the logging event's components. They require 
   		no logging event instanciation, nor any other treatement to provide their 
   		filtering functionnalities. They are much more performant than the usual
   		<code>Filter</code> objects.
   	</p>
   	
   	<h3>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 custumized filter object, developing a custom <code>TurboFilter</code> only
      ask that one implement the <code>decide()</code> method. In the next example, we
      create a slightly more complex filter:
    </p>
    
<em>Example 6.6: Basic custom <code>TurboFilter</code> (<a href="../xref/chapter6/SampleTurboFilter.html">logback-examples/src/main/java/chapter6/SampleTurboFilter.java</a>)</em>		
<div class="source"><pre>package chapter6;

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></div>

		<p>
			The <code>TurboFilter</code> above accepts events that contain a specific marker.
			If said marker is not found, then the filter passes the responsability 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 the newly created <code>TurboFilter</code>.
		</p>
		
<em>Example 6.7: Basic custom <code>TurboFilter</code> configuration (logback-examples/src/main/java/chapter6/sampleTurboFilterConfig.xml)</em>		
<div class="source"><pre>&lt;configuration>
  <b>&lt;turboFilter class="chapter6.SampleTurboFilter">
    &lt;Marker>sample&lt;/Marker>
  &lt;/turboFilter></b>

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

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

   	<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> 
   		check the presence of a given value in the MDC. 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 6.8: <code>MDCFilter</code> and <code>MarkerFilter</code> 
configuration (logback-examples/src/main/java/chapter6/turboFilters.xml)</em>
<div class="source"><pre>&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;layout class="ch.qos.logback.classic.PatternLayout">
      &lt;Pattern>%date [%thread] %-5level %logger - %msg%n&lt;/Pattern>
  &lt;/layout>
  &lt;/appender>

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

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

		<p>
			As we've seen previously, the <code>FilterEvents</code> class creates 10 logging requests, 
			each with its number from 0 to 9. All of the requests are of level <em>INFO</em>,
			just like the configured overall level, except for two requests. 
			The 3rd request, is a <em>DEBUG</em> level corresponding to the key <em>username</em>.
			This obviously satisfies the first <code>TurboFilter</code> declared in the previous 
			configuration file. The 6th request, a <em>ERROR</em> level request, 
			which is issued along with the <em>billing</em> marker, matches 
			the second <code>TurboFilter</code>.
		</p>
		
		<p>	
			Here is the output of the previous command:
		</p>

<div class="source"><pre>
2006-12-04 15:17:22,859 [main] INFO  chapter6.FilterEvents - logging statement 0
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 1
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 2
2006-12-04 15:17:22,875 [main] DEBUG chapter6.FilterEvents - logging statement 3
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 4
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 5
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 7
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 8
2006-12-04 15:17:22,875 [main] INFO  chapter6.FilterEvents - logging statement 9
</pre></div>
			
			
		<p>
			One can see that the 3rd request, who 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 a <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>
		
		  
    <h2>Logback Access</h2>
    
    <p>
    	Logback access benefits from most of the possibilities available
    	to the classic module. <code>Filter</code> objects are available and work
    	in the same way as their classic counterpart. They handle access' implementation
    	of logging events: <code>AccessEvent</code>. 
    	Thus, a customized filter
    	for logback access is follows strictly the same rules than one for the 
    	classic module, except for the event implemenation recieved as a parameter.
    	On the other hand,
    	<code>TurboFilter</code> objects are not available to the access module.
    </p>
    
    <h3>Filters</h3>
    
    <p>
    	<code>EvaluatorFilter</code> objects, with their expressions, are available to
    	the access module. However, the variables that one can use to build an expression
    	are different. Only the <code>AccessEvent</code> object can be used, by inserting the
    	<em>event</em> variable in the expression. Although less wide than its classic
    	counterpart, the access evaluation filter is just as powerfull. All the
    	request and response components are reachable from the <em>event</em> variable.
    </p>    
    
    <p>
    	Here is a sample configuration that will ensure that any 404 error will be displayed:
    </p>
   	
<em>Example 6.9: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator.xml)</em>
<div class="source"><pre>&lt;configuration>

  &lt;appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator name="myEval">
        &lt;expression>event.getStatusCode() == 404&lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>ACCEPT&lt;/OnMatch>
    &lt;/filter></b>
    &lt;layout class="ch.qos.logback.access.PatternLayout">
      &lt;pattern>
        %h %l %u %t %r %s %b
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>

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

		<p>
			We might imagine a slightly more complex use of filters to ensure the display of 404 errors, but
			to prevent polluting the output with endless accesses to CSS files. Here is what such a configuration
			would look like:
		</p>	

<em>Example 6.10: Access Evaluator (logback-examples/src/main/java/chapter6/accessEventEvaluator2.xml)</em>
<div class="source"><pre>&lt;configuration>

  &lt;appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <b>&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator name="Eval404">
        &lt;expression>event.getStatusCode() == 404&lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>ACCEPT&lt;/OnMatch>
    &lt;/filter>
    &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
      &lt;evaluator name="EvalCSS">
        &lt;expression>event.getRequestURI().contains("css")&lt;/expression>
      &lt;/evaluator>
      &lt;OnMismatch>NEUTRAL&lt;/OnMismatch>
      &lt;OnMatch>DENY&lt;/OnMatch>
    &lt;/filter></b>
    &lt;layout class="ch.qos.logback.access.PatternLayout">
      &lt;pattern>
        %h %l %u %t %r %s %b
      &lt;/pattern>
    &lt;/layout>
  &lt;/appender>

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