diff --git a/core/deployment/src/main/java/io/quarkus/deployment/logging/LoggingResourceProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/logging/LoggingResourceProcessor.java index e1fa11ba794b97..acaf966faf7b03 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/logging/LoggingResourceProcessor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/logging/LoggingResourceProcessor.java @@ -1,6 +1,5 @@ package io.quarkus.deployment.logging; -import java.lang.reflect.Modifier; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; @@ -38,7 +37,6 @@ import org.jboss.jandex.CompositeIndex; import org.jboss.jandex.DotName; import org.jboss.jandex.IndexView; -import org.jboss.jandex.MethodInfo; import org.jboss.logging.Logger; import org.jboss.logmanager.EmbeddedConfigurator; import org.jboss.logmanager.LogManager; @@ -112,6 +110,7 @@ import io.quarkus.runtime.logging.LogBuildTimeConfig; import io.quarkus.runtime.logging.LogCleanupFilterElement; import io.quarkus.runtime.logging.LogConfig; +import io.quarkus.runtime.logging.LogFilterFactory; import io.quarkus.runtime.logging.LogMetricsHandlerRecorder; import io.quarkus.runtime.logging.LoggingSetupRecorder; @@ -126,7 +125,7 @@ public final class LoggingResourceProcessor { "isMinLevelEnabled", boolean.class, int.class, String.class); - private static final DotName LOGGING_FILTER = DotName.createSimple(LoggingFilter.class.getName()); + public static final DotName LOGGING_FILTER = DotName.createSimple(LoggingFilter.class.getName()); private static final DotName FILTER = DotName.createSimple(Filter.class.getName()); private static final String ILLEGAL_LOGGING_FILTER_USE_MESSAGE = "'@" + LoggingFilter.class.getName() + "' can only be used on classes that implement '" @@ -235,7 +234,8 @@ LoggingSetupBuildItem setupLoggingRuntimeInit(RecorderContext context, LoggingSe BuildProducer shutdownListenerBuildItemBuildProducer, LaunchModeBuildItem launchModeBuildItem, List logCleanupFilters, - BuildProducer reflectiveClassBuildItemBuildProducer) { + BuildProducer reflectiveClassBuildItemBuildProducer, + BuildProducer serviceProviderBuildItemBuildProducer) { if (!launchModeBuildItem.isAuxiliaryApplication() || launchModeBuildItem.getAuxiliaryDevModeType().orElse(null) == DevModeType.TEST_ONLY) { final List>> handlers = handlerBuildItems.stream() @@ -272,6 +272,8 @@ LoggingSetupBuildItem setupLoggingRuntimeInit(RecorderContext context, LoggingSe reflectiveClassBuildItemBuildProducer.produce(new ReflectiveClassBuildItem(true, false, false, discoveredLogComponents.getNameToFilterClass().values().toArray( EMPTY_STRING_ARRAY))); + serviceProviderBuildItemBuildProducer + .produce(ServiceProviderBuildItem.allProvidersFromClassPath(LogFilterFactory.class.getName())); } shutdownListenerBuildItemBuildProducer.produce(new ShutdownListenerBuildItem( @@ -317,10 +319,6 @@ private DiscoveredLogComponents discoverLogComponents(IndexView index) { throw new IllegalStateException("Unimplemented mode of use of '" + LoggingFilter.class.getName() + "'"); } ClassInfo classInfo = target.asClass(); - if (!Modifier.isFinal(classInfo.flags())) { - throw new RuntimeException( - ILLEGAL_LOGGING_FILTER_USE_MESSAGE + " Offending class is '" + classInfo.name() + "'"); - } boolean isFilterImpl = false; ClassInfo currentClassInfo = classInfo; while ((currentClassInfo != null) && (!JandexUtil.DOTNAME_OBJECT.equals(currentClassInfo.name()))) { @@ -343,11 +341,6 @@ private DiscoveredLogComponents discoverLogComponents(IndexView index) { ILLEGAL_LOGGING_FILTER_USE_MESSAGE + " Offending class is '" + classInfo.name() + "'"); } - MethodInfo ctor = classInfo.method(""); - if ((ctor == null) || (ctor.typeParameters().size() > 0)) { - throw new RuntimeException("Classes annotated with '" + LoggingFilter.class.getName() - + "' must have a no-args constructor. Offending class is '" + classInfo.name() + "'"); - } String filterName = instance.value("name").asString(); if (filtersMap.containsKey(filterName)) { throw new RuntimeException("Filter '" + filterName + "' was defined multiple times."); diff --git a/core/runtime/src/main/java/io/quarkus/runtime/logging/LogFilterFactory.java b/core/runtime/src/main/java/io/quarkus/runtime/logging/LogFilterFactory.java new file mode 100644 index 00000000000000..bd5ecbf40467f5 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/logging/LogFilterFactory.java @@ -0,0 +1,48 @@ +package io.quarkus.runtime.logging; + +import java.util.ServiceLoader; +import java.util.logging.Filter; + +public interface LogFilterFactory { + + int MIN_PRIORITY = Integer.MAX_VALUE; + int DEFAULT_PRIORITY = 0; + + Filter create(String className) throws Exception; + + default int priority() { + return DEFAULT_PRIORITY; + } + + static LogFilterFactory factory() { + LogFilterFactory result = null; + ServiceLoader load = ServiceLoader.load(LogFilterFactory.class); + for (LogFilterFactory next : load) { + if (result == null) { + result = next; + } else { + if (next.priority() < result.priority()) { + result = next; + } + } + } + if (result == null) { + result = new ReflectionLogFilterFactory(); + } + return result; + } + + class ReflectionLogFilterFactory implements LogFilterFactory { + + @Override + public Filter create(String className) throws Exception { + return (Filter) Class.forName(className, true, Thread.currentThread().getContextClassLoader()) + .getConstructor().newInstance(); + } + + @Override + public int priority() { + return LogFilterFactory.MIN_PRIORITY; + } + } +} diff --git a/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java index f10f9c3dab7313..cc2c7a7963d16f 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java @@ -254,13 +254,12 @@ private static Map createNamedFilters(DiscoveredLogComponents di } Map nameToFilter = new HashMap<>(); + LogFilterFactory logFilterFactory = LogFilterFactory.factory(); discoveredLogComponents.getNameToFilterClass().forEach(new BiConsumer<>() { @Override public void accept(String name, String className) { try { - nameToFilter.put(name, - (Filter) Class.forName(className, true, Thread.currentThread().getContextClassLoader()) - .getConstructor().newInstance()); + nameToFilter.put(name, logFilterFactory.create(className)); } catch (Exception e) { throw new RuntimeException("Unable to create instance of Logging Filter '" + className + "'"); } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/LoggingBeanSupportProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/LoggingBeanSupportProcessor.java new file mode 100644 index 00000000000000..71bdfdb1b81604 --- /dev/null +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/LoggingBeanSupportProcessor.java @@ -0,0 +1,16 @@ +package io.quarkus.arc.deployment; + +import io.quarkus.arc.processor.BuiltinScope; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.logging.LoggingResourceProcessor; + +public class LoggingBeanSupportProcessor { + + @BuildStep + public void discoveredComponents(BuildProducer beanDefiningAnnotationProducer) { + beanDefiningAnnotationProducer.produce(new BeanDefiningAnnotationBuildItem( + LoggingResourceProcessor.LOGGING_FILTER, BuiltinScope.SINGLETON.getName(), false)); + } + +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/logging/ArcLogFilterFactory.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/logging/ArcLogFilterFactory.java new file mode 100644 index 00000000000000..4d60953885061b --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/logging/ArcLogFilterFactory.java @@ -0,0 +1,20 @@ +package io.quarkus.arc.runtime.logging; + +import java.util.logging.Filter; + +import io.quarkus.arc.Arc; +import io.quarkus.runtime.logging.LogFilterFactory; + +public class ArcLogFilterFactory implements LogFilterFactory { + + @Override + public Filter create(String className) throws Exception { + return (Filter) Arc.container().instance(Class.forName(className, true, Thread.currentThread() + .getContextClassLoader())).get(); + } + + @Override + public int priority() { + return LogFilterFactory.DEFAULT_PRIORITY - 100; + } +} diff --git a/extensions/arc/runtime/src/main/resources/META-INF/services/io.quarkus.runtime.logging.LogFilterFactory b/extensions/arc/runtime/src/main/resources/META-INF/services/io.quarkus.runtime.logging.LogFilterFactory new file mode 100644 index 00000000000000..d114e9f1e84d40 --- /dev/null +++ b/extensions/arc/runtime/src/main/resources/META-INF/services/io.quarkus.runtime.logging.LogFilterFactory @@ -0,0 +1 @@ +io.quarkus.arc.runtime.logging.ArcLogFilterFactory diff --git a/integration-tests/logging-min-level-set/src/main/java/io/quarkus/it/logging/minlevel/set/filter/TestFilter.java b/integration-tests/logging-min-level-set/src/main/java/io/quarkus/it/logging/minlevel/set/filter/TestFilter.java index 30163df4312409..964a97ad1850e8 100644 --- a/integration-tests/logging-min-level-set/src/main/java/io/quarkus/it/logging/minlevel/set/filter/TestFilter.java +++ b/integration-tests/logging-min-level-set/src/main/java/io/quarkus/it/logging/minlevel/set/filter/TestFilter.java @@ -3,13 +3,21 @@ import java.util.logging.Filter; import java.util.logging.LogRecord; +import org.eclipse.microprofile.config.inject.ConfigProperty; + import io.quarkus.logging.LoggingFilter; @LoggingFilter(name = "my-filter") -public final class TestFilter implements Filter { +public class TestFilter implements Filter { + + private final String part; + + public TestFilter(@ConfigProperty(name = "my-filter.part") String part) { + this.part = part; + } @Override public boolean isLoggable(LogRecord record) { - return !record.getMessage().contains("TEST"); + return !record.getMessage().contains(part); } } diff --git a/integration-tests/logging-min-level-set/src/main/resources/application.properties b/integration-tests/logging-min-level-set/src/main/resources/application.properties index e33158f666c731..89dddefeda7c1f 100644 --- a/integration-tests/logging-min-level-set/src/main/resources/application.properties +++ b/integration-tests/logging-min-level-set/src/main/resources/application.properties @@ -4,3 +4,4 @@ quarkus.log.category."io.quarkus.it.logging.minlevel.set.below".min-level=TRACE quarkus.log.category."io.quarkus.it.logging.minlevel.set.below.child".min-level=inherit quarkus.log.category."io.quarkus.it.logging.minlevel.set.promote".min-level=ERROR quarkus.log.console.filter=my-filter +my-filter.part=TEST