diff --git a/application/build.gradle b/application/build.gradle index 7a9c4f23c3..2220065fb5 100644 --- a/application/build.gradle +++ b/application/build.gradle @@ -47,8 +47,7 @@ dependencies { implementation 'net.dv8tion:JDA:4.4.0_351' - compileOnly 'org.apache.logging.log4j:log4j-api:2.16.0' - runtimeOnly 'org.apache.logging.log4j:log4j-core:2.16.0' + implementation 'org.apache.logging.log4j:log4j-core:2.16.0' runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.16.0' implementation 'org.jooq:jooq:3.15.3' diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java b/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java new file mode 100644 index 0000000000..0789f7738c --- /dev/null +++ b/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java @@ -0,0 +1,68 @@ +package org.togetherjava.tjbot.logging; + +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LogEvent; +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.jetbrains.annotations.NotNull; + + +/** + * A custom Filter for Log4j2, which only lets an event pass through if a Logging Flag is set in the + * environment. Intended to be used for local development for devs do not want to also run the + * logviewer project. No errors in console or Log should appear, if the Flag is not set and the + * logviewer is not running. + */ +@Plugin(name = "FlaggedFilter", category = Core.CATEGORY_NAME, elementType = Filter.ELEMENT_TYPE) +public class FlaggedFilter extends AbstractFilter { + + /** + * The environment Variable that needs to bet set in order for this Filter to let events through + */ + public static final String LOGGING_FLAG = "TJ_APPENDER"; + + /** + * Create a FlaggedFilter. + * + * @param onMatch The action to take on a match. + * @param onMismatch The action to take on a mismatch. + */ + public FlaggedFilter(@NotNull Result onMatch, @NotNull Result onMismatch) { + super(onMatch, onMismatch); + } + + /** + * The actual filtering occurs here. If the Flag {@link #LOGGING_FLAG} is not set returns + * {@link Result#DENY} so nothing goes through. If the Flag is set it returns + * {@link Result#NEUTRAL} so other configured Filter still work. + * + * @param event The Event to log. + * @return {@link Result#DENY} if the Flag is not set, else {@link Result#NEUTRAL} + */ + @Override + public Result filter(LogEvent event) { + return isLoggingEnabled() ? Result.NEUTRAL : Result.DENY; + } + + boolean isLoggingEnabled() { + return System.getenv().containsKey(LOGGING_FLAG); + } + + /** + * Required by the Log4j2 - Plugin framework in order to create an instance of this Filter. + * + * @param onMatch The action to take on a match. + * @param onMismatch The action to take on a mismatch. + * @return The created FlaggedFilter. + */ + @PluginFactory + public static FlaggedFilter createFilter( + @NotNull @PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch, + @NotNull + @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) { + return new FlaggedFilter(onMatch, onMismatch); + } +} diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/package-info.java b/application/src/main/java/org/togetherjava/tjbot/logging/package-info.java new file mode 100644 index 0000000000..ecac734f57 --- /dev/null +++ b/application/src/main/java/org/togetherjava/tjbot/logging/package-info.java @@ -0,0 +1,4 @@ +/** + * This package is for custom logging plugins of the bot. + */ +package org.togetherjava.tjbot.logging; diff --git a/application/src/main/resources/log4j2.xml b/application/src/main/resources/log4j2.xml index d82af3842e..43540687ee 100644 --- a/application/src/main/resources/log4j2.xml +++ b/application/src/main/resources/log4j2.xml @@ -1,5 +1,5 @@ - + @@ -17,6 +17,7 @@ + diff --git a/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java b/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java new file mode 100644 index 0000000000..52251b6bae --- /dev/null +++ b/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java @@ -0,0 +1,36 @@ +package org.togetherjava.tjbot.logging; + +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +final class FilterTest { + + private FlaggedFilter filter; + private LogEvent event; + + @BeforeEach + void setUp() { + this.filter = FlaggedFilter.createFilter(Filter.Result.NEUTRAL, Filter.Result.DENY); + this.event = Log4jLogEvent.newBuilder().build(); + } + + @Test + void shouldPassFilter() { + FlaggedFilter spy = Mockito.spy(this.filter); + Mockito.when(spy.isLoggingEnabled()).thenReturn(true); + Assertions.assertEquals(Filter.Result.NEUTRAL, spy.filter(this.event)); + } + + + @Test + void shouldNotPassFilter() { + FlaggedFilter spy = Mockito.spy(this.filter); + Mockito.when(spy.isLoggingEnabled()).thenReturn(false); + Assertions.assertEquals(Filter.Result.DENY, spy.filter(this.event)); + } +}