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}