
The branch, master has been updated via ef5a12d9162edc1cd94e5b71f4a58c3784e236be (commit) from 93098a6ca9cfb47dc87cd10e035d5f678723b1f5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=ef5a12d9162edc1cd94e5b71f... http://github.com/ceki/logback/commit/ef5a12d9162edc1cd94e5b71f4a58c3784e236... commit ef5a12d9162edc1cd94e5b71f4a58c3784e236be Author: Ceki Gulcu <ceki@qos.ch> Date: Mon Nov 9 22:43:04 2009 +0100 working on the filters.html chapter diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index 26beab2..a69ccb9 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -214,9 +214,7 @@ * </Import-Package> - <Bundle-RequiredExecutionEnvironment> - J2SE-1.5 - </Bundle-RequiredExecutionEnvironment> + <Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment> </instructions> </configuration> </plugin> diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java index c40b6db..093cc8e 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java @@ -52,7 +52,6 @@ public class JaninoEventEvaluator extends JaninoEventEvaluatorBase<ILoggingEvent DEFAULT_PARAM_NAME_LIST.add("marker"); DEFAULT_PARAM_NAME_LIST.add("mdc"); DEFAULT_PARAM_NAME_LIST.add("throwable"); - DEFAULT_PARAM_TYPE_LIST.add(int.class); DEFAULT_PARAM_TYPE_LIST.add(int.class); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java index 27db72b..336f13c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/filter/LevelFilter.java @@ -19,40 +19,36 @@ import ch.qos.logback.core.filter.AbstractMatcherFilter; import ch.qos.logback.core.spi.FilterReply; /** - * A class that filters events depending on their level. - * - * One can specify a level and the behaviour of the filter when - * said level is encountered in a logging event. - * - * For more information about filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html + * A class that filters events by the level equality. + + * <p> + * For more information about this filter, please refer to the online manual at + * http://logback.qos.ch/manual/filters.html#levelFilter * * @author Ceki Gülcü * @author Sébastien Pennec */ -public class LevelFilter extends AbstractMatcherFilter { +public class LevelFilter extends AbstractMatcherFilter<ILoggingEvent> { Level level; - + @Override - public FilterReply decide(Object eventObject) { + public FilterReply decide(ILoggingEvent event) { if (!isStarted()) { return FilterReply.NEUTRAL; } - - ILoggingEvent event = (ILoggingEvent)eventObject; - + if (event.getLevel().equals(level)) { return onMatch; } else { return onMismatch; } } - + public void setLevel(String level) { this.level = Level.toLevel(level); } - + public void start() { if (this.level != null) { super.start(); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java index 7ba9b8f..9bf1c2f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/filter/ThresholdFilter.java @@ -19,31 +19,29 @@ import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; /** - * A class that filters events depending on their level. + * Filters events below the threshold level. * - * All events with a level under or above the specified - * level will be denied, while all events with a level + * Events with a level below the specified + * level will be denied, while events with a level * equal or above the specified level will trigger a * FilterReply.NEUTRAL result, to allow the rest of the * filter chain process the event. * * For more information about filters, please refer to the online manual at - * http://logback.qos.ch/manual/filters.html + * http://logback.qos.ch/manual/filters.html#thresholdFilter * * @author Sébastien Pennec */ -public class ThresholdFilter extends Filter { +public class ThresholdFilter extends Filter<ILoggingEvent> { Level level; @Override - public FilterReply decide(Object eventObject) { + public FilterReply decide(ILoggingEvent event) { if (!isStarted()) { return FilterReply.NEUTRAL; } - ILoggingEvent event = (ILoggingEvent)eventObject; - if (event.getLevel().isGreaterOrEqual(level)) { return FilterReply.NEUTRAL; } else { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java index 7d750f2..13e8ecf 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/JaninoEventEvaluatorTest.java @@ -113,6 +113,23 @@ public class JaninoEventEvaluatorTest { } @Test + public void testWithNullMarker_LBCORE_118() throws Exception { + JaninoEventEvaluator jee = new JaninoEventEvaluator(); + jee.setExpression("marker.contains(\"BLUE\")"); + jee.setContext(loggerContext); + jee.addMatcher(matcherX); + jee.start(); + + ILoggingEvent event = makeLoggingEvent(null); + try { + jee.evaluate(event); + fail("We should not reach this point"); + } catch (EvaluationException ee) { + + } + } + + @Test public void testWithNullMarker() throws Exception { JaninoEventEvaluator jee = new JaninoEventEvaluator(); jee.setExpression("marker.contains(\"BLUE\")"); @@ -129,6 +146,8 @@ public class JaninoEventEvaluatorTest { } } + + @Test public void testComplex() throws Exception { diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java index 5c10720..28b14ac 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/EventEvaluator.java @@ -17,36 +17,35 @@ import ch.qos.logback.core.spi.ContextAware; import ch.qos.logback.core.spi.LifeCycle; /** - * An EventEvaluator has the responsibility to evaluate whether a given an event - * matches a given criteria. + * Evaluates whether a given an event matches user-specified criteria. * - * <p>Implementations are free to evaluate the event as they see fit. In + * <p> + * Implementations are free to evaluate the event as they see fit. In * particular, the evaluation results <em>may</em> depend on previous events. - * + * * @author Ceki Gülcü */ public interface EventEvaluator<E> extends ContextAware, LifeCycle { - /** - * Evaluates whether the event passed as parameter matches this evaluator's - * matching criteria. + * Evaluates whether the event passed as parameter matches some user-specified + * criteria. * - * <p>The <code>Evaluator</code> instance is free to evaluate the event as - * it pleases. In particular, the evaluation results <em>may</em> depend on - * previous events. + * <p> + * The <code>Evaluator</code> is free to evaluate the event as it pleases. In + * particular, the evaluation results <em>may</em> depend on previous events. * - * @param event The event to evaluate - * @return true if there is a match, false otherwise. - * @throws NullPointerException can be thrown in presence of null values - * @throws EvaluationException Thrown during evaluation + * @param event + * The event to evaluate + * @return true if there is a match, false otherwise. + * @throws NullPointerException + * can be thrown in presence of null values + * @throws EvaluationException + * may be thrown during faulty evaluation */ boolean evaluate(E event) throws NullPointerException, EvaluationException; - - - - + /** * Evaluators are named entities. * @@ -54,7 +53,6 @@ public interface EventEvaluator<E> extends ContextAware, LifeCycle { */ public String getName(); - /** * Evaluators are named entities. */ diff --git a/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java b/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java index 5e03a16..fce2ad3 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java @@ -18,7 +18,14 @@ import java.util.List; import org.codehaus.janino.ExpressionEvaluator; -abstract public class JaninoEventEvaluatorBase<E> extends EventEvaluatorBase<E>{ +/** + * Abstract class which sets the groundwork for janino based evaluations. + * + * @author Ceki Gülcü + * + * @param <E> + */ +abstract public class JaninoEventEvaluatorBase<E> extends EventEvaluatorBase<E> { static Class EXPRESSION_TYPE = boolean.class; static Class[] THROWN_EXCEPTIONS = new Class[1]; @@ -27,7 +34,6 @@ abstract public class JaninoEventEvaluatorBase<E> extends EventEvaluatorBase<E>{ static { THROWN_EXCEPTIONS[0] = EvaluationException.class; } - private String expression; @@ -60,7 +66,8 @@ abstract public class JaninoEventEvaluatorBase<E> extends EventEvaluatorBase<E>{ public boolean evaluate(E event) throws EvaluationException { if (!isStarted()) { - throw new IllegalStateException("Evaluator [" + name + "] was called in stopped state"); + throw new IllegalStateException("Evaluator [" + name + + "] was called in stopped state"); } try { Boolean result = (Boolean) ee.evaluate(getParameterValues(event)); diff --git a/logback-examples/src/main/java/chapter6/SampleFilter.java b/logback-examples/src/main/java/chapter6/SampleFilter.java index a4b60c6..bf7ee9d 100644 --- a/logback-examples/src/main/java/chapter6/SampleFilter.java +++ b/logback-examples/src/main/java/chapter6/SampleFilter.java @@ -17,11 +17,10 @@ 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 { +public class SampleFilter extends Filter<ILoggingEvent> { @Override - public FilterReply decide(Object eventObject) { - ILoggingEvent event = (ILoggingEvent)eventObject; + public FilterReply decide(ILoggingEvent event) { if (event.getMessage() != null && event.getMessage().contains("sample")) { return FilterReply.ACCEPT; } else { diff --git a/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml b/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml index 4e6738e..bcdb27f 100644 --- a/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml +++ b/logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml @@ -2,14 +2,19 @@ <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + + <!-- deny all events with a level below INFO, that is TRACE and DEBUG --> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> - <layout class="ch.qos.logback.classic.PatternLayout"> + <layout> <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern> </layout> </appender> + + <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> + </configuration> \ No newline at end of file diff --git a/logback-site/src/site/pages/manual/filters.html b/logback-site/src/site/pages/manual/filters.html index 3d0ebb9..957ba15 100644 --- a/logback-site/src/site/pages/manual/filters.html +++ b/logback-site/src/site/pages/manual/filters.html @@ -60,69 +60,62 @@ <h3><a name="filter" href="#filter">Regular filters</a></h3> - <p>Any regular logback-classic filter extends the <a + <p>Regular logback-classic filters extend the <a href="../xref/ch/qos/logback/core/filter/Filter.html"><code>Filter</code></a> - abstract class which consists of the <code>decide(Object - event)</code> method taking an <code>ILoggingEvent</code> instance - as parameter. Logback-classic will ask any given filter to decide - what to do with newly created events. + abstract class which essentially consists of a single method, + <code>decide()</code> method taking an <code>ILoggingEvent</code> + instance as parameter. </p> <p>Filters are organized as an ordered list and 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 - <a + 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>FilterReply.DENY</code>, - <code>FilterReply.NEUTRAL</code> or - <code>FilterReply.ACCEPT</code>. If the value returned by - <code>decide</code>() is <code>FilterReply.DENY</code>, then the + 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>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. + 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 <code>Filter</code> objects can 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>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>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 concentrate only on the behaviour of your - filter. + <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 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 whose message does not - contain this String. + <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 6.1: Basic custom filter (<a href="../xref/chapter6/SampleFilter.html">logback-examples/src/main/java/chapter6/SampleFilter.java</a>)</em> <pre class="prettyprint source">package chapter6; -import ch.qos.logback.classic.spi.LoggingEvent; +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 { +public class SampleFilter extends Filter>ILoggingEvent> { @Override - public FilterReply decide(Object eventObject) { - LoggingEvent event = (LoggingEvent)eventObject; - + public FilterReply decide(ILoggingEvent event) { if (event.getMessage().contains("sample")) { return FilterReply.ACCEPT; } else { @@ -131,16 +124,14 @@ public class SampleFilter extends Filter { } }</pre> - <p> - What is shown above might be the simplest filter. Like any filter, it - can be attached to any appender using the <Filter> element, as - shown below: + <p>The configutation files shown next attaches a + <code>SampleFilter</code> to a <code>ConsoleAppener</code>. </p> <em>Example 6.2: SampleFilter configuration (logback-examples/src/main/java/chapter6/SampleFilterConfig.xml)</em> <pre class="prettyprint source"><configuration> - <appender name="STDOUT" - class="ch.qos.logback.core.ConsoleAppender"> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <b><Filter class="chapter6.SampleFilter" /></b> <layout class="ch.qos.logback.classic.PatternLayout"> @@ -155,34 +146,41 @@ public class SampleFilter extends Filter { </root> </configuration></pre> - <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>With the help of Joran, logback's configuration framework, + specifiying properties or sub-componenets 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 <code><filter></code> + 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 properties: <em>OnMatch</em> and - <em>OnMismatch</em>, both of which can be configured like any - other property. - </p> + <p>Often times, 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, say 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 specifiying the appropriate response on match + and on mistmatch, 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>Logback Filters</h3> + <h3><a name="levelFilter" href="#levelFilter">LevelFilter</a></h3> - <p>At 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. If the event's level is equal to the - configured level, the filter accepts or 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><a href="../xref/ch/qos/logback/classic/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 6.3: Sample LevelFilter configuration (logback-examples/src/main/java/chapter6/levelFilterConfig.xml)</em> @@ -194,7 +192,7 @@ public class SampleFilter extends Filter { <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter></b> - <layout class="ch.qos.logback.classic.PatternLayout"> + <layout> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> @@ -205,23 +203,27 @@ public class SampleFilter extends Filter { </root> </configuration></pre> - <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. + <h3><a name="thresholdFilter" href="#thresholdFilter">ThresholdFilter</a></h3> + + <p>The <a + href="../xref/ch/qos/logback/classic/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 6.4: Sample ThresholdFilter configuration (logback-examples/src/main/java/chapter6/thresholdFilterConfig.xml)</em> <pre class="prettyprint source"><configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <!-- deny all events with a level below INFO, that is TRACE and DEBUG --> <b><filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter></b> - <layout class="ch.qos.logback.classic.PatternLayout"> + <layout> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> @@ -233,8 +235,27 @@ public class SampleFilter extends Filter { </configuration></pre> - <h3>Evaluator Filters taking Java Expressions</h3> + <h3><a name="evalutatorFilter" + href="#evalutatorFilter">EvaluatorFilter</a></h3> + <p><a + href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html"><code>EvaluatorFilter</code></a> + is a generic filter encapsulating an <a + href="../xref/ch/qos/logback/core/boolex/EventEvaluator.html"> + <code>EventEvaluator</code></a> which evaluates whether a given + criteria is met. On match and respectively on mismatch, the + <code>EvaluatorFilter</code> will return the value set for the + <span class="option">OnMatch</span> and respectively for the <span + class="option">OnMismatch</span> properties. + </p> + + <p>The <code>EventEvaluator</code> class is abstract and you can + implement your own even evaluation logic. Logback-classic ships + with a concrete evaluator implementation called <a + href="../xref/ch/qos/logback/classic/boolex/JaninoEvaluator.html">JaninoEvaluator</a> + which take artibtrary java expressions as the evaluation criteria, + enabling unprecedented flexibility for filtering logging events. + </p> <p>A special category of filters is implemented by the <a href="../xref/ch/qos/logback/core/filter/EvaluatorFilter.html"> ----------------------------------------------------------------------- Summary of changes: logback-classic/pom.xml | 4 +- .../classic/boolex/JaninoEventEvaluator.java | 1 - .../ch/qos/logback/classic/filter/LevelFilter.java | 26 ++-- .../logback/classic/filter/ThresholdFilter.java | 14 +- .../classic/boolex/JaninoEventEvaluatorTest.java | 19 ++ .../ch/qos/logback/core/boolex/EventEvaluator.java | 36 ++-- .../core/boolex/JaninoEventEvaluatorBase.java | 13 +- .../src/main/java/chapter6/SampleFilter.java | 5 +- .../main/java/chapter6/thresholdFilterConfig.xml | 7 +- logback-site/src/site/pages/manual/filters.html | 177 +++++++++++--------- 10 files changed, 171 insertions(+), 131 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework.