Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Gary Gregory
Hi Ralph,

Thank you for taking a peek.

I either did not explain myself clearly or in enough detail as I don't feel
you fully grasped what I proposed ;-)

"Secondly, I don’t like that the only criteria it is able to use to
determine whether to throw an exception is the log level."

It is _not_ only the log level, this would work with _any_ filter. I am
_not_ proposing to add any _new_ filters, that's what I want to avoid. I
propose the ability for any filter to be configured with "Result.THROW", a
new Result value, which log4j-core would translate to throwing an exception.

"Filters are for determining whether log events should be logged ... It is
more like an interceptor."

Yes, this proposal can make a filter look like an interceptor or an
"interruptor" in this case.

Let me present it slightly differently:

I feel it's reasonable for Log4j to provide the ability to cause a unit
test to fail if a log event meets a criterion. JUnit detects exceptions as
test failures. Log4j can propagate exceptions if configured to do so. The
last step missing is how to configure Log4j to throw an exception when a
log event criterion is met. Log4j provides filters which is the closest
feature for testing log events for criteria. So, it seems to me like
filters are the best place to implement this feature. I don't think we need
to invent something else.

HTH,
Gary


On Wed, Oct 9, 2024 at 11:11 AM Ralph Goers 
wrote:

> This just feels wrong. Filters are for determining whether log events
> should be logged. This Filter doesn’t have anything to do with that. It is
> more like an interceptor.
>
> Secondly, I don’t like that the only criteria it is able to use to
> determine whether to throw an exception is the log level.
>
> This just feels way too specific.
>
> Ralph
>
> > On Oct 9, 2024, at 7:36 AM, Gary D. Gregory  wrote:
> >
> > 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 

Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Gary Gregory
Hi Volkan,

Thank you for your review.

Later, I would like to have our whole build check all tests for Hibernate
warnings. Today, I'm taking a first step. The second step is to have
another Maven module's tests perform this check.

Recasting the solution as a JUnit 5 extension is a good idea, but not
strictly necessary IMO.

I am not fond of JUnit 5 having dropped a bomb by not making all JUnit 4
Rules run on 5, so I am reticent to buy into another extension framework
they could leave behind in version 6.

Gary


On Wed, Oct 9, 2024 at 11:08 AM Volkan Yazıcı 
wrote:

> Can you solve your problem by writing a JUnit extension (or
> `@BeforeAll`/`@AfterAll`) that registers your custom filter to the active
> logger context and removes it after the test? That is,
>
> @FailOnLog4jEvent(level = Level.WARN, namePrefix = "org.hibernate.")
> class SomeHibernateTest {
> // ... `@Test`-annotated methods ...
> }
>
>
> If this is only one test, you can even make it simpler:
>
> class SomeHibernateTest {
>
> @BeforeAll
> static void registerLog4jEventBan() {
> // ...
> }
>
> @AfterAll
> static void removeLog4jEventBan() {
> }
>
> // ... `@Test`-annotated methods ...
>
> }
>
>
> Maybe it is me, but I am not able to see the necessity to add a new
> `Result` type, in particular, given you stated *"I only want this check on
> this one test class"*.
>
> On Wed, Oct 9, 2024 at 4:34 PM 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}.
> >  * 
> >  * The default Level is {@code ERROR}.
> >  * 
> >  *
> >  * @see Level#isMoreSpecificThan(Level)
> >  */
> > @Plugin(name = "ThrowingThresholdFilter", category = Node.CATEGORY,
> > elementType = Filter.ELEMENT

Feature proposal for a new Filter result: Throw

2024-10-09 Thread Gary D. Gregory
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}.
 * 
 * The default Level is {@code ERROR}.
 * 
 *
 * @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

Re: Adding to Logging KEYS file

2024-10-09 Thread Piotr P. Karwasz
Hi Volkan,

On Wed, 9 Oct 2024 at 16:46, Volkan Yazıcı  wrote:
>
> Piotr, note that the build must be reproducible
>  for
> CI-based signing. If this is not the case for Log4cxx, could you also
> address that in your PR, please?

Sure, since Log4cxx only publishes sources, we just need to take care
of how we build the `tar.gz`. This is a well documented case (see
[1]).

Piotr

[1] https://reproducible-builds.org/docs/archives/


Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Volkan Yazıcı
Can you solve your problem by writing a JUnit extension (or
`@BeforeAll`/`@AfterAll`) that registers your custom filter to the active
logger context and removes it after the test? That is,

@FailOnLog4jEvent(level = Level.WARN, namePrefix = "org.hibernate.")
class SomeHibernateTest {
// ... `@Test`-annotated methods ...
}


If this is only one test, you can even make it simpler:

class SomeHibernateTest {

@BeforeAll
static void registerLog4jEventBan() {
// ...
}

@AfterAll
static void removeLog4jEventBan() {
}

// ... `@Test`-annotated methods ...

}


Maybe it is me, but I am not able to see the necessity to add a new
`Result` type, in particular, given you stated *"I only want this check on
this one test class"*.

On Wed, Oct 9, 2024 at 4:34 PM 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}.
>  * 
>  * The default Level is {@code ERROR}.
>  * 
>  *
>  * @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);
> }

Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Gary D. Gregory
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}.
>  * 
>  * The default Level is {@code ERROR}.
>  * 
>  *
>  * @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 

Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Gary Gregory
Hi Ralph,

I'll try again:

As mentioned, I don't want to have to write this custom filter in the first
place.

I want to write:

@SuppressWarnings("resource")
@BeforeAll
static void beforeAddFilter() {

LoggerContext.getContext(false).getLogger("org.hibernate").addFilter(ThresholdFilter.createFilter(Level.WARN,
*Result.THROW*, Result.NEUTRAL));
}

The value Result.THROW does not exist today. This proposal is to:

- Add Result.THROW
- There is no need to modify any Filter impls.
- When Core sees Result.THROW result from a Filter, it throws a
FilterLoggingException.

I hope that helps make my proposal clearer :-)
TY,
Gary



On Wed, Oct 9, 2024 at 2:46 PM Ralph Goers 
wrote:

> Yeah, you lost me. Your code has
>
>private Result filter(final Level testLevel) {
>if (testLevel.isMoreSpecificThan(this.level)) {
>throw new FilterLoggingException(Objects.toString(testLevel));
>}
>return onMismatch;
>}
>
> This isn’t returning a new type of Result, it is actually throwing an
> exception. If it was doing
> return Result.FilterException;
>
> Instead of the throw then I could understand what you are saying.
>
> Ralph
>
>
> > On Oct 9, 2024, at 9:55 AM, Gary Gregory  wrote:
> >
> > Hi Ralph,
> >
> > Thank you for taking a peek.
> >
> > I either did not explain myself clearly or in enough detail as I don't
> feel
> > you fully grasped what I proposed ;-)
> >
> > "Secondly, I don’t like that the only criteria it is able to use to
> > determine whether to throw an exception is the log level."
> >
> > It is _not_ only the log level, this would work with _any_ filter. I am
> > _not_ proposing to add any _new_ filters, that's what I want to avoid. I
> > propose the ability for any filter to be configured with "Result.THROW",
> a
> > new Result value, which log4j-core would translate to throwing an
> exception.
> >
> > "Filters are for determining whether log events should be logged ... It
> is
> > more like an interceptor."
> >
> > Yes, this proposal can make a filter look like an interceptor or an
> > "interruptor" in this case.
> >
> > Let me present it slightly differently:
> >
> > I feel it's reasonable for Log4j to provide the ability to cause a unit
> > test to fail if a log event meets a criterion. JUnit detects exceptions
> as
> > test failures. Log4j can propagate exceptions if configured to do so. The
> > last step missing is how to configure Log4j to throw an exception when a
> > log event criterion is met. Log4j provides filters which is the closest
> > feature for testing log events for criteria. So, it seems to me like
> > filters are the best place to implement this feature. I don't think we
> need
> > to invent something else.
> >
> > HTH,
> > Gary
> >
> >
> > On Wed, Oct 9, 2024 at 11:11 AM Ralph Goers 
> > wrote:
> >
> >> This just feels wrong. Filters are for determining whether log events
> >> should be logged. This Filter doesn’t have anything to do with that. It
> is
> >> more like an interceptor.
> >>
> >> Secondly, I don’t like that the only criteria it is able to use to
> >> determine whether to throw an exception is the log level.
> >>
> >> This just feels way too specific.
> >>
> >> Ralph
> >>
> >>> On Oct 9, 2024, at 7:36 AM, Gary D. Gregory 
> wrote:
> >>>
> >>> 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() {
> 
> >>
> LoggerCo

Re: Adding to Logging KEYS file

2024-10-09 Thread Volkan Yazıcı
Piotr, note that the build must be reproducible
 for
CI-based signing. If this is not the case for Log4cxx, could you also
address that in your PR, please?

On Wed, Oct 9, 2024 at 9:09 AM Piotr P. Karwasz 
wrote:

> On Wed, 9 Oct 2024 at 08:36, Stephen Webb  wrote:
> >
> > That would be much simpler. I was not aware that option was available. Is
> > there an example I can copy?
>
> We use `actions/setup-java` in our workflows[1], which can also
> install a GPG key on the Github runner (and clears it when the action
> ends/fails).
> You probably could use `crazy-max/ghaction-import-gpg` in Log4cxx to
> just install the GPG key.
>
> To speed up the process, I have opened INFRA-29194[3] to request the
> addition of our shared GPG key and `dev` Subversion credentials to the
> `logging-log4cxx`.
> Once this is done, I can submit a PR that enhances the release workflow.
>
> Piotr
>
> [1]
> https://github.com/apache/logging-parent/blob/428d9ede494f54358c6f004b07f7e40f8f33d3ab/.github/workflows/merge-dependabot-reusable.yaml#L70-L79
> [2] https://github.com/crazy-max/ghaction-import-gpg
> [3] https://issues.apache.org/jira/browse/INFRA-26194
>


Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Ralph Goers
This just feels wrong. Filters are for determining whether log events should be 
logged. This Filter doesn’t have anything to do with that. It is more like an 
interceptor. 

Secondly, I don’t like that the only criteria it is able to use to determine 
whether to throw an exception is the log level.  

This just feels way too specific.

Ralph

> On Oct 9, 2024, at 7:36 AM, Gary D. Gregory  wrote:
> 
> 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}.
>> * 
>> * The default Level is {@code ERROR}.
>> * 
>> *
>> * @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 Resu

