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