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