001package io.prometheus.metrics.core.datapoints;
002
003import java.util.concurrent.Callable;
004import java.util.function.Supplier;
005
006/**
007 * Convenience API for timing durations.
008 * <p>
009 * Durations are recorded in seconds. The Prometheus instrumentation guidelines <a href="https://prometheus.io/docs/instrumenting/writing_exporters/#naming">say</a>:
010 * <i>"Metrics must use base units (e.g. seconds, bytes) and leave converting them to something more readable to graphing tools".</i>
011 */
012public interface TimerApi {
013
014    /**
015     * Start a {@code Timer}. Example:
016     * <pre>{@code
017     * Histogram histogram = Histogram.builder()
018     *         .name("http_request_duration_seconds")
019     *         .help("HTTP request service time in seconds")
020     *         .unit(SECONDS)
021     *         .labelNames("method", "path")
022     *         .register();
023     *
024     * try (Timer timer = histogram.labelValues("GET", "/").startTimer()) {
025     *     // duration of this code block will be observed.
026     * }
027     * }</pre>
028     * Durations are recorded in seconds. The Prometheus instrumentation guidelines <a href="https://prometheus.io/docs/instrumenting/writing_exporters/#naming">say</a>:
029     * <i>"Metrics must use base units (e.g. seconds, bytes) and leave converting them to something more readable to graphing tools".</i>
030     */
031    Timer startTimer();
032
033    /**
034     * Observe the duration of the {@code func} call. Example:
035     * <pre>{@code
036     * Histogram histogram = Histogram.builder()
037     *         .name("request_duration_seconds")
038     *         .help("HTTP request service time in seconds")
039     *         .unit(SECONDS)
040     *         .labelNames("method", "path")
041     *         .register();
042     *
043     * histogram2.labelValues("GET", "/").time(() -> {
044     *     // duration of this code block will be observed.
045     * });
046     * }</pre>
047     * <p>
048     * Durations are recorded in seconds. The Prometheus instrumentation guidelines <a href="https://prometheus.io/docs/instrumenting/writing_exporters/#naming">say</a>:
049     * <i>"Metrics must use base units (e.g. seconds, bytes) and leave converting them to something more readable to graphing tools".</i>
050     */
051    default void time(Runnable func) {
052        try (Timer timer = startTimer()) {
053            func.run();
054        }
055    }
056
057    /**
058     * Like {@link #time(Runnable)}, but returns the return value of {@code func}.
059     */
060    default <T> T time(Supplier<T> func) {
061        try (Timer timer = startTimer()) {
062            return func.get();
063        }
064    }
065
066    /**
067     * Like {@link #time(Supplier)}, but {@code func} may throw a checked {@code Exception}.
068     */
069    default <T> T timeChecked(Callable<T> func) throws Exception {
070        try (Timer timer = startTimer()) {
071            return func.call();
072        }
073    }
074}