001package io.prometheus.client;
002
003/**
004 * SimpleTimer, to measure elapsed duration in seconds as a double.
005 *
006 * <p>
007 * This is a helper class intended to measure latencies and encapsulate the conversion to seconds without losing precision.
008 *
009 * <p>
010 * Keep in mind that preferred approaches avoid using this mechanism if possible, since latency metrics broken out by
011 * outcome should be minimized; {@link Summary#startTimer()} and {@link Histogram#startTimer()} are preferred.
012 * Consider moving outcome labels to a separate metric like a counter.
013 *
014 * <p>
015 * Example usage:
016 * <pre>
017 * {@code
018 *   class YourClass {
019 *     static final Summary requestLatency = Summary.build()
020 *         .name("requests_latency_seconds")
021 *         .help("Request latency in seconds.")
022 *         .labelNames("aLabel")
023 *         .register();
024 *
025 *     void processRequest(Request req) {
026 *        SimpleTimer requestTimer = new SimpleTimer();
027 *        try {
028 *          // Your code here.
029 *        } finally {
030 *          requestLatency.labels("aLabelValue").observe(requestTimer.elapsedSeconds());
031 *        }
032 *     }
033 *   }
034 * }
035 * </pre>
036 *
037 */
038public class SimpleTimer {
039  private final long start;
040  static TimeProvider defaultTimeProvider = new TimeProvider();
041  private final TimeProvider timeProvider;
042
043  static class TimeProvider {
044    long nanoTime() {
045      return System.nanoTime();
046    }
047  }
048
049  // Visible for testing.
050  SimpleTimer(TimeProvider timeProvider) {
051    this.timeProvider = timeProvider;
052    start = timeProvider.nanoTime();
053  }
054
055  public SimpleTimer() {
056    this(defaultTimeProvider);
057  }
058
059  /**
060   * @return Measured duration in seconds since {@link SimpleTimer} was constructed.
061   */
062  public double elapsedSeconds() {
063    return elapsedSecondsFromNanos(start, timeProvider.nanoTime());
064  }
065
066  public static double elapsedSecondsFromNanos(long startNanos, long endNanos) {
067      return (endNanos - startNanos) / Collector.NANOSECONDS_PER_SECOND;
068  }
069}