001package io.prometheus.metrics.model.snapshots; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.List; 006 007/** Immutable snapshot of a Counter. */ 008public class CounterSnapshot extends MetricSnapshot { 009 010 /** 011 * To create a new {@link CounterSnapshot}, you can either call the constructor directly or use 012 * the builder with {@link CounterSnapshot#builder()}. 013 * 014 * @param metadata the metric name in metadata must not include the {@code _total} suffix. See 015 * {@link MetricMetadata} for more naming conventions. 016 * @param dataPoints the constructor will create a sorted copy of the collection. 017 */ 018 public CounterSnapshot(MetricMetadata metadata, Collection<CounterDataPointSnapshot> dataPoints) { 019 super(metadata, dataPoints); 020 } 021 022 @SuppressWarnings("unchecked") 023 @Override 024 public List<CounterDataPointSnapshot> getDataPoints() { 025 return (List<CounterDataPointSnapshot>) dataPoints; 026 } 027 028 public static class CounterDataPointSnapshot extends DataPointSnapshot { 029 030 private final double value; 031 private final Exemplar exemplar; // may be null 032 033 /** 034 * To create a new {@link CounterDataPointSnapshot}, you can either call the constructor 035 * directly or use the Builder with {@link CounterDataPointSnapshot#builder()}. 036 * 037 * @param value the counter value. Must not be negative. 038 * @param labels must not be null. Use {@link Labels#EMPTY} if there are no labels. 039 * @param exemplar may be null. 040 * @param createdTimestampMillis timestamp (as in {@link System#currentTimeMillis()}) when the 041 * time series (this specific set of labels) was created (or reset to zero). It's optional. 042 * Use {@code 0L} if there is no created timestamp. 043 */ 044 public CounterDataPointSnapshot( 045 double value, Labels labels, Exemplar exemplar, long createdTimestampMillis) { 046 this(value, labels, exemplar, createdTimestampMillis, 0); 047 } 048 049 /** 050 * Constructor with an additional scrape timestamp. This is only useful in rare cases as the 051 * scrape timestamp is usually set by the Prometheus server during scraping. Exceptions include 052 * mirroring metrics with given timestamps from other metric sources. 053 */ 054 @SuppressWarnings("this-escape") 055 public CounterDataPointSnapshot( 056 double value, 057 Labels labels, 058 Exemplar exemplar, 059 long createdTimestampMillis, 060 long scrapeTimestampMillis) { 061 super(labels, createdTimestampMillis, scrapeTimestampMillis); 062 this.value = value; 063 this.exemplar = exemplar; 064 validate(); 065 } 066 067 public double getValue() { 068 return value; 069 } 070 071 /** May be {@code null}. */ 072 public Exemplar getExemplar() { 073 return exemplar; 074 } 075 076 protected void validate() { 077 if (value < 0.0) { 078 throw new IllegalArgumentException(value + ": counters cannot have a negative value"); 079 } 080 } 081 082 public static Builder builder() { 083 return new Builder(); 084 } 085 086 public static class Builder extends DataPointSnapshot.Builder<Builder> { 087 088 private Exemplar exemplar = null; 089 private Double value = null; 090 private long createdTimestampMillis = 0L; 091 092 private Builder() {} 093 094 /** Counter value. This is required. The value must not be negative. */ 095 public Builder value(double value) { 096 this.value = value; 097 return this; 098 } 099 100 public Builder exemplar(Exemplar exemplar) { 101 this.exemplar = exemplar; 102 return this; 103 } 104 105 public Builder createdTimestampMillis(long createdTimestampMillis) { 106 this.createdTimestampMillis = createdTimestampMillis; 107 return this; 108 } 109 110 public CounterDataPointSnapshot build() { 111 if (value == null) { 112 throw new IllegalArgumentException("Missing required field: value is null."); 113 } 114 return new CounterDataPointSnapshot( 115 value, labels, exemplar, createdTimestampMillis, scrapeTimestampMillis); 116 } 117 118 @Override 119 protected Builder self() { 120 return this; 121 } 122 } 123 } 124 125 public static Builder builder() { 126 return new Builder(); 127 } 128 129 public static class Builder extends MetricSnapshot.Builder<Builder> { 130 131 private final List<CounterDataPointSnapshot> dataPoints = new ArrayList<>(); 132 133 private Builder() {} 134 135 /** Add a data point. Can be called multiple times to add multiple data points. */ 136 public Builder dataPoint(CounterDataPointSnapshot dataPoint) { 137 dataPoints.add(dataPoint); 138 return this; 139 } 140 141 @Override 142 public CounterSnapshot build() { 143 return new CounterSnapshot(buildMetadata(), dataPoints); 144 } 145 146 @Override 147 protected Builder self() { 148 return this; 149 } 150 } 151}