Re: Feature proposal for a new Filter result: Throw

2024-10-09 Thread Ralph Goers
Yeah, you lost me. Your code has 

   private Result filter(final Level testLevel) {
   if (testLevel.isMoreSpecificThan(this.level)) {
   throw new FilterLoggingException(Objects.toString(testLevel));
   }
   return onMismatch;
   }

This isn’t returning a new type of Result, it is actually throwing an 
exception. If it was doing 
return Result.FilterException;

Instead of the throw then I could understand what you are saying.

Ralph


> On Oct 9, 2024, at 9:55 AM, Gary Gregory  wrote:
> 
> Hi Ralph,
> 
> Thank you for taking a peek.
> 
> I either did not explain myself clearly or in enough detail as I don't feel
> you fully grasped what I proposed ;-)
> 
> "Secondly, I don’t like that the only criteria it is able to use to
> determine whether to throw an exception is the log level."
> 
> It is _not_ only the log level, this would work with _any_ filter. I am
> _not_ proposing to add any _new_ filters, that's what I want to avoid. I
> propose the ability for any filter to be configured with "Result.THROW", a
> new Result value, which log4j-core would translate to throwing an exception.
> 
> "Filters are for determining whether log events should be logged ... It is
> more like an interceptor."
> 
> Yes, this proposal can make a filter look like an interceptor or an
> "interruptor" in this case.
> 
> Let me present it slightly differently:
> 
> I feel it's reasonable for Log4j to provide the ability to cause a unit
> test to fail if a log event meets a criterion. JUnit detects exceptions as
> test failures. Log4j can propagate exceptions if configured to do so. The
> last step missing is how to configure Log4j to throw an exception when a
> log event criterion is met. Log4j provides filters which is the closest
> feature for testing log events for criteria. So, it seems to me like
> filters are the best place to implement this feature. I don't think we need
> to invent something else.
> 
> HTH,
> Gary
> 
> 
> On Wed, Oct 9, 2024 at 11:11 AM Ralph Goers 
> wrote:
> 
>> This just feels wrong. Filters are for determining whether log events
>> should be logged. This Filter doesn’t have anything to do with that. It is
>> more like an interceptor.
>> 
>> Secondly, I don’t like that the only criteria it is able to use to
>> determine whether to throw an exception is the log level.
>> 
>> This just feels way too specific.
>> 
>> Ralph
>> 
>>> On Oct 9, 2024, at 7:36 AM, Gary D. Gregory  wrote:
>>> 
>>> 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.lo

Re: Adding to Logging KEYS file

2024-10-09 Thread Piotr P. Karwasz
Hi Stephen,

On Wed, 9 Oct 2024 at 09:09, Piotr P. Karwasz  wrote:
> [1] 
> https://github.com/apache/logging-parent/blob/428d9ede494f54358c6f004b07f7e40f8f33d3ab/.github/workflows/merge-dependabot-reusable.yaml#L70-L79

The `deploy-release-reusable` workflow[1] should be a better example
on how we generate all the distribution files.
Some parts are Maven-specific, but the major part of the shell scripts
are reusable.

Piotr

[1] 
https://github.com/apache/logging-parent/blob/428d9ede494f54358c6f004b07f7e40f8f33d3ab/.github/workflows/deploy-release-reusable.yaml#L208


Re: Adding to Logging KEYS file

2024-10-09 Thread Piotr P. Karwasz
On Wed, 9 Oct 2024 at 08:36, Stephen Webb  wrote:
>
> That would be much simpler. I was not aware that option was available. Is
> there an example I can copy?

We use `actions/setup-java` in our workflows[1], which can also
install a GPG key on the Github runner (and clears it when the action
ends/fails).
You probably could use `crazy-max/ghaction-import-gpg` in Log4cxx to
just install the GPG key.

To speed up the process, I have opened INFRA-29194[3] to request the
addition of our shared GPG key and `dev` Subversion credentials to the
`logging-log4cxx`.
Once this is done, I can submit a PR that enhances the release workflow.

Piotr

[1] 
https://github.com/apache/logging-parent/blob/428d9ede494f54358c6f004b07f7e40f8f33d3ab/.github/workflows/merge-dependabot-reusable.yaml#L70-L79
[2] https://github.com/crazy-max/ghaction-import-gpg
[3] https://issues.apache.org/jira/browse/INFRA-26194