Skip to content

Commit

Permalink
Quite down Quinoa logs (#734)
Browse files Browse the repository at this point in the history
Currently, Quinoa generates a lot of logs during
quarkus dev because it has to do a bunch of stuff.
Most of these logs are only useful as progress
 markers or when an error occurs , so they
 great candidates for the StartupLogCompressor
  • Loading branch information
geoand authored Jul 29, 2024
1 parent a439560 commit 9c51aca
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.quarkus.deployment.console.ConsoleInstalledBuildItem;
import io.quarkus.deployment.logging.LoggingSetupBuildItem;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.deployment.util.FileUtil;
import io.quarkus.runtime.LaunchMode;
Expand Down Expand Up @@ -111,7 +113,9 @@ public ConfiguredQuinoaBuildItem prepareQuinoaDirectory(
public InstalledPackageManagerBuildItem install(
ConfiguredQuinoaBuildItem configuredQuinoa,
LiveReloadBuildItem liveReload,
OutputTargetBuildItem outputTarget) throws IOException {
OutputTargetBuildItem outputTarget,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) throws IOException {
if (configuredQuinoa != null) {
final QuinoaConfig resolvedConfig = configuredQuinoa.resolvedConfig();
Optional<String> packageManagerBinary = resolvedConfig.packageManager();
Expand All @@ -120,13 +124,16 @@ public InstalledPackageManagerBuildItem install(
final PackageManagerInstall.Installation result = PackageManagerInstall.install(
resolvedConfig.packageManagerInstall(),
configuredQuinoa.projectDir(),
configuredQuinoa.uiDir());
configuredQuinoa.uiDir(),
consoleInstalledBuildItem,
loggingSetupBuildItem);
packageManagerBinary = Optional.of(result.getPackageManagerBinary());
paths.add(result.getNodeDirPath());
}

final PackageManagerRunner packageManagerRunner = autoDetectPackageManager(packageManagerBinary,
resolvedConfig.packageManagerCommand(), configuredQuinoa.uiDir(), paths);
resolvedConfig.packageManagerCommand(), configuredQuinoa.uiDir(), paths, consoleInstalledBuildItem,
loggingSetupBuildItem);
final Path targetPackageJson = outputTarget.getOutputDirectory().resolve(TARGET_DIR_NAME).resolve(BUILD_FILE);
final Path currentPackageJson = configuredQuinoa.packageJson();
if (resolvedConfig.forceInstall()
Expand Down Expand Up @@ -271,10 +278,10 @@ private HashSet<BuiltResourcesBuildItem.BuiltResource> lookupBuiltResources(Path
try (Stream<Path> paths = Files.walk(targetDir, FileVisitOption.FOLLOW_LINKS).filter(Files::isRegularFile)) {
final var files = paths.toList();
final HashSet<BuiltResourcesBuildItem.BuiltResource> entries = new HashSet<>(files.size());
LOG.infof("Quinoa target directory: '%s'", targetDir);
LOG.infof("Quinoa target directory: '%s' containing %d resources", targetDir, files.size());
for (Path file : files) {
final String name = "/" + targetDir.relativize(file).toString().replace('\\', '/');
LOG.infof("Quinoa generated resource: '%s'", name);
LOG.debugf("Quinoa generated resource: '%s'", name);
entries.add(new BuiltResourcesBuildItem.BuiltResource(name, Files.readAllBytes(file)));
}
return entries;
Expand Down Expand Up @@ -440,4 +447,4 @@ public Path getUIDir() {
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import com.github.eirslett.maven.plugins.frontend.lib.PackageManagerInstallFactory;

import io.quarkiverse.quinoa.deployment.config.PackageManagerInstallConfig;
import io.quarkus.deployment.console.ConsoleInstalledBuildItem;
import io.quarkus.deployment.console.StartupLogCompressor;
import io.quarkus.deployment.logging.LoggingSetupBuildItem;
import io.quarkus.deployment.util.FileUtil;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.vertx.core.Vertx;
Expand All @@ -35,7 +38,9 @@ private PackageManagerInstall() {
}

public static Installation install(PackageManagerInstallConfig config,
final Path projectDir, final Path uiDir) {
final Path projectDir, final Path uiDir,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) {
Path installDir = resolveInstallDir(config, projectDir).normalize();
if (config.nodeVersion().isEmpty()) {
throw new ConfigurationException("node-version is required to install package manager",
Expand All @@ -60,7 +65,7 @@ public static Installation install(PackageManagerInstallConfig config,
thrown.getCause().getMessage(), i + 1);
FileUtil.deleteDirectory(installDir);
}
return attemptInstall(config, uiDir, installDir, factory);
return attemptInstall(config, uiDir, installDir, factory, consoleInstalledBuildItem, loggingSetupBuildItem);
} catch (InstallationException e) {
thrown = e;
i++;
Expand Down Expand Up @@ -93,14 +98,22 @@ private static Vertx createVertxInstance() {
}

private static Installation attemptInstall(PackageManagerInstallConfig config, Path uiDir, Path installDir,
PackageManagerInstallFactory factory) throws InstallationException {
PackageManagerInstallFactory factory,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,

LoggingSetupBuildItem loggingSetupBuildItem) throws InstallationException {
StartupLogCompressor nodeInstallerLogCompressor = null;
try {
nodeInstallerLogCompressor = new StartupLogCompressor("node installer", consoleInstalledBuildItem,
loggingSetupBuildItem);
factory.getNodeInstaller()
.setNodeVersion("v" + config.nodeVersion().get())
.setNodeDownloadRoot(config.nodeDownloadRoot())
.setNpmVersion(config.npmVersion())
.install();
nodeInstallerLogCompressor.close();
} catch (InstallationException e) {
nodeInstallerLogCompressor.closeAndDumpCaptured();
if (e.getCause() instanceof DirectoryNotEmptyException && e.getCause().getMessage().contains("tmp")) {
LOG.warnf("Quinoa was not able to delete the Node install temporary directory: %s",
e.getCause().getMessage());
Expand All @@ -114,11 +127,20 @@ private static Installation attemptInstall(PackageManagerInstallConfig config, P
final String npmVersion = config.npmVersion();
boolean isNpmProvided = PackageManagerInstallConfig.NPM_PROVIDED.equalsIgnoreCase(npmVersion);
if (!isNpmProvided) {
factory.getNPMInstaller()
.setNodeVersion("v" + config.nodeVersion().get())
.setNpmVersion(npmVersion)
.setNpmDownloadRoot(config.npmDownloadRoot())
.install();
StartupLogCompressor npmInstallerLogCompressor = null;
try {
npmInstallerLogCompressor = new StartupLogCompressor("npm installer", consoleInstalledBuildItem,
loggingSetupBuildItem);
factory.getNPMInstaller()
.setNodeVersion("v" + config.nodeVersion().get())
.setNpmVersion(npmVersion)
.setNpmDownloadRoot(config.npmDownloadRoot())
.install();
npmInstallerLogCompressor.close();
} catch (InstallationException e) {
npmInstallerLogCompressor.closeAndDumpCaptured();
throw e;
}
}

// Use yarn if yarnVersion is set (and npm is provided)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static java.lang.String.format;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand All @@ -19,6 +20,7 @@
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

import javax.net.ssl.HostnameVerifier;
Expand Down Expand Up @@ -47,10 +49,16 @@ public class PackageManagerRunner {
private final Path directory;

private final PackageManager packageManager;
private final Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem;
private final LoggingSetupBuildItem loggingSetupBuildItem;

private PackageManagerRunner(Path directory, PackageManager packageManager) {
private PackageManagerRunner(Path directory, PackageManager packageManager,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) {
this.directory = directory;
this.packageManager = packageManager;
this.consoleInstalledBuildItem = consoleInstalledBuildItem;
this.loggingSetupBuildItem = loggingSetupBuildItem;
}

public Path getDirectory() {
Expand Down Expand Up @@ -182,7 +190,9 @@ public void run() {
}

public static PackageManagerRunner autoDetectPackageManager(Optional<String> configuredBinary,
PackageManagerCommandConfig packageManagerCommands, Path directory, List<String> paths) {
PackageManagerCommandConfig packageManagerCommands, Path directory, List<String> paths,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) {
String binary;
PackageManagerType type = detectPackageManagerType(directory);
if (configuredBinary.isEmpty()) {
Expand All @@ -191,7 +201,8 @@ public static PackageManagerRunner autoDetectPackageManager(Optional<String> con
binary = configuredBinary.get();
type = resolveConfiguredPackageManagerType(binary, type);
}
return new PackageManagerRunner(directory, PackageManager.resolve(type, binary, packageManagerCommands, paths));
return new PackageManagerRunner(directory, PackageManager.resolve(type, binary, packageManagerCommands, paths),
consoleInstalledBuildItem, loggingSetupBuildItem);
}

public static boolean isWindows() {
Expand All @@ -216,6 +227,7 @@ private Process process(PackageManager.Command command) {

private boolean exec(PackageManager.Command command) {
Process process = null;
HandleOutput handleOutput = null;
try {
final ProcessBuilder processBuilder = new ProcessBuilder();
if (!command.envs.isEmpty()) {
Expand All @@ -226,12 +238,17 @@ private boolean exec(PackageManager.Command command) {
.command(runner(command))
.redirectErrorStream(true)
.start();
new HandleOutput(process.getInputStream()).run();
handleOutput = new HandleOutput(process.getInputStream(), consoleInstalledBuildItem, loggingSetupBuildItem);
handleOutput.run();
process.waitFor();
} catch (IOException e) {
throw new RuntimeException("Input/Output error while executing command.", e);
} catch (InterruptedException e) {
return false;
} finally {
if (handleOutput != null) {
handleOutput.close();
}
}
return process != null && process.exitValue() == 0;
}
Expand All @@ -244,18 +261,25 @@ private String[] runner(PackageManager.Command command) {
}
}

private static class HandleOutput implements Runnable {
private static class HandleOutput implements Runnable, Closeable {

private final InputStream is;
private final Logger.Level logLevel;
private final StartupLogCompressor logCompressor;
private final AtomicBoolean closed = new AtomicBoolean(false);

HandleOutput(InputStream is) {
this(is, Logger.Level.INFO);
HandleOutput(InputStream is,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) {
this(is, Logger.Level.INFO, consoleInstalledBuildItem, loggingSetupBuildItem);
}

HandleOutput(InputStream is, Logger.Level logLevel) {
HandleOutput(InputStream is, Logger.Level logLevel,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
LoggingSetupBuildItem loggingSetupBuildItem) {
this.is = is;
this.logLevel = LOG.isEnabled(logLevel) ? logLevel : null;
logCompressor = new StartupLogCompressor("quinoa", consoleInstalledBuildItem, loggingSetupBuildItem);
}

@Override
Expand All @@ -272,6 +296,15 @@ public void run() {
if (logLevel != null) {
LOG.log(logLevel, "Failed to handle output", e);
}
closed.set(true);
logCompressor.closeAndDumpCaptured();
}
}

@Override
public void close() {
if (closed.compareAndSet(false, true)) {
logCompressor.close();
}
}
}
Expand Down

0 comments on commit 9c51aca

Please sign in to comment.