From 907c7fa184ecbdfa131a259a290ae77c5d518bf8 Mon Sep 17 00:00:00 2001 From: Andrew Ash Date: Mon, 11 Aug 2025 13:13:36 -0700 Subject: [PATCH 1/4] More efficient FormattingTestReporter.writeAllOutput by lazily processing each line --- .../logging/gradle/testreport/FormattingTestReporter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java index 1b2bbdfd..d20e982b 100644 --- a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java +++ b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java @@ -18,6 +18,7 @@ // CHECKSTYLE:OFF +import com.google.common.base.Splitter; import com.palantir.witchcraft.java.logging.format.LogFormatter; import com.palantir.witchcraft.java.logging.format.LogParser; import java.io.File; @@ -69,14 +70,13 @@ private static final class FormattingTestResultsProvider implements TestResultsP } @Override - @SuppressWarnings("StringSplitter") public void writeAllOutput(long classId, TestOutputEvent.Destination destination, Writer writer) { if (destination == TestOutputEvent.Destination.StdErr || destination == TestOutputEvent.Destination.StdOut) { StringWriter stringWriter = new StringWriter(); delegate.writeAllOutput(classId, destination, stringWriter); String contents = stringWriter.toString(); - for (String line : contents.split("\n")) { + Splitter.on('\n').splitToStream(contents).forEachOrdered(line -> { try { PARSER.tryParse(line) .orElseGet(() -> out -> { @@ -87,7 +87,7 @@ public void writeAllOutput(long classId, TestOutputEvent.Destination destination } catch (IOException e) { throw new RuntimeException(e); } - } + }); } else { delegate.writeAllOutput(classId, destination, writer); } From c9fbe99003195bc172be8868684dc7887c35d8ee Mon Sep 17 00:00:00 2001 From: Andrew Ash Date: Mon, 11 Aug 2025 13:23:33 -0700 Subject: [PATCH 2/4] LineProcessingWriter --- .../testreport/FormattingTestReporter.java | 65 ++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java index d20e982b..db9cf82a 100644 --- a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java +++ b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java @@ -18,12 +18,10 @@ // CHECKSTYLE:OFF -import com.google.common.base.Splitter; import com.palantir.witchcraft.java.logging.format.LogFormatter; import com.palantir.witchcraft.java.logging.format.LogParser; import java.io.File; import java.io.IOException; -import java.io.StringWriter; import java.io.Writer; import org.gradle.api.Action; import org.gradle.api.internal.tasks.testing.junit.result.TestClassResult; @@ -73,26 +71,59 @@ private static final class FormattingTestResultsProvider implements TestResultsP public void writeAllOutput(long classId, TestOutputEvent.Destination destination, Writer writer) { if (destination == TestOutputEvent.Destination.StdErr || destination == TestOutputEvent.Destination.StdOut) { - StringWriter stringWriter = new StringWriter(); - delegate.writeAllOutput(classId, destination, stringWriter); - String contents = stringWriter.toString(); - Splitter.on('\n').splitToStream(contents).forEachOrdered(line -> { - try { - PARSER.tryParse(line) - .orElseGet(() -> out -> { - out.write(line); - out.write("\n"); - }) - .write(writer); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); + delegate.writeAllOutput(classId, destination, new LineProcessingWriter(writer, PARSER)); } else { delegate.writeAllOutput(classId, destination, writer); } } + private static class LineProcessingWriter extends Writer { + private final Writer delegate; + private final LogParser parser; + private final StringBuilder lineBuffer = new StringBuilder(); + + LineProcessingWriter(Writer delegate, LogParser parser) { + this.delegate = delegate; + this.parser = parser; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + for (int i = off; i < off + len; i++) { + char c = cbuf[i]; + if (c == '\n') { + processLine(); + } else { + lineBuffer.append(c); + } + } + } + + @Override + public void flush() throws IOException { + delegate.flush(); + } + + @Override + public void close() throws IOException { + if (!lineBuffer.isEmpty()) { + processLine(); + } + delegate.close(); + } + + private void processLine() throws IOException { + String line = lineBuffer.toString(); + parser.tryParse(line) + .orElseGet(() -> out -> { + out.write(line); + out.write("\n"); + }) + .write(delegate); + lineBuffer.setLength(0); + } + } + @Override public void writeNonTestOutput(long classId, TestOutputEvent.Destination destination, Writer writer) { delegate.writeNonTestOutput(classId, destination, writer); From 0d7eae0690c1ca1eb9af1a6b43fcc44a0bdeb97f Mon Sep 17 00:00:00 2001 From: Andrew Ash Date: Mon, 11 Aug 2025 14:52:11 -0700 Subject: [PATCH 3/4] BiConsumer --- .../testreport/FormattingTestReporter.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java index db9cf82a..06a8ee79 100644 --- a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java +++ b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; import java.io.Writer; +import java.util.function.BiConsumer; import org.gradle.api.Action; import org.gradle.api.internal.tasks.testing.junit.result.TestClassResult; import org.gradle.api.internal.tasks.testing.junit.result.TestResultsProvider; @@ -60,6 +61,21 @@ private static final class FormattingTestResultsProvider implements TestResultsP writer.write("\n"); } : Writable.NOP)); + private static final BiConsumer LINE_PROCESSOR = (line, outputWriter) -> { + try { + PARSER.tryParse(line) + .orElseGet(() -> out -> { + try { + out.write(line); + } catch (IOException e) { + throw new RuntimeException(e); + } + }) + .write(outputWriter); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; private final TestResultsProvider delegate; @@ -71,7 +87,7 @@ private static final class FormattingTestResultsProvider implements TestResultsP public void writeAllOutput(long classId, TestOutputEvent.Destination destination, Writer writer) { if (destination == TestOutputEvent.Destination.StdErr || destination == TestOutputEvent.Destination.StdOut) { - delegate.writeAllOutput(classId, destination, new LineProcessingWriter(writer, PARSER)); + delegate.writeAllOutput(classId, destination, new LineProcessingWriter(writer, LINE_PROCESSOR)); } else { delegate.writeAllOutput(classId, destination, writer); } @@ -79,22 +95,22 @@ public void writeAllOutput(long classId, TestOutputEvent.Destination destination private static class LineProcessingWriter extends Writer { private final Writer delegate; - private final LogParser parser; + private final BiConsumer lineProcessor; private final StringBuilder lineBuffer = new StringBuilder(); - LineProcessingWriter(Writer delegate, LogParser parser) { + LineProcessingWriter(Writer delegate, BiConsumer lineProcessor) { this.delegate = delegate; - this.parser = parser; + this.lineProcessor = lineProcessor; } @Override public void write(char[] cbuf, int off, int len) throws IOException { for (int i = off; i < off + len; i++) { - char c = cbuf[i]; - if (c == '\n') { + char ch = cbuf[i]; + if (ch == '\n') { processLine(); } else { - lineBuffer.append(c); + lineBuffer.append(ch); } } } @@ -114,12 +130,8 @@ public void close() throws IOException { private void processLine() throws IOException { String line = lineBuffer.toString(); - parser.tryParse(line) - .orElseGet(() -> out -> { - out.write(line); - out.write("\n"); - }) - .write(delegate); + lineProcessor.accept(line, delegate); + delegate.write("\n"); lineBuffer.setLength(0); } } From 50543744b0acc1d91ddfea511c48b10f12cd8657 Mon Sep 17 00:00:00 2001 From: Andrew Ash Date: Mon, 22 Sep 2025 16:42:43 -0700 Subject: [PATCH 4/4] CR --- .../gradle/testreport/FormattingTestReporter.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java index 06a8ee79..5ab9da0e 100644 --- a/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java +++ b/gradle-witchcraft-logging/src/main/groovy/com/palantir/witchcraft/java/logging/gradle/testreport/FormattingTestReporter.java @@ -22,6 +22,7 @@ import com.palantir.witchcraft.java.logging.format.LogParser; import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.io.Writer; import java.util.function.BiConsumer; import org.gradle.api.Action; @@ -58,7 +59,7 @@ private static final class FormattingTestResultsProvider implements TestResultsP (include, formatted) -> include ? writer -> { writer.write(formatted); - writer.write("\n"); + writer.write('\n'); } : Writable.NOP)); private static final BiConsumer LINE_PROCESSOR = (line, outputWriter) -> { @@ -68,12 +69,12 @@ private static final class FormattingTestResultsProvider implements TestResultsP try { out.write(line); } catch (IOException e) { - throw new RuntimeException(e); + throw new UncheckedIOException(e); } }) .write(outputWriter); } catch (IOException e) { - throw new RuntimeException(e); + throw new UncheckedIOException(e); } }; @@ -131,7 +132,7 @@ public void close() throws IOException { private void processLine() throws IOException { String line = lineBuffer.toString(); lineProcessor.accept(line, delegate); - delegate.write("\n"); + delegate.write('\n'); lineBuffer.setLength(0); } }