Skip to content

Commit

Permalink
Enable the registration of @LoggingFilter classes via CDI
Browse files Browse the repository at this point in the history
This allows for users to configure their filters
via the usual Quarkus configuration approach.

Follows up on: quarkusio#27864
  • Loading branch information
geoand committed Sep 14, 2022
1 parent 9402450 commit 94db7c1
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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 '"
Expand Down Expand Up @@ -235,7 +234,8 @@ LoggingSetupBuildItem setupLoggingRuntimeInit(RecorderContext context, LoggingSe
BuildProducer<ShutdownListenerBuildItem> shutdownListenerBuildItemBuildProducer,
LaunchModeBuildItem launchModeBuildItem,
List<LogCleanupFilterBuildItem> logCleanupFilters,
BuildProducer<ReflectiveClassBuildItem> reflectiveClassBuildItemBuildProducer) {
BuildProducer<ReflectiveClassBuildItem> reflectiveClassBuildItemBuildProducer,
BuildProducer<ServiceProviderBuildItem> serviceProviderBuildItemBuildProducer) {
if (!launchModeBuildItem.isAuxiliaryApplication()
|| launchModeBuildItem.getAuxiliaryDevModeType().orElse(null) == DevModeType.TEST_ONLY) {
final List<RuntimeValue<Optional<Handler>>> handlers = handlerBuildItems.stream()
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()))) {
Expand All @@ -343,11 +341,6 @@ private DiscoveredLogComponents discoverLogComponents(IndexView index) {
ILLEGAL_LOGGING_FILTER_USE_MESSAGE + " Offending class is '" + classInfo.name() + "'");
}

MethodInfo ctor = classInfo.method("<init>");
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.");
Expand Down
Original file line number Diff line number Diff line change
@@ -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<LogFilterFactory> 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,12 @@ private static Map<String, Filter> createNamedFilters(DiscoveredLogComponents di
}

Map<String, Filter> 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 + "'");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<BeanDefiningAnnotationBuildItem> beanDefiningAnnotationProducer) {
beanDefiningAnnotationProducer.produce(new BeanDefiningAnnotationBuildItem(
LoggingResourceProcessor.LOGGING_FILTER, BuiltinScope.SINGLETON.getName(), false));
}

}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.arc.runtime.logging.ArcLogFilterFactory
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 94db7c1

Please sign in to comment.