All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.mnemonic.commons.metrics.TimerContext Maven / Gradle / Ivy

package no.mnemonic.commons.metrics;

import no.mnemonic.commons.logging.Logger;
import no.mnemonic.commons.logging.Logging;

import java.time.Clock;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * A timer context is a helper to register timing metrics for your code.
 *
 * Example:
 * 
 *   LongAdder executionTimeInMillis = new LongAdder();
 *   try (TimerContext ignored = TimerContext.timerMillis(executionTimeInMillis::add) {
 *     //do some work
 *   }
 *   System.out.println("Milliseconds required for work: " + executionTimeInMillis);
 * 
 *
 * For long-living worker components, a good use case is to define a LongAdder in your component instance
 * for measuring accumulated time for an operation, by appending to it for every execution.
 */
public class TimerContext implements AutoCloseable {

  private static final Logger LOGGER = Logging.getLogger(TimerContext.class);
  private static Clock clock = Clock.systemUTC();

  enum MetricType {

    millis(clock::millis),
    nanos(() -> TimeUnit.MILLISECONDS.toNanos(clock.millis())),
    seconds(() -> TimeUnit.MILLISECONDS.toSeconds(clock.millis()));

    private final Supplier currentSupplier;

    MetricType(Supplier currentSupplier) {
      this.currentSupplier = currentSupplier;
    }

    public long getCurrent() {
      return currentSupplier.get();
    }
  }

  private final Consumer metric;
  private final MetricType type;
  private final long startTime;

  private TimerContext(Consumer metric, MetricType type) {
    if (metric == null) throw new IllegalArgumentException("Metric not set");
    if (type == null) throw new IllegalArgumentException("Type not set");
    this.metric = metric;
    this.type = type;
    this.startTime = type.getCurrent();
  }

  @Override
  public void close() {
    try {
      metric.accept(type.getCurrent() - startTime);
    } catch (Throwable e) {
      LOGGER.warning(e, "Error updating timer metric");
    }
  }

  public static TimerContext timerMillis(Consumer metric) {
    return new TimerContext(metric, MetricType.millis);
  }

  public static TimerContext timerNanos(Consumer metric) {
    return new TimerContext(metric, MetricType.nanos);
  }

  public static TimerContext timerSeconds(Consumer metric) {
    return new TimerContext(metric, MetricType.seconds);
  }

  static void setClock(Clock clock) {
    TimerContext.clock = clock;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy