org.openstreetmap.atlas.utilities.runtime.RunScriptMonitor Maven / Gradle / Ivy
package org.openstreetmap.atlas.utilities.runtime;
import java.io.InputStream;
import java.util.concurrent.TimeoutException;
import org.openstreetmap.atlas.streaming.resource.InputStreamResource;
import org.openstreetmap.atlas.utilities.scalars.Duration;
import org.openstreetmap.atlas.utilities.threads.Pool;
import org.openstreetmap.atlas.utilities.threads.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Monitor for the output of a {@link Process} started with {@link RunScript}.
*
* @author matthieun
*/
public abstract class RunScriptMonitor
{
/**
* Print the logs of a {@link Process} using a {@link Logger}
*
* @author matthieun
*/
public static class PrinterMonitor extends RunScriptMonitor
{
private final Logger logger;
public PrinterMonitor(final Logger logger)
{
this.logger = logger;
}
@Override
protected void parseStandardError(final Iterable lines)
{
parseStream(lines);
}
@Override
protected void parseStandardOutput(final Iterable lines)
{
parseStream(lines);
}
private void parseStream(final Iterable lines)
{
lines.forEach(line -> this.logger.info(line));
}
}
private static final Duration REFRESH_DURATION = Duration.milliseconds(100);
private static final Logger logger = LoggerFactory.getLogger(RunScriptMonitor.class);
private Thread out;
private Thread err;
/**
* Parse the output logs of a {@link Process}.
*
* @param standardOut
* The output stream for standard output
* @param standardErr
* The output stream for standard error
*/
protected void parse(final InputStream standardOut, final InputStream standardErr)
{
this.out = new Thread(
() -> parseStandardOutput(new InputStreamResource(() -> standardOut).lines()));
this.err = new Thread(
() -> parseStandardError(new InputStreamResource(() -> standardErr).lines()));
this.out.setPriority(Thread.MAX_PRIORITY);
this.err.setPriority(Thread.MAX_PRIORITY);
this.out.start();
this.err.start();
}
/**
* Parse the standard error stream
*
* @param lines
* The stream
*/
protected abstract void parseStandardError(Iterable lines);
/**
* Parse the standard output stream
*
* @param lines
* The stream
*/
protected abstract void parseStandardOutput(Iterable lines);
/**
* Make sure that the logs are parsed before the end.
*
* @param maximum
* The maximum duration to wait for.
*/
protected void waitForCompletion(final Duration maximum)
{
try (Pool waiter = new Pool(1, "waiter", Duration.ONE_SECOND))
{
final Result result = waiter.queue(() ->
{
while (this.out.isAlive() || this.err.isAlive())
{
REFRESH_DURATION.sleep();
}
return true;
});
result.get(maximum);
}
catch (final TimeoutException e)
{
logger.warn("RunScript logs monitor did not finish in {}.", maximum);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy