From 411581042ac54ba836e2a23d76a09c6c63592092 Mon Sep 17 00:00:00 2001 From: Jeromy Cannon Date: Wed, 5 Jul 2023 12:47:47 -0500 Subject: [PATCH] feat: add SLF4J logging to fullstack-helm-client module (#137) Signed-off-by: Jeromy Cannon Signed-off-by: Nathan Klick Co-authored-by: Nathan Klick --- ...m.hedera.fullstack.jpms-modules.gradle.kts | 4 + fullstack-bom/build.gradle.kts | 1 + fullstack-helm-client/build.gradle.kts | 2 + .../helm/client/execution/HelmExecution.java | 75 +++++++++++++++++-- .../execution/HelmExecutionBuilder.java | 12 ++- .../client/resource/HelmSoftwareLoader.java | 10 +++ .../src/main/java/module-info.java | 1 + .../src/test/resources/log4j2-test.xml | 32 ++++++++ 8 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 fullstack-helm-client/src/test/resources/log4j2-test.xml diff --git a/buildSrc/src/main/kotlin/com.hedera.fullstack.jpms-modules.gradle.kts b/buildSrc/src/main/kotlin/com.hedera.fullstack.jpms-modules.gradle.kts index 3b9a25d74..40ee590ba 100644 --- a/buildSrc/src/main/kotlin/com.hedera.fullstack.jpms-modules.gradle.kts +++ b/buildSrc/src/main/kotlin/com.hedera.fullstack.jpms-modules.gradle.kts @@ -26,6 +26,10 @@ javaModuleDependencies { } extraJavaModuleInfo { + module("org.apache.logging.log4j:log4j-slf4j2-impl", "org.apache.logging.log4j.slf4j2.impl") { + exportAllPackages() + } + knownModule("org.slf4j:slf4j-api", "org.slf4j") knownModule("org.slf4j:slf4j-nop", "org.slf4j.nop") knownModule("org.slf4j:slf4j-simple", "org.slf4j.simple") diff --git a/fullstack-bom/build.gradle.kts b/fullstack-bom/build.gradle.kts index d18acc1d3..0b24bca7a 100644 --- a/fullstack-bom/build.gradle.kts +++ b/fullstack-bom/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { api(platform("org.assertj:assertj-bom:3.24.2")) api(platform("com.fasterxml.jackson:jackson-bom:2.15.2")) api(platform("org.mockito:mockito-bom:5.3.1")) + api(platform("org.apache.logging.log4j:log4j-bom:2.20.0")) } dependencies.constraints { diff --git a/fullstack-helm-client/build.gradle.kts b/fullstack-helm-client/build.gradle.kts index ec4f331d5..e61c06394 100644 --- a/fullstack-helm-client/build.gradle.kts +++ b/fullstack-helm-client/build.gradle.kts @@ -33,6 +33,8 @@ dependencies { testImplementation(gav("org.junit.jupiter.api")) testImplementation(gav("org.junit.jupiter.params")) testImplementation(gav("org.assertj.core")) + runtimeOnly(gav("org.apache.logging.log4j")) + runtimeOnly(gav("org.apache.logging.log4j.slf4j2.impl")) } } diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecution.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecution.java index e0584c316..d4eb903f1 100644 --- a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecution.java +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecution.java @@ -30,11 +30,17 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Represents the execution of a helm command and is responsible for parsing the response. */ public final class HelmExecution { + /** + * The logger for this class which should be used for all logging. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(HelmExecution.class); /** * The message for a timeout error. @@ -78,6 +84,11 @@ public final class HelmExecution { OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } + /** + * Creates a new {@link HelmExecution} instance for the specified process. + * + * @param process the underlying {@link Process} instance wrapped by this {@link HelmExecution} instance. + */ public HelmExecution(final Process process) { this.process = Objects.requireNonNull(process, "process must not be null"); this.standardOutputSink = new BufferedStreamSink(process.getInputStream()); @@ -210,9 +221,28 @@ public T responseAs(final Class responseClass, final Duration timeout) { throw new HelmExecutionException(exitCode()); } + final String standardOutput = StreamUtils.streamToString(suppressExceptions(this::standardOutput)); + final String standardError = StreamUtils.streamToString(suppressExceptions(this::standardError)); + + LOGGER.atDebug() + .setMessage( + "ResponseAs exiting with exitCode: {}\n\tResponseClass: {}\n\tstandardOutput: {}\n\tstandardError: {}") + .addArgument(this::exitCode) + .addArgument(responseClass.getName()) + .addArgument(standardOutput) + .addArgument(standardError) + .log(); + try { - return OBJECT_MAPPER.readValue(standardOutput(), responseClass); + return OBJECT_MAPPER.readValue(standardOutput, responseClass); } catch (final Exception e) { + LOGGER.atWarn() + .setMessage("ResponseAs failed to deserialize response into class: {}\n\tresponse: {}") + .addArgument(responseClass.getName()) + .addArgument(standardOutput) + .setCause(e) + .log(); + throw new HelmParserException(String.format(MSG_DESERIALIZATION_ERROR, responseClass.getName()), e); } } @@ -258,12 +288,31 @@ public List responseAsList(final Class responseClass, final Duration t throw new HelmExecutionException(exitCode()); } + final String standardOutput = StreamUtils.streamToString(suppressExceptions(this::standardOutput)); + final String standardError = StreamUtils.streamToString(suppressExceptions(this::standardError)); + + LOGGER.atDebug() + .setMessage( + "ResponseAsList exiting with exitCode: {}\n\tResponseClass: {}\n\tstandardOutput: {}\n\tstandardError: {}") + .addArgument(this::exitCode) + .addArgument(responseClass.getName()) + .addArgument(standardOutput) + .addArgument(standardError) + .log(); + try { return OBJECT_MAPPER .readerFor(responseClass) - .readValues(standardOutput()) + .readValues(standardOutput) .readAll(); } catch (final Exception e) { + LOGGER.atWarn() + .setMessage("ResponseAsList failed to deserialize response into class: {}\n\tresponse: {}") + .addArgument(responseClass.getName()) + .addArgument(standardOutput) + .setCause(e) + .log(); + throw new HelmParserException(String.format(MSG_LIST_DESERIALIZATION_ERROR, responseClass.getName()), e); } } @@ -296,11 +345,25 @@ public void call(final Duration timeout) { return; } + final String standardOutput = StreamUtils.streamToString(suppressExceptions(this::standardOutput)); + final String standardError = StreamUtils.streamToString(suppressExceptions(this::standardError)); + + LOGGER.atDebug() + .setMessage("Call exiting with exitCode: {}\n\tstandardOutput: {}\n\tstandardError: {}") + .addArgument(this::exitCode) + .addArgument(standardOutput) + .addArgument(standardError) + .log(); + if (exitCode() != 0) { - throw new HelmExecutionException( - exitCode(), - StreamUtils.streamToString(suppressExceptions(this::standardError)), - StreamUtils.streamToString(suppressExceptions(this::standardOutput))); + LOGGER.atWarn() + .setMessage("Call exiting with exitCode: {}\n\tstandardOutput: {}\n\tstandardError: {}") + .addArgument(this::exitCode) + .addArgument(standardOutput) + .addArgument(standardError) + .log(); + + throw new HelmExecutionException(exitCode(), standardError, standardOutput); } } } diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecutionBuilder.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecutionBuilder.java index 222cbd7f2..58a4751b7 100644 --- a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecutionBuilder.java +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/execution/HelmExecutionBuilder.java @@ -20,11 +20,14 @@ import java.io.IOException; import java.nio.file.Path; import java.util.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A builder for creating a helm command execution. */ public final class HelmExecutionBuilder { + private static final Logger LOGGER = LoggerFactory.getLogger(HelmExecutionBuilder.class); /** * The path to the helm executable. @@ -194,6 +197,13 @@ private String[] buildCommand() { } command.addAll(positionals); - return command.toArray(new String[0]); + + String[] commandArray = command.toArray(new String[0]); + LOGGER.atDebug() + .setMessage("Helm command: {}") + .addArgument(String.join(" ", Arrays.copyOfRange(commandArray, 1, commandArray.length))) + .log(); + + return commandArray; } } diff --git a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/resource/HelmSoftwareLoader.java b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/resource/HelmSoftwareLoader.java index 044d46852..74e270c6e 100644 --- a/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/resource/HelmSoftwareLoader.java +++ b/fullstack-helm-client/src/main/java/com/hedera/fullstack/helm/client/resource/HelmSoftwareLoader.java @@ -22,11 +22,14 @@ import com.hedera.fullstack.helm.client.HelmConfigurationException; import java.io.IOException; import java.nio.file.Path; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Loads the Helm executable contained in the JAR file into a temporary directory. */ public final class HelmSoftwareLoader { + private static final Logger LOGGER = LoggerFactory.getLogger(HelmSoftwareLoader.class); /** * The root resources folder where the software is located. @@ -83,6 +86,13 @@ public static Path installSupportedVersion() { pathBuilder.append(".exe"); } + LOGGER.atDebug() + .setMessage("Loading Helm executable from JAR file. [os={}, arch={}, path={}]") + .addArgument(os.name()) + .addArgument(arch.name()) + .addArgument(pathBuilder.toString()) + .log(); + return RESOURCE_LOADER.load(pathBuilder.toString()); } catch (IOException | SecurityException | IllegalStateException e) { throw new HelmConfigurationException(e); diff --git a/fullstack-helm-client/src/main/java/module-info.java b/fullstack-helm-client/src/main/java/module-info.java index b788f2832..f9dedce69 100644 --- a/fullstack-helm-client/src/main/java/module-info.java +++ b/fullstack-helm-client/src/main/java/module-info.java @@ -13,6 +13,7 @@ com.fasterxml.jackson.databind; requires com.fasterxml.jackson.databind; + requires org.slf4j; requires transitive com.hedera.fullstack.base.api; requires transitive com.fasterxml.jackson.annotation; } diff --git a/fullstack-helm-client/src/test/resources/log4j2-test.xml b/fullstack-helm-client/src/test/resources/log4j2-test.xml new file mode 100644 index 000000000..28a99f1c7 --- /dev/null +++ b/fullstack-helm-client/src/test/resources/log4j2-test.xml @@ -0,0 +1,32 @@ + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-8sn %-5p %-16marker <%t> %c{1}: %msg%n + + + + + + + + +