Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Socket Logging Handler #23128

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.quarkus.deployment.builditem;

import java.util.Map;
import java.util.Optional;
import java.util.logging.Formatter;

import org.wildfly.common.Assert;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.runtime.RuntimeValue;

/**
* The named log formatters build item. Producing this item will cause the logging subsystem to disregard its
* logging formatting configuration and use the formatter provided instead. If multiple formatters
* are enabled at run time, a warning message is printed and only one is used. Reserved names are console, file, syslog,
* socket.
*/
public final class NamedLogFormatsBuildItem extends MultiBuildItem {
private final RuntimeValue<Optional<Map<String, Formatter>>> namedFormattersValue;

/**
* Construct a new instance.
*
* @param namedFormattersValue the optional named formatters run time value to use (must not be {@code null})
*/
public NamedLogFormatsBuildItem(final RuntimeValue<Optional<Map<String, Formatter>>> namedFormattersValue) {
this.namedFormattersValue = Assert.checkNotNullParam("namedFormattersValue", namedFormattersValue);
}

/**
* Get the named formatters value.
*
* @return the named formatters value
*/
public RuntimeValue<Optional<Map<String, Formatter>>> getNamedFormattersValue() {
return namedFormattersValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.LogCategoryBuildItem;
import io.quarkus.deployment.builditem.LogConsoleFormatBuildItem;
import io.quarkus.deployment.builditem.LogHandlerBuildItem;
import io.quarkus.deployment.builditem.NamedLogFormatsBuildItem;
import io.quarkus.deployment.builditem.NamedLogHandlersBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
Expand Down Expand Up @@ -172,7 +172,7 @@ void miscSetup(
LoggingSetupBuildItem setupLoggingRuntimeInit(LoggingSetupRecorder recorder, LogConfig log, LogBuildTimeConfig buildLog,
Optional<WebSocketLogHandlerBuildItem> logStreamHandlerBuildItem,
List<LogHandlerBuildItem> handlerBuildItems,
List<NamedLogHandlersBuildItem> namedHandlerBuildItems, List<LogConsoleFormatBuildItem> consoleFormatItems,
List<NamedLogHandlersBuildItem> namedHandlerBuildItems, List<NamedLogFormatsBuildItem> formatItems,
Optional<ConsoleFormatterBannerBuildItem> possibleBannerBuildItem,
List<LogStreamBuildItem> logStreamBuildItems,
LaunchModeBuildItem launchModeBuildItem,
Expand Down Expand Up @@ -205,7 +205,7 @@ LoggingSetupBuildItem setupLoggingRuntimeInit(LoggingSetupRecorder recorder, Log

recorder.initializeLogging(log, buildLog, alwaysEnableLogStream, devUiLogHandler, handlers,
namedHandlers,
consoleFormatItems.stream().map(LogConsoleFormatBuildItem::getFormatterValue).collect(Collectors.toList()),
formatItems.stream().map(NamedLogFormatsBuildItem::getNamedFormattersValue).collect(Collectors.toList()),
possibleSupplier, launchModeBuildItem.getLaunchMode());
LogConfig logConfig = new LogConfig();
ConfigInstantiator.handleObject(logConfig);
Expand All @@ -232,7 +232,7 @@ public void run() {

@BuildStep(onlyIfNot = IsNormal.class)
@Produce(TestSetupBuildItem.class)
@Produce(LogConsoleFormatBuildItem.class)
@Produce(NamedLogFormatsBuildItem.class)
@Consume(ConsoleInstalledBuildItem.class)
void setupStackTraceFormatter(ApplicationArchivesBuildItem item, EffectiveIdeBuildItem ideSupport,
BuildSystemTargetBuildItem buildSystemTargetBuildItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ public final class LogConfig {
@ConfigDocSection
public SyslogConfig syslog;

/**
* Socket logging.
* <p>
* Logging to a socket is also supported but not enabled by default.
*/
@ConfigDocSection
public SocketConfig socket;

/**
* Logging categories.
* <p>
Expand Down Expand Up @@ -95,6 +103,15 @@ public final class LogConfig {
@ConfigDocSection
public Map<String, SyslogConfig> syslogHandlers;

/**
* Socket handlers.
* <p>
* The named socket handlers configured here can be linked on one or more categories.
*/
@ConfigItem(name = "handler.socket")
@ConfigDocSection
public Map<String, SocketConfig> socketHandlers;

/**
* Log cleanup filters - internal use.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.jboss.logmanager.handlers.PeriodicRotatingFileHandler;
import org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler;
import org.jboss.logmanager.handlers.SizeRotatingFileHandler;
import org.jboss.logmanager.handlers.SocketHandler;
import org.jboss.logmanager.handlers.SyslogHandler;

import io.quarkus.bootstrap.logging.InitialConfigurator;
Expand Down Expand Up @@ -85,7 +86,7 @@ public void initializeLogging(LogConfig config, LogBuildTimeConfig buildConfig,
final RuntimeValue<Optional<Handler>> devUiConsoleHandler,
final List<RuntimeValue<Optional<Handler>>> additionalHandlers,
final List<RuntimeValue<Map<String, Handler>>> additionalNamedHandlers,
final List<RuntimeValue<Optional<Formatter>>> possibleFormatters,
final List<RuntimeValue<Optional<Map<String, Formatter>>>> possibleFormatters,
final RuntimeValue<Optional<Supplier<String>>> possibleBannerSupplier, LaunchMode launchMode) {

final Map<String, CategoryConfig> categories = config.categories;
Expand Down Expand Up @@ -126,7 +127,7 @@ public void accept(String loggerName, CleanupFilterConfig config) {
if (config.console.enable) {
final Handler consoleHandler = configureConsoleHandler(config.console, consoleRuntimeConfig.getValue(),
errorManager, cleanupFiler,
possibleFormatters, possibleBannerSupplier, launchMode);
getApplicableFormatters(possibleFormatters, "console"), possibleBannerSupplier, launchMode);
errorManager = consoleHandler.getErrorManager();
handlers.add(consoleHandler);
}
Expand All @@ -150,16 +151,26 @@ public void close() throws SecurityException {
}

if (config.file.enable) {
handlers.add(configureFileHandler(config.file, errorManager, cleanupFiler));
handlers.add(configureFileHandler(config.file, errorManager, cleanupFiler,
getApplicableFormatters(possibleFormatters, "file")));
}

if (config.syslog.enable) {
final Handler syslogHandler = configureSyslogHandler(config.syslog, errorManager, cleanupFiler);
final Handler syslogHandler = configureSyslogHandler(config.syslog, errorManager, cleanupFiler,
getApplicableFormatters(possibleFormatters, "syslog"));
if (syslogHandler != null) {
handlers.add(syslogHandler);
}
}

if (config.socket.enable) {
final Handler socketHandler = configureSocketHandler(config.socket, errorManager, cleanupFiler,
getApplicableFormatters(possibleFormatters, "socket"));
if (socketHandler != null) {
handlers.add(socketHandler);
}
}

if ((launchMode.isDevOrTest() || enableWebStream)
&& devUiConsoleHandler != null
&& devUiConsoleHandler.getValue().isPresent()) {
Expand Down Expand Up @@ -317,37 +328,55 @@ private static CategoryBuildTimeConfig isSubsetOf(String categoryName, Map<Strin
}

private static Map<String, Handler> createNamedHandlers(LogConfig config, ConsoleRuntimeConfig consoleRuntimeConfig,
List<RuntimeValue<Optional<Formatter>>> possibleFormatters, ErrorManager errorManager,
List<RuntimeValue<Optional<Map<String, Formatter>>>> possibleFormatters, ErrorManager errorManager,
LogCleanupFilter cleanupFilter, LaunchMode launchMode) {
Map<String, Handler> namedHandlers = new HashMap<>();
for (Entry<String, ConsoleConfig> consoleConfigEntry : config.consoleHandlers.entrySet()) {
ConsoleConfig namedConsoleConfig = consoleConfigEntry.getValue();
if (!namedConsoleConfig.enable) {
continue;
}
List<Formatter> formatters = getApplicableFormatters(possibleFormatters, "console");
formatters.addAll(getApplicableFormatters(possibleFormatters, consoleConfigEntry.getKey()));
final Handler consoleHandler = configureConsoleHandler(namedConsoleConfig, consoleRuntimeConfig, errorManager,
cleanupFilter,
possibleFormatters, null, launchMode);
formatters, null, launchMode);
addToNamedHandlers(namedHandlers, consoleHandler, consoleConfigEntry.getKey());
}
for (Entry<String, FileConfig> fileConfigEntry : config.fileHandlers.entrySet()) {
FileConfig namedFileConfig = fileConfigEntry.getValue();
if (!namedFileConfig.enable) {
continue;
}
final Handler fileHandler = configureFileHandler(namedFileConfig, errorManager, cleanupFilter);
List<Formatter> formatters = getApplicableFormatters(possibleFormatters, "file");
formatters.addAll(getApplicableFormatters(possibleFormatters, fileConfigEntry.getKey()));
final Handler fileHandler = configureFileHandler(namedFileConfig, errorManager, cleanupFilter, formatters);
addToNamedHandlers(namedHandlers, fileHandler, fileConfigEntry.getKey());
}
for (Entry<String, SyslogConfig> sysLogConfigEntry : config.syslogHandlers.entrySet()) {
SyslogConfig namedSyslogConfig = sysLogConfigEntry.getValue();
if (!namedSyslogConfig.enable) {
continue;
}
final Handler syslogHandler = configureSyslogHandler(namedSyslogConfig, errorManager, cleanupFilter);
List<Formatter> formatters = getApplicableFormatters(possibleFormatters, "syslog");
formatters.addAll(getApplicableFormatters(possibleFormatters, sysLogConfigEntry.getKey()));
final Handler syslogHandler = configureSyslogHandler(namedSyslogConfig, errorManager, cleanupFilter, formatters);
if (syslogHandler != null) {
addToNamedHandlers(namedHandlers, syslogHandler, sysLogConfigEntry.getKey());
}
}
for (Entry<String, SocketConfig> socketConfigEntry : config.socketHandlers.entrySet()) {
SocketConfig namedSocketConfig = socketConfigEntry.getValue();
if (!namedSocketConfig.enable) {
continue;
}
List<Formatter> formatters = getApplicableFormatters(possibleFormatters, "socket");
formatters.addAll(getApplicableFormatters(possibleFormatters, socketConfigEntry.getKey()));
final Handler socketHandler = configureSocketHandler(namedSocketConfig, errorManager, cleanupFilter, formatters);
if (socketHandler != null) {
addToNamedHandlers(namedHandlers, socketHandler, socketConfigEntry.getKey());
}
}
return namedHandlers;
}

Expand Down Expand Up @@ -395,23 +424,31 @@ public void initializeLoggingForImageBuild() {
}
}

public static List<Formatter> getApplicableFormatters(
List<RuntimeValue<Optional<Map<String, Formatter>>>> possibleFormatters, String key) {
List<Formatter> formatters = new ArrayList<>();
for (RuntimeValue<Optional<Map<String, Formatter>>> value : possibleFormatters) {
final Optional<Map<String, Formatter>> val = value.getValue();
if (val.isPresent()) {
Formatter formatter = val.get().get(key);
if (formatter != null)
formatters.add(formatter);
}
}
return formatters;
}

private static Handler configureConsoleHandler(final ConsoleConfig config, ConsoleRuntimeConfig consoleRuntimeConfig,
final ErrorManager defaultErrorManager,
final LogCleanupFilter cleanupFilter,
final List<RuntimeValue<Optional<Formatter>>> possibleFormatters,
final List<Formatter> formatters,
final RuntimeValue<Optional<Supplier<String>>> possibleBannerSupplier, LaunchMode launchMode) {
Formatter formatter = null;
boolean formatterWarning = false;

for (RuntimeValue<Optional<Formatter>> value : possibleFormatters) {
if (formatter != null) {
formatterWarning = true;
}
final Optional<Formatter> val = value.getValue();
if (val.isPresent()) {
formatter = val.get();
}
boolean formatterWarning = formatters.size() > 1;
if (!formatters.isEmpty()) {
formatter = formatters.get(formatters.size() - 1);
}

boolean color = false;
if (formatter == null) {
Supplier<String> bannerSupplier = null;
Expand Down Expand Up @@ -478,7 +515,7 @@ public void close() throws SecurityException {
}

private static Handler configureFileHandler(final FileConfig config, final ErrorManager errorManager,
final LogCleanupFilter cleanupFilter) {
final LogCleanupFilter cleanupFilter, List<Formatter> formatters) {
FileHandler handler = new FileHandler();
FileConfig.RotationConfig rotationConfig = config.rotation;
if ((rotationConfig.maxFileSize.isPresent() || rotationConfig.rotateOnBoot)
Expand All @@ -501,8 +538,7 @@ private static Handler configureFileHandler(final FileConfig config, final Error
handler = periodicRotatingFileHandler;
}

final PatternFormatter formatter = new PatternFormatter(config.format);
handler.setFormatter(formatter);
handler.setFormatter(getFormatter(errorManager, formatters, () -> new PatternFormatter(config.format)));
handler.setAppend(true);
try {
handler.setFile(config.path);
Expand All @@ -520,7 +556,7 @@ private static Handler configureFileHandler(final FileConfig config, final Error

private static Handler configureSyslogHandler(final SyslogConfig config,
final ErrorManager errorManager,
final LogCleanupFilter logCleanupFilter) {
final LogCleanupFilter logCleanupFilter, List<Formatter> formatters) {
try {
final SyslogHandler handler = new SyslogHandler(config.endpoint.getHostString(), config.endpoint.getPort());
handler.setAppName(config.appName.orElse(getProcessName()));
Expand All @@ -532,8 +568,7 @@ private static Handler configureSyslogHandler(final SyslogConfig config,
handler.setTruncate(config.truncate);
handler.setUseCountingFraming(config.useCountingFraming);
handler.setLevel(config.level);
final PatternFormatter formatter = new PatternFormatter(config.format);
handler.setFormatter(formatter);
handler.setFormatter(getFormatter(errorManager, formatters, () -> new PatternFormatter(config.format)));
handler.setErrorManager(errorManager);
handler.setFilter(logCleanupFilter);
if (config.async.enable) {
Expand All @@ -546,6 +581,42 @@ private static Handler configureSyslogHandler(final SyslogConfig config,
}
}

private static Handler configureSocketHandler(final SocketConfig config,
final ErrorManager errorManager,
final LogCleanupFilter logCleanupFilter, List<Formatter> formatters) {
try {
final SocketHandler handler = new SocketHandler(config.endpoint.getHostString(), config.endpoint.getPort());
handler.setProtocol(config.protocol);
handler.setBlockOnReconnect(config.blockOnReconnect);
handler.setLevel(config.level);
handler.setFormatter(getFormatter(errorManager, formatters, () -> new PatternFormatter(config.format)));
handler.setErrorManager(errorManager);
handler.setFilter(logCleanupFilter);
if (config.async.enable) {
return createAsyncHandler(config.async, config.level, handler);
}
return handler;
} catch (IOException e) {
errorManager.error("Failed to create socket handler", e, ErrorManager.OPEN_FAILURE);
return null;
}
}

public static Formatter getFormatter(final ErrorManager errorManager, List<Formatter> formatters,
Supplier<Formatter> defaultFormatter) {
Formatter formatter;
boolean formatterWarning = formatters.size() > 1;
if (!formatters.isEmpty()) {
formatter = formatters.get(formatters.size() - 1);
} else {
formatter = defaultFormatter.get();
}
if (formatterWarning) {
errorManager.error("Multiple formatters were activated", null, ErrorManager.GENERIC_FAILURE);
}
return formatter;
}

private static AsyncHandler createAsyncHandler(AsyncConfig asyncConfig, Level level, Handler handler) {
final AsyncHandler asyncHandler = new AsyncHandler(asyncConfig.queueLength);
asyncHandler.setOverflowAction(asyncConfig.overflow);
Expand Down Expand Up @@ -602,4 +673,5 @@ public void accept(String name, Handler handler) {
handler.setFilter(new LogCleanupFilter(filterElements));
}
}

}
Loading