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

DAT-12945: support JSON logging in maven plugin #4152

Merged
merged 5 commits into from May 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -730,7 +730,7 @@ private void configureLogging(Level logLevel, String logFile, boolean wasDefault
OutputStream outputStream = pathHandlerFactory.openResourceOutputStream(logFile, new OpenOptions().setAppend(true));
fileHandler = new StreamHandler(outputStream, new SimpleFormatter());

setFormatterOnHandler(logService, fileHandler);
JavaLogService.setFormatterOnHandler(logService, fileHandler);

rootLogger.addHandler(fileHandler);
}
Expand Down Expand Up @@ -771,20 +771,7 @@ private void configureLogging(Level logLevel, String logFile, boolean wasDefault
if (handler instanceof ConsoleHandler) {
handler.setLevel(cliLogLevel);
}
setFormatterOnHandler(logService, handler);
}
}

/**
* Set the formatter for the supplied handler if the supplied log service
* is a JavaLogService and that service specifies a custom formatter.
*/
private void setFormatterOnHandler(LogService logService, Handler handler) {
if (logService instanceof JavaLogService && handler != null) {
Formatter customFormatter = ((JavaLogService) logService).getCustomFormatter();
if (customFormatter != null) {
handler.setFormatter(customFormatter);
}
JavaLogService.setFormatterOnHandler(logService, handler);
}
}

Expand Down
Expand Up @@ -15,6 +15,10 @@
import liquibase.integration.commandline.ChangeExecListenerUtils;
import liquibase.integration.commandline.CommandLineUtils;
import liquibase.integration.commandline.LiquibaseCommandLineConfiguration;
import liquibase.logging.LogFormat;
import liquibase.logging.LogService;
import liquibase.logging.core.JavaLogService;
import liquibase.logging.core.LogServiceFactory;
import liquibase.resource.DirectoryResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.resource.SearchPathResourceAccessor;
Expand All @@ -40,6 +44,9 @@
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Handler;

import static liquibase.configuration.LiquibaseConfiguration.REGISTERED_VALUE_PROVIDERS_KEY;

/**
* A base class for providing Liquibase {@link liquibase.Liquibase} functionality.
Expand Down Expand Up @@ -572,6 +579,16 @@ public abstract class AbstractLiquibaseMojo extends AbstractMojo {
@PropertyElement
protected String changeExecListenerPropertiesFile;

/**
* Sets the format of log output to console or log files.
* Open Source users default to unstructured TXT logs to the console or output log files.
* Pro users have the option to set value as JSON or JSON_PRETTY to enable json-structured log files to the console or output log files.
*
* @parameter property="liquibase.logFormat"
*/
@PropertyElement
protected String logFormat;

protected String commandName;
protected DefaultChangeExecListener defaultChangeExecListener;

Expand All @@ -598,14 +615,47 @@ protected Writer getOutputWriter(final File outputFile) throws IOException {
return new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(outputFile.toPath()), encoding));
}

private Map<String, Object> setUpLogging() throws Exception {
// First determine whether the specified log format requires the use of the standard Scope logger.
boolean useScopeLogger = false;
if (this.logFormat != null) {
try {
useScopeLogger = LogFormat.valueOf(this.logFormat.toUpperCase()).isUseScopeLoggerInMaven();
} catch (Exception ignored) {

}
}

Map<String, Object> scopeAttrs = new HashMap<>();
if (!useScopeLogger) {
// If the specified log format does not require the use of the standard Liquibase logger, just return the
// Maven log service as is traditionally done.
scopeAttrs.put(Scope.Attr.logService.name(), new MavenLogService(getLog()));
return scopeAttrs;
} else {
// The log format requires the use of the standard Liquibase logger, so set it up.
scopeAttrs.put(LiquibaseCommandLineConfiguration.LOG_FORMAT.getKey(), this.logFormat);
scopeAttrs.put(REGISTERED_VALUE_PROVIDERS_KEY, true);
// Get a new log service after registering the value providers, since the log service might need to load parameters using newly registered value providers.
LogService newLogService = Scope.child(scopeAttrs, () -> Scope.getCurrentScope().getSingleton(LogServiceFactory.class).getDefaultLogService());
// Set the formatter on all the handlers.
java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger("");
for (Handler handler : rootLogger.getHandlers()) {
JavaLogService.setFormatterOnHandler(newLogService, handler);
}
scopeAttrs.put(Scope.Attr.logService.name(), newLogService);
return scopeAttrs;
}
}

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (StringUtil.trimToNull(logging) != null) {
getLog().error("The liquibase-maven-plugin now manages logging via the standard maven logging config, not the 'logging' configuration. Use the -e, -X or -q flags or see https://maven.apache.org/maven-logging.html");
}

try {
Scope.child(Scope.Attr.logService, new MavenLogService(getLog()), () -> {
Scope.child(setUpLogging(), () -> {

getLog().info(MavenUtils.LOG_SEPARATOR);

Expand Down
@@ -1,7 +1,17 @@
package liquibase.logging;

public enum LogFormat {
TEXT,
JSON,
JSON_PRETTY
TEXT(false),
JSON(true),
JSON_PRETTY(true);

private final boolean useScopeLoggerInMaven;

LogFormat(boolean useScopeLoggerInMaven) {
this.useScopeLoggerInMaven = useScopeLoggerInMaven;
}

public boolean isUseScopeLoggerInMaven() {
return useScopeLoggerInMaven;
}
}
@@ -1,11 +1,13 @@
package liquibase.logging.core;

import liquibase.logging.LogService;
import liquibase.logging.Logger;
import liquibase.serializer.LiquibaseSerializable;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Formatter;
import java.util.logging.Handler;

public class JavaLogService extends AbstractLogService {

Expand Down Expand Up @@ -95,4 +97,18 @@ public void setParent(java.util.logging.Logger parent) {
public Formatter getCustomFormatter() {
return null;
}


/**
* Set the formatter for the supplied handler if the supplied log service
* is a JavaLogService and that service specifies a custom formatter.
*/
public static void setFormatterOnHandler(LogService logService, Handler handler) {
if (logService instanceof JavaLogService && handler != null) {
Formatter customFormatter = ((JavaLogService) logService).getCustomFormatter();
if (customFormatter != null) {
handler.setFormatter(customFormatter);
}
}
}
}