Skip to content

Commit

Permalink
Merge pull request #1866 from jplag/feature/avoidProgressBarOverlap
Browse files Browse the repository at this point in the history
Avoid progress bar overlap
  • Loading branch information
tsaglam authored Aug 1, 2024
2 parents e2f9b23 + e8e1368 commit eb6dca8
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 10 deletions.
14 changes: 10 additions & 4 deletions cli/src/main/java/de/jplag/cli/logger/CollectedLogger.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.jplag.cli.logger;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
Expand All @@ -19,7 +20,6 @@ public class CollectedLogger extends AbstractLogger {
private static final String JPLAG_LOGGER_PREFIX = "de.jplag.";
private static final Level LOG_LEVEL_FOR_EXTERNAL_LIBRARIES = Level.ERROR;
private static final int MAXIMUM_MESSAGE_LENGTH = 32;
private static final PrintStream TARGET_STREAM = System.out;
private static Level currentLogLevel = Level.INFO;

private final transient SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-hh:mm:ss_SSS");
Expand Down Expand Up @@ -148,11 +148,10 @@ private StringBuilder prepareLogOutput(LogEntry entry) {

private void printLogEntry(LogEntry entry) {
StringBuilder output = prepareLogOutput(entry);
TARGET_STREAM.println(output);
DelayablePrinter.getInstance().println(output.toString());
if (entry.cause() != null) {
entry.cause().printStackTrace(TARGET_STREAM);
this.printStackTrace(entry.cause());
}
TARGET_STREAM.flush();
}

public static Level getLogLevel() {
Expand All @@ -162,4 +161,11 @@ public static Level getLogLevel() {
public static void setLogLevel(Level logLevel) {
currentLogLevel = logLevel;
}

private void printStackTrace(Throwable error) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
error.printStackTrace(new PrintStream(outputStream));
String stackTrace = outputStream.toString();
DelayablePrinter.getInstance().println(stackTrace);
}
}
73 changes: 73 additions & 0 deletions cli/src/main/java/de/jplag/cli/logger/DelayablePrinter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package de.jplag.cli.logger;

import java.io.PrintStream;
import java.util.PriorityQueue;
import java.util.Queue;

/**
* Prints strings to stdout. Provides the option to delay the actual printing.
*/
public class DelayablePrinter {
private final Queue<String> outputQueue;
private PrintStream targetStream;

private boolean isDelayed;

private static final class InstanceHolder {
private static final DelayablePrinter instance = new DelayablePrinter();
}

/**
* Threadsafe singleton getter
* @return The singleton instance
*/
public static DelayablePrinter getInstance() {
return InstanceHolder.instance;
}

private DelayablePrinter() {
this.outputQueue = new PriorityQueue<>();
this.targetStream = System.out;
this.isDelayed = false;
}

/**
* Prints the given string to the terminal appending a line-break
* @param output The string to print
*/
public synchronized void println(String output) {
this.outputQueue.offer(output);
this.printQueue();
}

/**
* Stops printing to the terminal until {@link #resume()} is called
*/
public synchronized void delay() {
this.isDelayed = true;
}

/**
* Resumes printing if {@link #delay()} was called
*/
public synchronized void resume() {
this.isDelayed = false;
this.printQueue();
}

/**
* Changes the output stream messages are written to
*/
public void setOutputStream(PrintStream printStream) {
this.targetStream = printStream;
}

private synchronized void printQueue() {
if (!this.isDelayed) {
while (!this.outputQueue.isEmpty()) {
this.targetStream.println(this.outputQueue.poll());
}
this.targetStream.flush();
}
}
}
6 changes: 3 additions & 3 deletions cli/src/main/java/de/jplag/cli/logger/IdleBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import de.jplag.logging.ProgressBar;

/**
* Prints an idle progress bar, that does not count upwards.
*/
public class IdleBar implements ProgressBar {
public class IdleBar extends LogDelayingProgressBar {
private final PrintStream output;

private final Thread runner;
Expand All @@ -27,6 +25,7 @@ public class IdleBar implements ProgressBar {
private boolean running = false;

public IdleBar(String text) {
super();
this.output = System.out;
this.runner = new Thread(this::run);
this.length = 50;
Expand Down Expand Up @@ -61,6 +60,7 @@ public void dispose() {
}
this.output.print('\r');
this.output.println(this.text + ": complete");
super.dispose();
}

private void run() {
Expand Down
17 changes: 17 additions & 0 deletions cli/src/main/java/de/jplag/cli/logger/LogDelayingProgressBar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.jplag.cli.logger;

import de.jplag.logging.ProgressBar;

/**
* Superclass for progress bars, that delay the log output until the bar is done
*/
public abstract class LogDelayingProgressBar implements ProgressBar {
protected LogDelayingProgressBar() {
DelayablePrinter.getInstance().delay();
}

@Override
public void dispose() {
DelayablePrinter.getInstance().resume();
}
}
6 changes: 3 additions & 3 deletions cli/src/main/java/de/jplag/cli/logger/TongfeiProgressBar.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package de.jplag.cli.logger;

import de.jplag.logging.ProgressBar;

/**
* A ProgressBar, that used the tongfei progress bar library underneath, to show progress bars on the cli.
*/
public class TongfeiProgressBar implements ProgressBar {
public class TongfeiProgressBar extends LogDelayingProgressBar {
private final me.tongfei.progressbar.ProgressBar progressBar;

public TongfeiProgressBar(me.tongfei.progressbar.ProgressBar progressBar) {
super();
this.progressBar = progressBar;
}

Expand All @@ -20,5 +19,6 @@ public void step(int number) {
@Override
public void dispose() {
this.progressBar.close();
super.dispose();
}
}
51 changes: 51 additions & 0 deletions cli/src/test/java/de/jplag/cli/logger/DelayablePrinterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package de.jplag.cli.logger;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class DelayablePrinterTest {
private static final String TEST_MESSAGE = "Hello World";

private static ByteArrayOutputStream outputStream;

@BeforeAll
static void setUp() {
outputStream = new ByteArrayOutputStream();
DelayablePrinter.getInstance().setOutputStream(new PrintStream(outputStream));
}

@AfterAll
static void tearDown() {
DelayablePrinter.getInstance().setOutputStream(System.out);
}

@AfterEach
void cleanUpAfterTest() {
DelayablePrinter.getInstance().resume();
outputStream.reset();
}

@Test
void testDelay() {
DelayablePrinter.getInstance().delay();
DelayablePrinter.getInstance().println(TEST_MESSAGE);

Assertions.assertEquals("", outputStream.toString());

DelayablePrinter.getInstance().resume();

Assertions.assertEquals(TEST_MESSAGE + System.lineSeparator(), outputStream.toString());
}

@Test
void testDirectPrinting() {
DelayablePrinter.getInstance().println(TEST_MESSAGE);
Assertions.assertEquals(TEST_MESSAGE + System.lineSeparator(), outputStream.toString());
}
}

0 comments on commit eb6dca8

Please sign in to comment.