001package io.prometheus.metrics.core.metrics; 002 003import io.prometheus.metrics.annotations.StableApi; 004import io.prometheus.metrics.config.PrometheusProperties; 005import io.prometheus.metrics.model.registry.Collector; 006import io.prometheus.metrics.model.registry.PrometheusRegistry; 007import io.prometheus.metrics.model.snapshots.Label; 008import io.prometheus.metrics.model.snapshots.Labels; 009import io.prometheus.metrics.model.snapshots.MetricSnapshot; 010import java.util.ArrayList; 011import java.util.List; 012 013/** Common base class for all metrics. */ 014@StableApi 015public abstract class Metric implements Collector { 016 017 protected final Labels constLabels; 018 019 protected Metric(Builder<?, ?> builder) { 020 this.constLabels = builder.constLabels; 021 } 022 023 @Override 024 public abstract MetricSnapshot collect(); 025 026 protected abstract static class Builder<B extends Builder<B, M>, M extends Metric> { 027 028 protected final List<String> illegalLabelNames; 029 protected final PrometheusProperties properties; 030 protected Labels constLabels = Labels.EMPTY; 031 032 protected Builder(List<String> illegalLabelNames, PrometheusProperties properties) { 033 this.illegalLabelNames = new ArrayList<>(illegalLabelNames); 034 this.properties = properties; 035 } 036 037 // ConstLabels are only used rarely. In particular, do not use them to 038 // attach the same labels to all your metrics. Those use cases are 039 // better covered by target labels set by the scraping Prometheus 040 // server, or by one specific metric (e.g. a build_info or a 041 // machine_role metric). See also 042 // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels 043 public B constLabels(Labels constLabels) { 044 for (Label label : constLabels) { // NPE if constLabels is null 045 if (illegalLabelNames.contains(label.getName())) { 046 throw new IllegalArgumentException( 047 label.getName() + ": illegal label name for this metric type"); 048 } 049 } 050 this.constLabels = constLabels; 051 return self(); 052 } 053 054 public M register() { 055 return register(PrometheusRegistry.defaultRegistry); 056 } 057 058 public M register(PrometheusRegistry registry) { 059 M metric = build(); 060 registry.register(metric); 061 return metric; 062 } 063 064 public abstract M build(); 065 066 protected abstract B self(); 067 } 068}