[logback-dev] svn commit: r1712 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic main/java/ch/qos/logback/classic/turbo test/input/joran test/java/ch/qos/logback/classic/joran
Ralph Goers
Ralph.Goers at dslextreme.com
Fri Jul 18 16:21:30 CEST 2008
Thanks! I'd be interested in knowing what the concerns you have with the
semantics are.
noreply.ceki at qos.ch wrote:
> Author: ceki
> Date: Fri Jul 18 15:53:00 2008
> New Revision: 1712
>
> Added:
> logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java
> logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java
> logback/trunk/logback-classic/src/test/input/joran/turboDynamicThreshold.xml
> logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/XConfiguratorTestX.java
> Modified:
> logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Level.java
>
> Log:
> This patch is related to LBCLASSIC-53
>
> - This is a modified and hopefully improved version of Raph Goer's patch.
>
> MDCLevelFilter was renamed as DynamicThresholdFilter.
>
> In particular, the syntax for configuring a DynamicThresholdFilter
> is much shorter and convenient than previously. Here is an example:.
>
> <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
> <Key>userId</Key>
> <DefaultThreshold>ERROR</DefaultThreshold>
> <MDCValueLevelPair>
> <value>user1</value>
> <level>INFO</level>
> </MDCValueLevelPair>
> <MDCValueLevelPair>
> <value>user2</value>
> <level>TRACE</level>
> </MDCValueLevelPair>
>
> </turboFilter>
>
> See also turboDynamicThreshold.xml.
>
> However, I am not 100% satisfied with the semantics of
> DynamicThresholdFilter. Expect it to change according to
> feedback received on the mailing lists.
>
>
> Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Level.java
> ==============================================================================
> --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Level.java (original)
> +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Level.java Fri Jul 18 15:53:00 2008
> @@ -144,6 +144,17 @@
> return toLevel(sArg, Level.DEBUG);
> }
>
> +
> + /**
> + * This method exists in order to comply with Joran's valueOf convention.
> + * @param sArg
> + * @return
> + */
> + public static Level valueOf(String sArg) {
> + return toLevel(sArg, Level.DEBUG);
> + }
> +
> +
> /**
> * Convert an integer passed as argument to a Level. If the conversion fails,
> * then this method returns {@link #DEBUG}.
>
> Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java
> ==============================================================================
> --- (empty file)
> +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java Fri Jul 18 15:53:00 2008
> @@ -0,0 +1,129 @@
> +package ch.qos.logback.classic.turbo;
> +
> +import ch.qos.logback.classic.Logger;
> +import ch.qos.logback.classic.Level;
> +import ch.qos.logback.core.spi.FilterReply;
> +import org.slf4j.Marker;
> +import org.slf4j.MDC;
> +
> +import java.util.Map;
> +import java.util.HashMap;
> +
> +/**
> + * This filter will allow you to associate threshold levels to values found
> + * in the MDC. The threshold/value associations are looked up in MDC using
> + * a key. This key can be any value specified by the user.
> + *
> + * <p>TO BE DISCUSSED...
> + *
> + * <p>This provides very efficient course grained filtering based on things like a
> + * product name or a company name that would be associated with requests as they
> + * are being processed.
> + *
> + * The example configuration below illustrates how debug logging could be
> + * enabled for only individual users.
> + *
> + * <pre>
> + * <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
> + * <Key>userId</Key>
> + * <DefaultTheshold>ERROR</DefaultTheshold>
> + * <MDCValueLevelPair>
> + * <value>user1</value>
> + * <level>DEBUG</level>
> + * </MDCValueLevelPair>
> + * <MDCValueLevelPair>
> + * <value>user2</value>
> + * <level>TRACE</level>
> + * </MDCValueLevelPair>
> + * </turboFilter>
> + * </pre>
> + *
> + * @author Raplh Goers
> + * @author Ceki Gulcu
> + */
> +public class DynamicThresholdFilter extends TurboFilter {
> + private Map<String, Level> valueLevelMap = new HashMap<String, Level>();
> + private Level defaultThreshold = Level.ERROR;
> + private String key;
> +
> + /**
> + * The MDC key that will be filtered against
> + *
> + * @param key
> + * The name of the key.
> + */
> + public void setKey(String key) {
> + this.key = key;
> + }
> +
> + /**
> + *
> + * @return The name of the key being filtered
> + */
> + public String getKey() {
> + return this.key;
> + }
> +
> + public Level getDefaultThreshold() {
> + return defaultThreshold;
> + }
> +
> + public void setDefaultThreshold(Level defaultThreshold) {
> + this.defaultThreshold = defaultThreshold;
> + }
> +
> + /**
> + * Add a new MDCValuePair
> + */
> + public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair) {
> + if (valueLevelMap.containsKey(mdcValueLevelPair.getValue())) {
> + addError(mdcValueLevelPair.getValue() + " has been already set");
> + } else {
> + valueLevelMap.put(mdcValueLevelPair.getValue(), mdcValueLevelPair
> + .getLevel());
> + }
> + }
> +
> + /**
> + *
> + */
> + @Override
> + public void start() {
> + if (this.key == null) {
> + addError("No key name was specified");
> + }
> + super.start();
> + }
> +
> + /**
> + *
> + * @param marker
> + * @param logger
> + * @param level
> + * @param s
> + * @param objects
> + * @param throwable
> + * @return
> + */
> + @Override
> + public FilterReply decide(Marker marker, Logger logger, Level level,
> + String s, Object[] objects, Throwable throwable) {
> + String mdcValue = MDC.get(this.key);
> + if(!isStarted()) {
> + return FilterReply.NEUTRAL;
> + }
> +
> + Level levelAssociatedWithMDCValue = null;
> + if (mdcValue != null) {
> + levelAssociatedWithMDCValue = valueLevelMap.get(mdcValue);
> + }
> + if (levelAssociatedWithMDCValue == null) {
> + levelAssociatedWithMDCValue = defaultThreshold;
> + }
> + if (level.isGreaterOrEqual(levelAssociatedWithMDCValue)) {
> + return FilterReply.NEUTRAL;
> + } else {
> + return FilterReply.DENY;
> + }
> + }
> +}
>
> Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java
> ==============================================================================
> --- (empty file)
> +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/MDCValueLevelPair.java Fri Jul 18 15:53:00 2008
> @@ -0,0 +1,31 @@
> +package ch.qos.logback.classic.turbo;
> +
> +import ch.qos.logback.classic.Level;
> +
> +
> +/**
> + * Bean pairing an MDC value with a log level.
> + *
> + * @author Raplh Goers
> + * @author Ceki Gulcu
> + */
> +public class MDCValueLevelPair {
> + private String value;
> + private Level level;
> +
> + public String getValue() {
> + return value;
> + }
> +
> + public void setValue(String name) {
> + this.value = name;
> + }
> +
> + public Level getLevel() {
> + return level;
> + }
> +
> + public void setLevel(Level level) {
> + this.level = level;
> + }
> +}
>
> Added: logback/trunk/logback-classic/src/test/input/joran/turboDynamicThreshold.xml
> ==============================================================================
> --- (empty file)
> +++ logback/trunk/logback-classic/src/test/input/joran/turboDynamicThreshold.xml Fri Jul 18 15:53:00 2008
> @@ -0,0 +1,29 @@
> +<?xml version="1.0" encoding="UTF-8" ?>
> +<!DOCTYPE configuration>
> +
> +<configuration>
> +
> + <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
> + <Key>userId</Key>
> + <DefaultThreshold>ERROR</DefaultThreshold>
> + <MDCValueLevelPair>
> + <value>user1</value>
> + <level>INFO</level>
> + </MDCValueLevelPair>
> + <MDCValueLevelPair>
> + <value>user2</value>
> + <level>TRACE</level>
> + </MDCValueLevelPair>
> +
> + </turboFilter>
> +
> +
> + <appender name="LIST"
> + class="ch.qos.logback.core.read.ListAppender">
> + </appender>
> +
> + <root>
> + <level value="DEBUG" />
> + <appender-ref ref="LIST" />
> + </root>
> +</configuration>
>
> Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/XConfiguratorTestX.java
> ==============================================================================
> --- (empty file)
> +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/XConfiguratorTestX.java Fri Jul 18 15:53:00 2008
> @@ -0,0 +1,62 @@
> +/**
> + * LOGBack: the generic, reliable, fast and flexible logging framework.
> + *
> + * Copyright (C) 1999-2006, QOS.ch
> + *
> + * This library is free software, you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public License as
> + * published by the Free Software Foundation.
> + */
> +package ch.qos.logback.classic.joran;
> +
> +import junit.framework.TestCase;
> +
> +import org.slf4j.MDC;
> +
> +import ch.qos.logback.classic.Logger;
> +import ch.qos.logback.classic.LoggerContext;
> +import ch.qos.logback.classic.spi.LoggingEvent;
> +import ch.qos.logback.classic.util.TeztConstants;
> +import ch.qos.logback.core.joran.spi.JoranException;
> +import ch.qos.logback.core.read.ListAppender;
> +import ch.qos.logback.core.util.StatusPrinter;
> +
> +public class XConfiguratorTestX extends TestCase {
> +
> + public XConfiguratorTestX(String name) {
> + super(name);
> + }
> +
> + public void testSimpleList() throws JoranException {
> + JoranConfigurator jc = new JoranConfigurator();
> + LoggerContext loggerContext = new LoggerContext();
> + jc.setContext(loggerContext);
> + jc.doConfigure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turboDynamicThreshold.xml");
> +
> + StatusPrinter.print(loggerContext.getStatusManager());
> +
> + Logger logger = loggerContext.getLogger(this.getClass().getName());
> + Logger root = loggerContext.getLogger(LoggerContext.ROOT_NAME);
> + ListAppender listAppender = (ListAppender) root.getAppender("LIST");
> + assertEquals(0, listAppender.list.size());
> +
> + // this one should be denied
> + MDC.put("userId", "user1");
> + logger.debug("hello user1");
> + // this one should log
> + MDC.put("userId", "user2");
> + logger.debug("hello user2");
> +
> + assertEquals(1, listAppender.list.size());
> + LoggingEvent le = (LoggingEvent) listAppender.list.get(0);
> + assertEquals("hello user2", le.getMessage());
> + }
> +
> +
> +// public static Test suite() {
> +// TestSuite suite = new TestSuite();
> +// suite.addTestSuite(XConfiguratorTest.class);
> +// //suite.addTest(new JoranConfiguratorTest("testEvaluatorFilter"));
> +// return suite;
> +// }
> +}
> _______________________________________________
> logback-dev mailing list
> logback-dev at qos.ch
> http://qos.ch/mailman/listinfo/logback-dev
>
More information about the logback-dev
mailing list