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