/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.logging; import org.slf4j.MDC; import org.slf4j.Marker; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.turbo.MatchingFilter; import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.util.OptionHelper; /** * This filter accepts events based on whether the log event is greater than * or equal to the level of the key parameter in the MDC and on whether the * originating logger is a child of the topLogger parameter. */ public class LoggerAndMDCFilter extends MatchingFilter { private String key; private String topLogger; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getTopLogger() { return topLogger; } public void setTopLogger(String topLogger) { this.topLogger = topLogger; } @Override public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) { if (!isStarted()) { return FilterReply.NEUTRAL; } String mdcLevel = MDC.get(key); if (mdcLevel == null) { return FilterReply.NEUTRAL; } /* Logger children do not actually have to start with the prefix of their * parent, but it's a de facto convention and logback doesn't surface any * other way to access child loggers. */ boolean isChild = (Logger.ROOT_LOGGER_NAME.equals(topLogger)) ? true : logger.getName().startsWith(topLogger); // If for some reason someone puts in a non-parseable value for the level in // the MDC, then we will default to INFO. if (isChild && level.isGreaterOrEqual(Level.toLevel(mdcLevel, Level.INFO))) { return onMatch; } return onMismatch; } @Override public void start() { int errors = 0; if (OptionHelper.isEmpty(topLogger)) { addWarn("The \"topLogger\" property is not set. Default to ROOT logger."); topLogger = Logger.ROOT_LOGGER_NAME; } if (OptionHelper.isEmpty(key)) { addError("The \"key\" property must be set"); errors++; } if (errors == 0) { super.start(); } } }