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