001package io.prometheus.metrics.model.snapshots;
002
003public abstract class DataPointSnapshot {
004    private final Labels labels;
005    private final long createdTimestampMillis;
006    private final long scrapeTimestampMillis;
007
008    protected DataPointSnapshot(Labels labels, long createdTimestampMillis, long scrapeTimestampMillis) {
009        this.labels = labels;
010        this.createdTimestampMillis = createdTimestampMillis;
011        this.scrapeTimestampMillis = scrapeTimestampMillis;
012        validate();
013    }
014
015    private void validate() {
016        if (labels == null) {
017            throw new IllegalArgumentException("Labels cannot be null. Use Labels.EMPTY if there are no labels.");
018        }
019        if (createdTimestampMillis < 0) {
020            throw new IllegalArgumentException("Created timestamp cannot be negative. Use 0 if the metric doesn't have a created timestamp.");
021        }
022        if (scrapeTimestampMillis < 0) {
023            throw new IllegalArgumentException("Scrape timestamp cannot be negative. Use 0 to indicate that the Prometheus server should set the scrape timestamp.");
024        }
025        if (hasCreatedTimestamp() && hasScrapeTimestamp()) {
026            if (scrapeTimestampMillis < createdTimestampMillis) {
027                throw new IllegalArgumentException("The scrape timestamp cannot be before the created timestamp");
028            }
029        }
030    }
031
032    public Labels getLabels() {
033        return labels;
034    }
035
036    public boolean hasScrapeTimestamp() {
037        return scrapeTimestampMillis != 0L;
038    }
039
040    /**
041     * This will only return a reasonable value if {@link #hasScrapeTimestamp()} is true.
042     */
043    public long getScrapeTimestampMillis() {
044        return scrapeTimestampMillis;
045    }
046
047    public boolean hasCreatedTimestamp() {
048        return createdTimestampMillis != 0L;
049    }
050
051    /**
052     * This will only return a reasonable value if {@link #hasCreatedTimestamp()} is true.
053     * Some metrics like Gauge don't have created timestamps. For these metrics {@link #hasCreatedTimestamp()}
054     * is always false.
055     */
056    public long getCreatedTimestampMillis() {
057        return createdTimestampMillis;
058    }
059
060    public static abstract class Builder<T extends Builder<T>> {
061
062        protected Labels labels = Labels.EMPTY;
063        protected long scrapeTimestampMillis = 0L;
064
065        public T labels(Labels labels) {
066            this.labels = labels;
067            return self();
068        }
069
070        /**
071         * In most cases you should not set a scrape timestamp,
072         * because the scrape timestamp is set by the Prometheus server during scraping.
073         * Exceptions include mirroring metrics with given timestamps from other metric sources.
074         */
075        public T scrapeTimestampMillis(long scrapeTimestampMillis) {
076            this.scrapeTimestampMillis = scrapeTimestampMillis;
077            return self();
078        }
079
080        protected abstract T self();
081    }
082}