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