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