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