Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@
package org.keycloak.quarkus.runtime.logging;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Filter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.regex.Pattern;

import org.keycloak.common.util.MultiSiteUtils;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;

import io.quarkus.bootstrap.logging.InitialConfigurator;
import io.quarkus.logging.LoggingFilter;
import org.infinispan.commons.jdkspecific.ThreadCreator;

/**
* @author Alexander Schwartz
Expand All @@ -38,6 +43,10 @@ public final class KeycloakLogFilter implements Filter {
private static final Pattern ISPN000312_PATTERN = Pattern.compile(
"^\\[Context=(" + String.join("|", InfinispanConnectionProvider.USER_SESSION_CACHE_NAME, InfinispanConnectionProvider.CLIENT_SESSION_CACHE_NAME, InfinispanConnectionProvider.OFFLINE_USER_SESSION_CACHE_NAME, InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME) + ")] ISPN000312: .*");

// Use this thread pool to asynchronously log from non-blocking threads, which could otherwise be pinned and lead to deadlocks.
// A single thread ensures that all log entries appear in the correct order.
private final ExecutorService executor = Executors.newSingleThreadExecutor();

@Override
public boolean isLoggable(LogRecord record) {
// The ARJUNA012125 messages are logged and then thrown.
Expand All @@ -55,6 +64,21 @@ public boolean isLoggable(LogRecord record) {
}
}

if (ThreadCreator.isVirtual(Thread.currentThread())) {
executor.submit(new RecordLogger(record));
return false;
}

return true;
}

public record RecordLogger(LogRecord record) implements Runnable {
@Override
public void run() {
for (Handler handler : InitialConfigurator.DELAYED_HANDLER.getHandlers()) {
handler.publish(record);
}
}
}

}
Loading