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