001package io.prometheus.client; 002 003import java.util.Arrays; 004import java.util.Collections; 005import java.util.concurrent.ConcurrentHashMap; 006import java.util.Enumeration; 007import java.util.Iterator; 008import java.util.List; 009import java.util.NoSuchElementException; 010import java.util.Set; 011 012/** 013 * A registry of Collectors. 014 * <p> 015 * The majority of users should use the {@link #defaultRegistry}, rather than instantiating their own. 016 * <p> 017 * Creating a registry other than the default is primarily useful for unittests, or 018 * pushing a subset of metrics to the <a href="https://github.com/prometheus/pushgateway">Pushgateway</a> 019 * from batch jobs. 020 */ 021public class CollectorRegistry { 022 /** 023 * The default registry. 024 */ 025 public static final CollectorRegistry defaultRegistry = new CollectorRegistry(); 026 027 private final Set<Collector> collectors = 028 Collections.newSetFromMap(new ConcurrentHashMap<Collector, Boolean>()); 029 030 /** 031 * Register a Collector. 032 * <p> 033 * A collector can be registered to multiple CollectorRegistries. 034 */ 035 public void register(Collector m) { 036 collectors.add(m); 037 } 038 039 /** 040 * Unregister a Collector. 041 */ 042 public void unregister(Collector m) { 043 collectors.remove(m); 044 } 045 /** 046 * Unregister all Collectors. 047 */ 048 public void clear() { 049 collectors.clear(); 050 } 051 052 /** 053 * Enumeration of metrics of all registered collectors. 054 */ 055 public Enumeration<Collector.MetricFamilySamples> metricFamilySamples() { 056 return new MetricFamilySamplesEnumeration(); 057 } 058 class MetricFamilySamplesEnumeration implements Enumeration<Collector.MetricFamilySamples> { 059 060 private final Iterator<Collector> collectorIter = collectors.iterator(); 061 private Iterator<Collector.MetricFamilySamples> metricFamilySamples; 062 private Collector.MetricFamilySamples next; 063 064 MetricFamilySamplesEnumeration() { 065 findNextElement(); 066 } 067 068 private void findNextElement() { 069 if (metricFamilySamples != null && metricFamilySamples.hasNext()) { 070 next = metricFamilySamples.next(); 071 } else { 072 while (collectorIter.hasNext()) { 073 metricFamilySamples = collectorIter.next().collect().iterator(); 074 if (metricFamilySamples.hasNext()) { 075 next = metricFamilySamples.next(); 076 return; 077 } 078 } 079 next = null; 080 } 081 } 082 083 public Collector.MetricFamilySamples nextElement() { 084 Collector.MetricFamilySamples current = next; 085 if (current == null) { 086 throw new NoSuchElementException(); 087 } 088 findNextElement(); 089 return current; 090 } 091 092 public boolean hasMoreElements() { 093 return next != null; 094 } 095 } 096 097 /** 098 * Returns the given value, or null if it doesn't exist. 099 * <p> 100 * This is inefficient, and intended only for use in unittests. 101 */ 102 public Double getSampleValue(String name) { 103 return getSampleValue(name, new String[]{}, new String[]{}); 104 } 105 106 /** 107 * Returns the given value, or null if it doesn't exist. 108 * <p> 109 * This is inefficient, and intended only for use in unittests. 110 */ 111 public Double getSampleValue(String name, String[] labelNames, String[] labelValues) { 112 for (Collector.MetricFamilySamples metricFamilySamples: Collections.list(metricFamilySamples())) { 113 for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) { 114 if (sample.name.equals(name) 115 && Arrays.equals(sample.labelNames.toArray(), labelNames) 116 && Arrays.equals(sample.labelValues.toArray(), labelValues)) { 117 return new Double(sample.value); 118 } 119 } 120 } 121 return null; 122 } 123 124}