001package io.prometheus.metrics.model.snapshots; 002 003import static io.prometheus.metrics.model.snapshots.PrometheusNaming.prometheusName; 004import static java.util.Collections.unmodifiableList; 005import static java.util.Comparator.comparing; 006 007import java.util.ArrayList; 008import java.util.Arrays; 009import java.util.Collection; 010import java.util.HashSet; 011import java.util.Iterator; 012import java.util.List; 013import java.util.Set; 014import java.util.stream.Stream; 015 016/** Immutable list of metric snapshots. */ 017public class MetricSnapshots implements Iterable<MetricSnapshot> { 018 019 private final List<MetricSnapshot> snapshots; 020 021 /** See {@link #MetricSnapshots(Collection)} */ 022 public MetricSnapshots(MetricSnapshot... snapshots) { 023 this(Arrays.asList(snapshots)); 024 } 025 026 /** 027 * To create MetricSnapshots, you can either call the constructor directly or use {@link 028 * #builder()}. 029 * 030 * @param snapshots the constructor creates a sorted copy of snapshots. 031 * @throws IllegalArgumentException if snapshots contains duplicate metric names. To avoid 032 * duplicate metric names use {@link #builder()} and check {@link 033 * Builder#containsMetricName(String)} before calling {@link 034 * Builder#metricSnapshot(MetricSnapshot)}. 035 */ 036 public MetricSnapshots(Collection<MetricSnapshot> snapshots) { 037 List<MetricSnapshot> list = new ArrayList<>(snapshots); 038 list.sort(comparing(s -> s.getMetadata().getPrometheusName())); 039 for (int i = 0; i < snapshots.size() - 1; i++) { 040 if (list.get(i) 041 .getMetadata() 042 .getPrometheusName() 043 .equals(list.get(i + 1).getMetadata().getPrometheusName())) { 044 throw new IllegalArgumentException( 045 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 public boolean containsMetricName(String name) { 084 if (name == null) { 085 return false; 086 } 087 String prometheusName = prometheusName(name); 088 return prometheusNames.contains(prometheusName); 089 } 090 091 /** Add a metric snapshot. Call multiple times to add multiple metric snapshots. */ 092 public Builder metricSnapshot(MetricSnapshot snapshot) { 093 snapshots.add(snapshot); 094 prometheusNames.add(snapshot.getMetadata().getPrometheusName()); 095 return this; 096 } 097 098 public MetricSnapshots build() { 099 return new MetricSnapshots(snapshots); 100 } 101 } 102}