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}