001package io.prometheus.metrics.model.registry; 002 003import io.prometheus.metrics.model.snapshots.MetricMetadata; 004import io.prometheus.metrics.model.snapshots.MetricSnapshot; 005import io.prometheus.metrics.model.snapshots.MetricSnapshots; 006import java.util.Collections; 007import java.util.List; 008import java.util.Set; 009import java.util.function.Predicate; 010import javax.annotation.Nullable; 011 012/** Like {@link Collector}, but collecting multiple Snapshots at once. */ 013@FunctionalInterface 014public interface MultiCollector { 015 016 /** Called when the Prometheus server scrapes metrics. */ 017 MetricSnapshots collect(); 018 019 /** 020 * Provides Collector with the details of the request issued by Prometheus to allow multi-target 021 * pattern implementation Override to implement request dependent logic to provide MetricSnapshot 022 */ 023 default MetricSnapshots collect(PrometheusScrapeRequest scrapeRequest) { 024 return collect(); 025 } 026 027 /** 028 * Like {@link #collect()}, but returns only the snapshots where {@code includedNames.test(name)} 029 * is {@code true}. 030 * 031 * <p>Override this if there is a more efficient way than first collecting all snapshot and then 032 * discarding the excluded ones. 033 */ 034 default MetricSnapshots collect(Predicate<String> includedNames) { 035 return collect(includedNames, null); 036 } 037 038 /** 039 * Like {@link #collect(Predicate)}, but with support for multi-target pattern. 040 * 041 * <p>Override this if there is a more efficient way than first collecting the snapshot and then 042 * discarding it. 043 */ 044 default MetricSnapshots collect( 045 Predicate<String> includedNames, @Nullable PrometheusScrapeRequest scrapeRequest) { 046 MetricSnapshots allSnapshots = scrapeRequest == null ? collect() : collect(scrapeRequest); 047 MetricSnapshots.Builder result = MetricSnapshots.builder(); 048 for (MetricSnapshot snapshot : allSnapshots) { 049 if (includedNames.test(snapshot.getMetadata().getPrometheusName())) { 050 result.metricSnapshot(snapshot); 051 } 052 } 053 return result.build(); 054 } 055 056 /** 057 * This is called in two places: 058 * 059 * <ol> 060 * <li>During registration to check if a metric with that name already exists. 061 * <li>During scrape to check if the collector can be skipped because a name filter is present 062 * and all names are excluded. 063 * </ol> 064 * 065 * <p>Returning an empty list means checks are omitted (registration metric always succeeds), and 066 * the collector is always scraped (if a name filter is present and all names are excluded the 067 * result is dropped). 068 * 069 * <p>If your collector returns a constant list of metrics that have names that do not change at 070 * runtime it is a good idea to overwrite this and return the names. 071 */ 072 default List<String> getPrometheusNames() { 073 return Collections.emptyList(); 074 } 075 076 /** 077 * Returns the metric type for the given Prometheus name. 078 * 079 * <p>This is used for per-name type validation during registration. Returning {@code null} means 080 * type validation is skipped for that specific metric name. 081 * 082 * <p>Validation is performed only at registration time. If this method returns {@code null}, no 083 * type validation is performed for that name, and duplicate or conflicting metrics may result in 084 * invalid exposition output. 085 * 086 * @param prometheusName the Prometheus metric name 087 * @return the metric type for the given name, or {@code null} to skip validation 088 */ 089 @Nullable 090 default MetricType getMetricType(String prometheusName) { 091 return null; 092 } 093 094 /** 095 * Returns the complete set of label names for the given Prometheus name. 096 * 097 * <p>This includes both dynamic label names and constant label names. Label names are normalized 098 * using Prometheus naming conventions (dots converted to underscores). 099 * 100 * <p>This is used for per-name label schema validation during registration. Two collectors with 101 * the same name and type can coexist if they have different label name sets. 102 * 103 * <p>Returning {@code null} is treated as an empty label set: the registry normalizes it to 104 * {@code Collections.emptySet()} and performs full label-schema validation and duplicate 105 * detection. Two collectors with the same name, type, and {@code null} (or empty) label names are 106 * considered duplicate and registration of the second will fail. 107 * 108 * @param prometheusName the Prometheus metric name 109 * @return the set of all label names for the given name, or {@code null} (treated as empty) for a 110 * metric with no labels 111 */ 112 @Nullable 113 default Set<String> getLabelNames(String prometheusName) { 114 return null; 115 } 116 117 /** 118 * Returns the metric metadata (name, help, unit) for the given Prometheus name. 119 * 120 * <p>When non-null, the registry uses this to validate that metrics with the same name have 121 * consistent help and unit. Returning {@code null} means help/unit validation is skipped for that 122 * name. 123 * 124 * @param prometheusName the Prometheus metric name 125 * @return the metric metadata for that name, or {@code null} to skip help/unit validation 126 */ 127 @Nullable 128 default MetricMetadata getMetadata(String prometheusName) { 129 return null; 130 } 131}