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