001package io.prometheus.client; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Map; 006 007/** 008 * Counter metric, to track counts of events or running totals. 009 * <p> 010 * Example of Counters include: 011 * <ul> 012 * <li>Number of requests processed</li> 013 * <li>Number of items that were inserted into a queue</li> 014 * <li>Total amount of data a system has processed</li> 015 * </ul> 016 * 017 * Counters can only go up (and be reset), if your use case can go down you should use a {@link Gauge} instead. 018 * Use the <code>rate()</code> function in Prometheus to calculate the rate of increase of a Counter. 019 * By convention, the names of Counters are suffixed by <code>_total</code>. 020 * 021 * <p> 022 * An example Counter: 023 * <pre> 024 * {@code 025 * class YourClass { 026 * static final Counter requests = Counter.build() 027 * .name("requests_total").help("Total requests.").register(); 028 * static final Counter failedRequests = Counter.build() 029 * .name("requests_failed_total").help("Total failed requests.").register(); 030 * 031 * void processRequest() { 032 * requests.inc(); 033 * try { 034 * // Your code here. 035 * } catch (Exception e) { 036 * failedRequests.inc(); 037 * throw e; 038 * } 039 * } 040 * } 041 * } 042 * </pre> 043 * 044 * <p> 045 * You can also use labels to track different types of metric: 046 * <pre> 047 * {@code 048 * class YourClass { 049 * static final Counter requests = Counter.build() 050 * .name("requests_total").help("Total requests.") 051 * .labelNames("method").register(); 052 * 053 * void processGetRequest() { 054 * requests.labels("get").inc(); 055 * // Your code here. 056 * } 057 * void processPostRequest() { 058 * requests.labels("post").inc(); 059 * // Your code here. 060 * } 061 * } 062 * } 063 * </pre> 064 * These can be aggregated and processed together much more easily in the Promtheus 065 * server than individual metrics for each labelset. 066 */ 067public class Counter extends SimpleCollector<Counter.Child> { 068 069 Counter(Builder b) { 070 super(b); 071 } 072 073 public static class Builder extends SimpleCollector.Builder<Builder, Counter> { 074 @Override 075 public Counter create() { 076 return new Counter(this); 077 } 078 } 079 080 /** 081 * Return a Builder to allow configuration of a new Counter. 082 */ 083 public static Builder build() { 084 return new Builder(); 085 } 086 087 @Override 088 protected Child newChild() { 089 return new Child(); 090 } 091 092 /** 093 * The value of a single Counter. 094 * <p> 095 * <em>Warning:</em> References to a Child become invalid after using 096 * {@link SimpleCollector#remove} or {@link SimpleCollector#clear}, 097 */ 098 public static class Child { 099 private final DoubleAdder value = new DoubleAdder(); 100 /** 101 * Increment the counter by 1. 102 */ 103 public void inc() { 104 inc(1); 105 } 106 /** 107 * Increment the counter by the given amount. 108 * @throws IllegalArgumentException If amt is negative. 109 */ 110 public void inc(double amt) { 111 if (amt < 0) { 112 throw new IllegalArgumentException("Amount to increment must be non-negative."); 113 } 114 value.add(amt); 115 } 116 /** 117 * Get the value of the counter. 118 */ 119 public double get() { 120 return value.sum(); 121 } 122 } 123 124 // Convenience methods. 125 /** 126 * Increment the counter with no labels by 1. 127 */ 128 public void inc() { 129 inc(1); 130 } 131 /** 132 * Increment the counter with no labels by the given amount. 133 * @throws IllegalArgumentException If amt is negative. 134 */ 135 public void inc(double amt) { 136 noLabelsChild.inc(amt); 137 } 138 139 @Override 140 public List<MetricFamilySamples> collect() { 141 List<MetricFamilySamples.Sample> samples = new ArrayList<MetricFamilySamples.Sample>(); 142 for(Map.Entry<List<String>, Child> c: children.entrySet()) { 143 samples.add(new MetricFamilySamples.Sample(fullname, labelNames, c.getKey(), c.getValue().get())); 144 } 145 MetricFamilySamples mfs = new MetricFamilySamples(fullname, Type.COUNTER, help, samples); 146 147 List<MetricFamilySamples> mfsList = new ArrayList<MetricFamilySamples>(); 148 mfsList.add(mfs); 149 return mfsList; 150 } 151}