001package io.prometheus.metrics.model.snapshots; 002 003import io.prometheus.metrics.annotations.StableApi; 004import io.prometheus.metrics.model.registry.MetricType; 005import java.util.Collection; 006import java.util.Collections; 007import java.util.LinkedHashSet; 008import java.util.Set; 009import javax.annotation.Nullable; 010 011/** Registration-time descriptor for a metric family. */ 012@StableApi 013public final class MetricFamilyDescriptor { 014 015 private final MetricType type; 016 private final MetricMetadata metadata; 017 private final Set<String> labelNames; 018 019 private MetricFamilyDescriptor( 020 MetricType type, MetricMetadata metadata, Collection<String> labelNames) { 021 if (type == null) { 022 throw new IllegalArgumentException("Missing required field: type is null"); 023 } 024 if (metadata == null) { 025 throw new IllegalArgumentException("Missing required field: metadata is null"); 026 } 027 if (labelNames == null) { 028 throw new IllegalArgumentException("Missing required field: labelNames is null"); 029 } 030 this.type = type; 031 this.metadata = metadata; 032 this.labelNames = Collections.unmodifiableSet(new LinkedHashSet<>(labelNames)); 033 } 034 035 public static MetricFamilyDescriptor of(MetricType type, MetricMetadata metadata) { 036 return of(type, metadata, Collections.emptySet()); 037 } 038 039 public static MetricFamilyDescriptor of( 040 MetricType type, MetricMetadata metadata, Collection<String> labelNames) { 041 return new MetricFamilyDescriptor(type, metadata, labelNames); 042 } 043 044 public static Builder<?> of(MetricType type, String name) { 045 switch (type) { 046 case COUNTER: 047 return counter(name); 048 case GAUGE: 049 return gauge(name); 050 case HISTOGRAM: 051 return histogram(name); 052 case SUMMARY: 053 return summary(name); 054 case INFO: 055 return info(name); 056 case STATESET: 057 return stateSet(name); 058 case UNKNOWN: 059 default: 060 return unknown(name); 061 } 062 } 063 064 public static CounterBuilder counter(String name) { 065 return new CounterBuilder().name(name); 066 } 067 068 public static GaugeBuilder gauge(String name) { 069 return new GaugeBuilder().name(name); 070 } 071 072 public static HistogramBuilder histogram(String name) { 073 return new HistogramBuilder().name(name); 074 } 075 076 public static SummaryBuilder summary(String name) { 077 return new SummaryBuilder().name(name); 078 } 079 080 public static InfoBuilder info(String name) { 081 return new InfoBuilder().name(name); 082 } 083 084 public static StateSetBuilder stateSet(String name) { 085 return new StateSetBuilder().name(name); 086 } 087 088 public static UnknownBuilder unknown(String name) { 089 return new UnknownBuilder().name(name); 090 } 091 092 public MetricType getType() { 093 return type; 094 } 095 096 public MetricMetadata getMetadata() { 097 return metadata; 098 } 099 100 public Set<String> getLabelNames() { 101 return labelNames; 102 } 103 104 public String getPrometheusName() { 105 return metadata.getPrometheusName(); 106 } 107 108 public abstract static class Builder<T extends Builder<T>> { 109 110 @Nullable protected String name; 111 @Nullable protected String help; 112 @Nullable protected Unit unit; 113 protected final Set<String> labelNames = new LinkedHashSet<>(); 114 115 public T name(String name) { 116 this.name = name; 117 return self(); 118 } 119 120 public T help(String help) { 121 if (help == null) { 122 throw new IllegalArgumentException("Missing required field: help is null"); 123 } 124 this.help = help; 125 return self(); 126 } 127 128 public T unit(Unit unit) { 129 if (unit == null) { 130 throw new IllegalArgumentException("Missing required field: unit is null"); 131 } 132 this.unit = unit; 133 return self(); 134 } 135 136 public T labelName(String labelName) { 137 this.labelNames.add(PrometheusNaming.prometheusName(labelName)); 138 return self(); 139 } 140 141 public T labelNames(String... labelNames) { 142 for (String labelName : labelNames) { 143 labelName(labelName); 144 } 145 return self(); 146 } 147 148 public T labelNames(Collection<String> labelNames) { 149 for (String labelName : labelNames) { 150 labelName(labelName); 151 } 152 return self(); 153 } 154 155 public MetricFamilyDescriptor build() { 156 return new MetricFamilyDescriptor(getType(), buildMetadata(), labelNames); 157 } 158 159 protected MetricMetadata buildMetadata() { 160 if (name == null) { 161 throw new IllegalArgumentException("Missing required field: name is null"); 162 } 163 return MetricMetadataSupport.metricMetadata(name, help, unit); 164 } 165 166 protected abstract MetricType getType(); 167 168 protected abstract T self(); 169 } 170 171 public static final class CounterBuilder extends Builder<CounterBuilder> { 172 173 @Override 174 protected MetricMetadata buildMetadata() { 175 if (name == null) { 176 throw new IllegalArgumentException("Missing required field: name is null"); 177 } 178 return MetricMetadataSupport.counterMetadata(name, help, unit); 179 } 180 181 @Override 182 protected MetricType getType() { 183 return MetricType.COUNTER; 184 } 185 186 @Override 187 protected CounterBuilder self() { 188 return this; 189 } 190 } 191 192 public static final class GaugeBuilder extends Builder<GaugeBuilder> { 193 194 @Override 195 protected MetricType getType() { 196 return MetricType.GAUGE; 197 } 198 199 @Override 200 protected GaugeBuilder self() { 201 return this; 202 } 203 } 204 205 public static final class HistogramBuilder extends Builder<HistogramBuilder> { 206 207 @Override 208 protected MetricType getType() { 209 return MetricType.HISTOGRAM; 210 } 211 212 @Override 213 protected HistogramBuilder self() { 214 return this; 215 } 216 } 217 218 public static final class SummaryBuilder extends Builder<SummaryBuilder> { 219 220 @Override 221 protected MetricType getType() { 222 return MetricType.SUMMARY; 223 } 224 225 @Override 226 protected SummaryBuilder self() { 227 return this; 228 } 229 } 230 231 public static final class InfoBuilder extends Builder<InfoBuilder> { 232 233 @Override 234 public InfoBuilder unit(Unit unit) { 235 if (unit == null) { 236 throw new IllegalArgumentException("Missing required field: unit is null"); 237 } 238 throw new IllegalArgumentException("Info metric cannot have a unit."); 239 } 240 241 @Override 242 protected MetricMetadata buildMetadata() { 243 if (name == null) { 244 throw new IllegalArgumentException("Missing required field: name is null"); 245 } 246 return MetricMetadataSupport.infoMetadata(name, help); 247 } 248 249 @Override 250 protected MetricType getType() { 251 return MetricType.INFO; 252 } 253 254 @Override 255 protected InfoBuilder self() { 256 return this; 257 } 258 } 259 260 public static final class StateSetBuilder extends Builder<StateSetBuilder> { 261 262 @Override 263 public StateSetBuilder unit(Unit unit) { 264 if (unit == null) { 265 throw new IllegalArgumentException("Missing required field: unit is null"); 266 } 267 throw new IllegalArgumentException("State set metric cannot have a unit."); 268 } 269 270 @Override 271 protected MetricType getType() { 272 return MetricType.STATESET; 273 } 274 275 @Override 276 protected StateSetBuilder self() { 277 return this; 278 } 279 } 280 281 public static final class UnknownBuilder extends Builder<UnknownBuilder> { 282 283 @Override 284 protected MetricType getType() { 285 return MetricType.UNKNOWN; 286 } 287 288 @Override 289 protected UnknownBuilder self() { 290 return this; 291 } 292 } 293}