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}