001package io.prometheus.metrics.model.snapshots; 002 003import java.util.ArrayList; 004import java.util.Arrays; 005import java.util.Collection; 006import java.util.HashSet; 007import java.util.Iterator; 008import java.util.List; 009import java.util.Set; 010import java.util.stream.Stream; 011 012import static io.prometheus.metrics.model.snapshots.PrometheusNaming.prometheusName; 013import static java.util.Collections.unmodifiableList; 014import static java.util.Comparator.comparing; 015 016/** 017 * Immutable list of metric snapshots. 018 */ 019public class MetricSnapshots implements Iterable<MetricSnapshot> { 020 021 private final List<MetricSnapshot> snapshots; 022 023 /** 024 * See {@link #MetricSnapshots(Collection)} 025 */ 026 public MetricSnapshots(MetricSnapshot... snapshots) { 027 this(Arrays.asList(snapshots)); 028 } 029 030 /** 031 * To create MetricSnapshots, you can either call the constructor directly 032 * or use {@link #builder()}. 033 * 034 * @param snapshots the constructor creates a sorted copy of snapshots. 035 * @throws IllegalArgumentException if snapshots contains duplicate metric names. 036 * To avoid duplicate metric names use {@link #builder()} and check 037 * {@link Builder#containsMetricName(String)} before calling 038 * {@link Builder#metricSnapshot(MetricSnapshot)}. 039 */ 040 public MetricSnapshots(Collection<MetricSnapshot> snapshots) { 041 List<MetricSnapshot> list = new ArrayList<>(snapshots); 042 list.sort(comparing(s -> s.getMetadata().getPrometheusName())); 043 for (int i = 0; i < snapshots.size() - 1; i++) { 044 if (list.get(i).getMetadata().getPrometheusName().equals(list.get(i + 1).getMetadata().getPrometheusName())) { 045 throw new IllegalArgumentException(list.get(i).getMetadata().getPrometheusName() + ": duplicate metric name"); 046 } 047 } 048 this.snapshots = unmodifiableList(list); 049 } 050 051 public static MetricSnapshots of(MetricSnapshot... snapshots) { 052 return new MetricSnapshots(snapshots); 053 } 054 055 @Override 056 public Iterator<MetricSnapshot> iterator() { 057 return snapshots.iterator(); 058 } 059 060 public int size() { 061 return snapshots.size(); 062 } 063 064 public MetricSnapshot get(int i) { 065 return snapshots.get(i); 066 } 067 068 public Stream<MetricSnapshot> stream() { 069 return snapshots.stream(); 070 } 071 072 public static Builder builder() { 073 return new Builder(); 074 } 075 076 public static class Builder { 077 078 private final List<MetricSnapshot> snapshots = new ArrayList<>(); 079 private final Set<String> prometheusNames = new HashSet<>(); 080 081 private Builder() { 082 } 083 084 public boolean containsMetricName(String name) { 085 if (name == null) { 086 return false; 087 } 088 String prometheusName = prometheusName(name); 089 return prometheusNames.contains(prometheusName); 090 } 091 092 /** 093 * Add a metric snapshot. Call multiple times to add multiple metric snapshots. 094 */ 095 public Builder metricSnapshot(MetricSnapshot snapshot) { 096 snapshots.add(snapshot); 097 prometheusNames.add(snapshot.getMetadata().getPrometheusName()); 098 return this; 099 } 100 101 public MetricSnapshots build() { 102 return new MetricSnapshots(snapshots); 103 } 104 } 105}