2021-12-23 10:42:24 +00:00
|
|
|
package com.onthegomap.planetiler.stats;
|
2021-04-07 00:33:35 +00:00
|
|
|
|
2021-06-05 12:02:51 +00:00
|
|
|
import static io.prometheus.client.Collector.NANOSECONDS_PER_SECOND;
|
|
|
|
|
2021-12-23 10:42:24 +00:00
|
|
|
import com.onthegomap.planetiler.util.FileUtils;
|
|
|
|
import com.onthegomap.planetiler.util.Format;
|
|
|
|
import com.onthegomap.planetiler.util.LogUtil;
|
|
|
|
import com.onthegomap.planetiler.util.MemoryEstimator;
|
2021-06-05 12:02:51 +00:00
|
|
|
import java.nio.file.Path;
|
2021-08-06 10:01:30 +00:00
|
|
|
import java.time.Duration;
|
2021-06-06 12:00:04 +00:00
|
|
|
import java.util.Map;
|
2021-10-20 01:57:47 +00:00
|
|
|
import java.util.concurrent.ConcurrentSkipListMap;
|
2021-06-05 12:02:51 +00:00
|
|
|
import java.util.function.Supplier;
|
2021-10-20 01:57:47 +00:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2021-06-05 12:02:51 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* A utility that collects and reports more detailed statistics about the JVM and running tasks than logs can convey.
|
|
|
|
* <p>
|
2022-03-09 02:08:03 +00:00
|
|
|
* {@link #inMemory()} stores basic stats in-memory to report at the end of the job and
|
|
|
|
* {@link #prometheusPushGateway(String, String, Duration)} pushes stats at a regular interval to a
|
|
|
|
* <a href="https://github.com/prometheus/pushgateway">prometheus push gateway</a>.
|
2021-09-10 00:46:20 +00:00
|
|
|
*/
|
2021-06-05 12:02:51 +00:00
|
|
|
public interface Stats extends AutoCloseable {
|
2021-04-07 00:33:35 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns a new stat collector that stores basic stats in-memory to report through {@link #printSummary()}. */
|
|
|
|
static Stats inMemory() {
|
|
|
|
return new InMemory();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-03-09 02:08:03 +00:00
|
|
|
* Returns a new stat collector pushes stats at a regular interval to a
|
|
|
|
* <a href="https://github.com/prometheus/pushgateway">prometheus push gateway</a> at {@code destination}.
|
2021-09-10 00:46:20 +00:00
|
|
|
*/
|
|
|
|
static Stats prometheusPushGateway(String destination, String job, Duration interval) {
|
|
|
|
return PrometheusStats.createAndStartPushing(destination, job, interval);
|
|
|
|
}
|
|
|
|
|
2021-10-20 01:57:47 +00:00
|
|
|
/**
|
|
|
|
* Logs top-level stats at the end of a job like the amount of user and CPU time that each task has taken, and size of
|
|
|
|
* each monitored file.
|
|
|
|
*/
|
2021-06-04 11:22:40 +00:00
|
|
|
default void printSummary() {
|
2022-01-28 01:23:24 +00:00
|
|
|
Format format = Format.defaultInstance();
|
2021-10-20 01:57:47 +00:00
|
|
|
Logger LOGGER = LoggerFactory.getLogger(getClass());
|
2022-03-09 02:08:03 +00:00
|
|
|
LOGGER.info("");
|
2021-10-20 01:57:47 +00:00
|
|
|
LOGGER.info("-".repeat(40));
|
2021-06-04 11:22:40 +00:00
|
|
|
timers().printSummary();
|
2021-10-20 01:57:47 +00:00
|
|
|
LOGGER.info("-".repeat(40));
|
|
|
|
for (var entry : monitoredFiles().entrySet()) {
|
|
|
|
long size = FileUtils.size(entry.getValue());
|
|
|
|
if (size > 0) {
|
2022-01-28 01:23:24 +00:00
|
|
|
LOGGER.info("\t" + entry.getKey() + "\t" + format.storage(size, false) + "B");
|
2021-10-20 01:57:47 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-04 11:22:40 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Records that a long-running task with {@code name} has started and returns a handle to call when finished.
|
|
|
|
* <p>
|
|
|
|
* Also sets the "stage" prefix that shows up in the logs to {@code name}.
|
|
|
|
*/
|
2021-08-10 10:55:30 +00:00
|
|
|
default Timers.Finishable startStage(String name) {
|
|
|
|
LogUtil.setStage(name);
|
|
|
|
var timer = timers().startTimer(name);
|
|
|
|
return () -> {
|
|
|
|
timer.stop();
|
|
|
|
LogUtil.clearStage();
|
|
|
|
};
|
|
|
|
}
|
2021-04-10 09:25:42 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Records that {@code numFeatures} features have been rendered to an output {@code layer} while processing a data
|
|
|
|
* source.
|
|
|
|
*/
|
|
|
|
void emittedFeatures(int z, String layer, int numFeatures);
|
2021-04-10 09:25:42 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Records that an input element was processed and emitted some output features in {@code layer}. */
|
|
|
|
void processedElement(String elemType, String layer);
|
2021-04-12 10:54:52 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Records that a tile has been written to the mbtiles output where compressed size is {@code bytes}. */
|
2021-06-04 11:22:40 +00:00
|
|
|
void wroteTile(int zoom, int bytes);
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Returns the timers for all stages started with {@link #startStage(String)}. */
|
2021-06-04 11:22:40 +00:00
|
|
|
Timers timers();
|
2021-04-16 00:54:33 +00:00
|
|
|
|
2021-10-20 01:57:47 +00:00
|
|
|
/** Returns all the files being monitored. */
|
|
|
|
Map<String, Path> monitoredFiles();
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Adds a stat that will track the size of a file or directory located at {@code path}. */
|
2021-10-20 01:57:47 +00:00
|
|
|
default void monitorFile(String name, Path path) {
|
|
|
|
monitoredFiles().put(name, path);
|
|
|
|
}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** Adds a stat that will track the estimated in-memory size of {@code object}. */
|
|
|
|
void monitorInMemoryObject(String name, MemoryEstimator.HasEstimate object);
|
2021-06-05 12:02:51 +00:00
|
|
|
|
2021-10-20 01:57:47 +00:00
|
|
|
/** Tracks a stat with {@code name} that always has a constant {@code value}. */
|
2021-09-10 00:46:20 +00:00
|
|
|
default void gauge(String name, Number value) {
|
|
|
|
gauge(name, () -> value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Tracks a stat with {@code name} that can go up or down over time. */
|
|
|
|
void gauge(String name, Supplier<Number> value);
|
|
|
|
|
|
|
|
/** Tracks a stat with {@code name} that should only go up over time. */
|
2021-06-05 12:02:51 +00:00
|
|
|
void counter(String name, Supplier<Number> supplier);
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Returns and starts tracking a new counter with {@code name} optimized for the caller to increment from multiple
|
|
|
|
* threads.
|
|
|
|
*/
|
2021-07-27 02:01:55 +00:00
|
|
|
default Counter.MultiThreadCounter longCounter(String name) {
|
|
|
|
Counter.MultiThreadCounter counter = Counter.newMultiThreadCounter();
|
2021-06-05 12:02:51 +00:00
|
|
|
counter(name, counter::get);
|
|
|
|
return counter;
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Returns and starts tracking a new counter where the value should be treated as number of milliseconds.
|
|
|
|
*/
|
2021-07-27 02:01:55 +00:00
|
|
|
default Counter.MultiThreadCounter nanoCounter(String name) {
|
|
|
|
Counter.MultiThreadCounter counter = Counter.newMultiThreadCounter();
|
2021-06-05 12:02:51 +00:00
|
|
|
counter(name, () -> counter.get() / NANOSECONDS_PER_SECOND);
|
|
|
|
return counter;
|
|
|
|
}
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Tracks a group of counters with a {@code label} key that is set to the key in each entry of the map returned from
|
|
|
|
* {@code values}.
|
|
|
|
*/
|
2021-06-06 12:00:04 +00:00
|
|
|
void counter(String name, String label, Supplier<Map<String, Counter.Readable>> values);
|
2021-06-05 12:02:51 +00:00
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/**
|
|
|
|
* Records that an invalid input feature was discarded where {@code errorCode} can be used to identify the kind of
|
|
|
|
* failure.
|
|
|
|
*/
|
|
|
|
void dataError(String errorCode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A stat collector that stores top-level metrics in-memory to report through {@link #printSummary()}.
|
|
|
|
* <p>
|
|
|
|
* Returns counters for the code to use, but doesn't keep a central listing of them.
|
|
|
|
*/
|
2021-04-11 20:10:28 +00:00
|
|
|
class InMemory implements Stats {
|
|
|
|
|
2021-09-10 00:46:20 +00:00
|
|
|
/** use {@link #inMemory()} */
|
2022-03-09 02:08:03 +00:00
|
|
|
private InMemory() {}
|
2021-09-10 00:46:20 +00:00
|
|
|
|
2021-06-04 11:22:40 +00:00
|
|
|
private final Timers timers = new Timers();
|
2021-10-20 01:57:47 +00:00
|
|
|
private final Map<String, Path> monitoredFiles = new ConcurrentSkipListMap<>();
|
2021-04-11 20:10:28 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void wroteTile(int zoom, int bytes) {}
|
2021-04-12 10:54:52 +00:00
|
|
|
|
|
|
|
@Override
|
2021-06-04 11:22:40 +00:00
|
|
|
public Timers timers() {
|
|
|
|
return timers;
|
2021-04-12 10:54:52 +00:00
|
|
|
}
|
2021-04-16 00:54:33 +00:00
|
|
|
|
|
|
|
@Override
|
2021-10-20 01:57:47 +00:00
|
|
|
public Map<String, Path> monitoredFiles() {
|
|
|
|
return monitoredFiles;
|
2021-06-05 12:02:51 +00:00
|
|
|
}
|
2021-04-16 00:54:33 +00:00
|
|
|
|
2021-06-05 12:02:51 +00:00
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void monitorInMemoryObject(String name, MemoryEstimator.HasEstimate object) {}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void counter(String name, Supplier<Number> supplier) {}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
@Override
|
2021-07-27 02:01:55 +00:00
|
|
|
public Counter.MultiThreadCounter longCounter(String name) {
|
|
|
|
return Counter.newMultiThreadCounter();
|
2021-06-06 12:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-07-27 02:01:55 +00:00
|
|
|
public Counter.MultiThreadCounter nanoCounter(String name) {
|
|
|
|
return Counter.newMultiThreadCounter();
|
2021-06-06 12:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void counter(String name, String label, Supplier<Map<String, Counter.Readable>> values) {}
|
2021-06-06 12:00:04 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void processedElement(String elemType, String layer) {}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void dataError(String errorCode) {}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void gauge(String name, Supplier<Number> value) {}
|
2021-06-04 11:22:40 +00:00
|
|
|
|
|
|
|
@Override
|
2022-03-09 02:08:03 +00:00
|
|
|
public void emittedFeatures(int z, String layer, int numFeatures) {}
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
@Override
|
2021-09-10 00:46:20 +00:00
|
|
|
public void close() {
|
2021-06-05 12:02:51 +00:00
|
|
|
|
|
|
|
}
|
2021-04-11 20:10:28 +00:00
|
|
|
}
|
2021-04-07 00:33:35 +00:00
|
|
|
}
|