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