Typo, the new code would be:

private static final Filter THROWING_FILTER = 
ThresholdFilter.createFilter(Level.WARN, Result.THROW, Result.NEUTRAL);

Sorry about that.

Gary

On 2024/10/09 14:34:15 "Gary D. Gregory" wrote:
> Hi All:
> 
> As a user, I want to programmatically configure Log4j to throw an exception 
> when a specific component logs a WARN event.
> 
> Background: I am working with a large and complex stack that include 
> Hibernate in the mix. I just fixed a bug that, that as a side-effect, caused 
> Hibernate to log WARN events. As a check on possible regressions, I want to 
> make sure that a test class fails when Hibernate logs a WARN event. This 
> whole Maven module shares a log4j configuration file and, for now, I only 
> want this check on this one test class.
> 
> My current implementation uses a custom filter called ThrowingThresholdFilter 
> [see end of message], a copy of our ThresholdFilter that throws a subclass of 
> LoggingException called FilterLoggingException when the configured Level is 
> matched.
> 
> I also have happen to have other checks with other custom filters: 
> ThrowingLevelFilter and ThrowingStringMatchFilter. 
> 
> The only change in the configuration file is the use of the 
> “ignoreExceptions” attribute to a Console Appender.
> 
> The test contains:
> private static final Filter THROWING_FILTER = 
> ThrowingThresholdFilter.createFilter(Level.WARN, Result.NEUTRAL);
>     @SuppressWarnings("resource")
>     @BeforeAll
>     static void beforeAddFilter() {
>         
> LoggerContext.getContext(false).getLogger("org.hibernate").addFilter(THROWING_FILTER);
>     }
> 
> My proposal is to allow a user to _not_ define any custom filters by reusing 
> a new Result enum value called “Throw”. When a filter returns “Throw”, then 
> Log4j throws a new LoggingException subclass called FilterLoggingException.
> 
> Then my test can replace:
> 
> private static final Filter THROWING_FILTER = 
> ThrowingThresholdFilter.createFilter(Level.WARN, Result.NEUTRAL);
> 
> and drop all custom filters.
> 
> With:
> 
> private static final Filter THROWING_FILTER = 
> ThresholdFilter.createFilter(Level.WARN, Result.NEUTRAL);
> 
> WDYT?
> 
> Gary
> 
> package my.company;
> 
> import java.util.Objects;
> 
> import org.apache.logging.log4j.Level;
> import org.apache.logging.log4j.LoggingException;
> import org.apache.logging.log4j.Marker;
> import org.apache.logging.log4j.core.Filter;
> import org.apache.logging.log4j.core.LogEvent;
> import org.apache.logging.log4j.core.Logger;
> import org.apache.logging.log4j.core.config.Node;
> import org.apache.logging.log4j.core.config.plugins.Plugin;
> import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
> import org.apache.logging.log4j.core.config.plugins.PluginFactory;
> import org.apache.logging.log4j.core.filter.AbstractFilter;
> import org.apache.logging.log4j.message.Message;
> import org.apache.logging.log4j.util.PerformanceSensitive;
> 
> /**
>  * This filter returns the onMatch result if the level in the {@link 
> LogEvent} is the same or more specific
>  * than the configured level and the {@code onMismatch} value otherwise. For 
> example, if the ThresholdFilter
>  * is configured with Level {@code ERROR} and the LogEvent contains Level 
> {@code DEBUG} then the {@code onMismatch} value will
>  * be returned since {@code ERROR} events are more specific than {@code 
> DEBUG}.
>  * <p>
>  * The default Level is {@code ERROR}.
>  * </p>
>  *
>  * @see Level#isMoreSpecificThan(Level)
>  */
> @Plugin(name = "ThrowingThresholdFilter", category = Node.CATEGORY, 
> elementType = Filter.ELEMENT_TYPE, printObject = true)
> @PerformanceSensitive("allocation")
> public final class ThrowingThresholdFilter extends AbstractFilter {
> 
>     public static class FilterLoggingException extends LoggingException {
> 
>         private static final long serialVersionUID = 1L;
> 
>         public FilterLoggingException(String message) {
>             super(message);
>         }
>         
>     }
> 
>     private final Level level;
> 
>     private ThrowingThresholdFilter(final Level level, final Result 
> onMismatch) {
>         super(Result.NEUTRAL, onMismatch);
>         this.level = level;
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level testLevel, final 
> Marker marker, final String msg,
>                          final Object... params) {
>         return filter(testLevel);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level testLevel, final 
> Marker marker, final Object msg,
>                          final Throwable t) {
>         return filter(testLevel);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level testLevel, final 
> Marker marker, final Message msg,
>                          final Throwable t) {
>         return filter(testLevel);
>     }
> 
>     @Override
>     public Result filter(final LogEvent event) {
>         return filter(event.getLevel());
>     }
> 
>     private Result filter(final Level testLevel) {
>         if (testLevel.isMoreSpecificThan(this.level)) {
>             throw new FilterLoggingException(Objects.toString(testLevel));
>         }
>         return onMismatch;
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4, final Object p5) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4, final Object p5, final Object p6) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4, final Object p5, final Object p6,
>             final Object p7) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4, final Object p5, final Object p6,
>             final Object p7, final Object p8) {
>         return filter(level);
>     }
> 
>     @Override
>     public Result filter(final Logger logger, final Level level, final Marker 
> marker, final String msg,
>             final Object p0, final Object p1, final Object p2, final Object 
> p3,
>             final Object p4, final Object p5, final Object p6,
>             final Object p7, final Object p8, final Object p9) {
>         return filter(level);
>     }
> 
>     public Level getLevel() {
>         return level;
>     }
> 
>     @Override
>     public String toString() {
>         return level.toString();
>     }
> 
>     /**
>      * Creates a ThrowingThresholdFilter.
>      * @param level The log Level.
>      * @param mismatch The action to take on a mismatch.
>      * @return The created ThrowingThresholdFilter.
>      */
>     // TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
>     @PluginFactory
>     public static ThrowingThresholdFilter createFilter(
>             @PluginAttribute("level") final Level level,
>             @PluginAttribute("onMismatch") final Result mismatch) {
>         final Level actualLevel = level == null ? Level.ERROR : level;
>         final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
>         return new ThrowingThresholdFilter(actualLevel, onMismatch);
>     }
> 
> }
> 

Reply via email to