001package io.prometheus.metrics.model.registry; 002 003import io.prometheus.metrics.model.snapshots.MetricMetadata; 004import io.prometheus.metrics.model.snapshots.MetricSnapshot; 005import java.util.Set; 006import java.util.function.Predicate; 007import javax.annotation.Nullable; 008 009/** 010 * To be registered with the Prometheus collector registry. See <i>Overall Structure</i> on <a 011 * href="https://prometheus.io/docs/instrumenting/writing_clientlibs/">https://prometheus.io/docs/instrumenting/writing_clientlibs/</a>. 012 */ 013@FunctionalInterface 014public interface Collector { 015 016 /** Called when the Prometheus server scrapes metrics. */ 017 MetricSnapshot 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 MetricSnapshot collect(PrometheusScrapeRequest scrapeRequest) { 024 return collect(); 025 } 026 027 /** 028 * Like {@link #collect()}, but returns {@code null} if {@code includedNames.test(name)} is {@code 029 * false}. 030 * 031 * <p>Override this if there is a more efficient way than first collecting the snapshot and then 032 * discarding it. 033 */ 034 @Nullable 035 default MetricSnapshot collect(Predicate<String> includedNames) { 036 MetricSnapshot result = collect(); 037 if (includedNames.test(result.getMetadata().getPrometheusName())) { 038 return result; 039 } else { 040 return null; 041 } 042 } 043 044 /** 045 * Like {@link #collect(Predicate)}, but with support for multi-target pattern. 046 * 047 * <p>Override this if there is a more efficient way than first collecting the snapshot and then 048 * discarding it. 049 */ 050 @Nullable 051 default MetricSnapshot collect( 052 Predicate<String> includedNames, PrometheusScrapeRequest scrapeRequest) { 053 MetricSnapshot result = collect(scrapeRequest); 054 if (includedNames.test(result.getMetadata().getPrometheusName())) { 055 return result; 056 } else { 057 return null; 058 } 059 } 060 061 /** 062 * This is called in two places: 063 * 064 * <ol> 065 * <li>During registration to check if a metric with that name already exists. 066 * <li>During scrape to check if this collector can be skipped because a name filter is present 067 * and the metric name is excluded. 068 * </ol> 069 * 070 * <p>Returning {@code null} means checks are omitted (registration the metric always succeeds), 071 * and the collector is always scraped (the result is dropped after scraping if a name filter is 072 * present and the metric name is excluded). 073 * 074 * <p>If your metric has a name that does not change at runtime it is a good idea to overwrite 075 * this and return the name. 076 * 077 * <p>All metrics in {@code prometheus-metrics-core} override this. 078 */ 079 @Nullable 080 default String getPrometheusName() { 081 return null; 082 } 083 084 /** 085 * Returns the metric type for registration-time validation. 086 * 087 * <p>This is used to prevent different metric types (e.g., Counter and Gauge) from sharing the 088 * same name. Returning {@code null} means type validation is skipped for this collector. 089 * 090 * <p>Validation is performed only at registration time. If this method returns {@code null}, no 091 * type validation is performed for this collector, and duplicate or conflicting metrics may 092 * result in invalid exposition output. 093 * 094 * @return the metric type, or {@code null} to skip validation 095 */ 096 @Nullable 097 default MetricType getMetricType() { 098 return null; 099 } 100 101 /** 102 * Returns the complete set of label names for this metric. 103 * 104 * <p>This includes both dynamic label names (specified in {@code labelNames()}) and constant 105 * label names (specified in {@code constLabels()}). Label names are normalized using Prometheus 106 * naming conventions. 107 * 108 * <p>This is used for registration-time validation to prevent duplicate label schemas for the 109 * same metric name. Two collectors with the same name and type can coexist if they have different 110 * label name sets. 111 * 112 * <p>Returning {@code null} is treated as an empty label set: the registry normalizes it to 113 * {@code Collections.emptySet()} and performs full label-schema validation and duplicate 114 * detection. Two collectors with the same name, type, and {@code null} (or empty) label names are 115 * considered duplicate and registration of the second will fail. 116 * 117 * @return the set of all label names, or {@code null} (treated as empty) for a metric with no 118 * labels 119 */ 120 @Nullable 121 default Set<String> getLabelNames() { 122 return null; 123 } 124 125 /** 126 * Returns the metric metadata (name, help, unit) for registration-time validation. 127 * 128 * <p>When non-null, the registry uses this to validate that metrics with the same name have 129 * consistent help and unit. Returning {@code null} means help/unit validation is skipped for this 130 * collector. 131 * 132 * @return the metric metadata, or {@code null} to skip help/unit validation 133 */ 134 @Nullable 135 default MetricMetadata getMetadata() { 136 return null; 137 } 138}