001package io.prometheus.metrics.core.datapoints;
002
003import io.prometheus.metrics.model.snapshots.Labels;
004
005/**
006 * Represents a single counter data point, i.e. a single line for a counter metric in Prometheus
007 * text format.
008 *
009 * <p>Example usage:
010 *
011 * <pre>{@code
012 * Counter counter = Counter.builder()
013 *     .name("tasks_total")
014 *     .labelNames("status")
015 *     .register();
016 * CounterDataPoint newTasks = counter.labelValues("new");
017 * CounterDataPoint pendingTasks = counter.labelValues("pending");
018 * CounterDataPoint completedTasks = counter.labelValues("completed");
019 * }</pre>
020 *
021 * <p>Using {@code DataPoint} directly improves performance. If you increment a counter like this:
022 *
023 * <pre>{@code
024 * counter.labelValues("pending").inc();
025 * }</pre>
026 *
027 * the label value {@code "pending"} needs to be looked up every single time. Using the {@code
028 * CounterDataPoint} like this:
029 *
030 * <pre>{@code
031 * CounterDataPoint pendingTasks = counter.labelValues("pending");
032 * pendingTasks.inc();
033 * }</pre>
034 *
035 * allows you to look up the label value only once, and then use the {@code CounterDataPoint}
036 * directly. This is a worthwhile performance improvement when instrumenting a performance-critical
037 * code path.
038 *
039 * <p>If you have a counter without labels like this:
040 *
041 * <pre>{@code
042 * Counter counterWithoutLabels = Counter.builder()
043 *     .name("events_total")
044 *     .register();
045 * }</pre>
046 *
047 * You can use it as a {@code CounterDataPoint} directly. So the following:
048 *
049 * <pre>{@code
050 * CounterDataPoint counterData = counterWithoutLabels.labelValues(); // empty label values
051 * }</pre>
052 *
053 * is equivalent to
054 *
055 * <pre>{@code
056 * CounterDataPoint counterData = counterWithoutLabels;
057 * }</pre>
058 */
059public interface CounterDataPoint extends DataPoint {
060
061  /** Add one. */
062  default void inc() {
063    inc(1L);
064  }
065
066  /**
067   * Add {@code amount}. Throws an {@link IllegalArgumentException} if {@code amount} is negative.
068   */
069  default void inc(long amount) {
070    inc((double) amount);
071  }
072
073  /**
074   * Add {@code amount}. Throws an {@link IllegalArgumentException} if {@code amount} is negative.
075   */
076  void inc(double amount);
077
078  /** Add one, and create a custom exemplar with the given labels. */
079  default void incWithExemplar(Labels labels) {
080    incWithExemplar(1.0, labels);
081  }
082
083  /**
084   * Add {@code amount}, and create a custom exemplar with the given labels. Throws an {@link
085   * IllegalArgumentException} if {@code amount} is negative.
086   */
087  default void incWithExemplar(long amount, Labels labels) {
088    inc((double) amount);
089  }
090
091  /**
092   * Add {@code amount}, and create a custom exemplar with the given labels. Throws an {@link
093   * IllegalArgumentException} if {@code amount} is negative.
094   */
095  void incWithExemplar(double amount, Labels labels);
096
097  /** Get the current value. */
098  double get();
099
100  /** Get the current value as a {@code long}. Decimal places will be discarded. */
101  long getLongValue();
102}