Skip to content

Commit 8148c35

Browse files
committed
cleanup
1 parent 44d01a1 commit 8148c35

File tree

10 files changed

+118
-102
lines changed

10 files changed

+118
-102
lines changed

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Counter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.prometheus.metrics.core.datapoints.CounterDataPoint;
66
import io.prometheus.metrics.core.exemplars.ExemplarSampler;
77
import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig;
8+
import io.prometheus.metrics.model.registry.MetricType;
89
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
910
import io.prometheus.metrics.model.snapshots.Exemplar;
1011
import io.prometheus.metrics.model.snapshots.Labels;
@@ -93,8 +94,8 @@ protected CounterSnapshot collect(List<Labels> labels, List<DataPoint> metricDat
9394
}
9495

9596
@Override
96-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
97-
return io.prometheus.metrics.model.registry.MetricType.COUNTER;
97+
public MetricType getMetricType() {
98+
return MetricType.COUNTER;
9899
}
99100

100101
@Override

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Gauge.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.prometheus.metrics.core.datapoints.GaugeDataPoint;
66
import io.prometheus.metrics.core.exemplars.ExemplarSampler;
77
import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig;
8+
import io.prometheus.metrics.model.registry.MetricType;
89
import io.prometheus.metrics.model.snapshots.Exemplar;
910
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
1011
import io.prometheus.metrics.model.snapshots.Labels;
@@ -95,8 +96,8 @@ protected GaugeSnapshot collect(List<Labels> labels, List<DataPoint> metricData)
9596
}
9697

9798
@Override
98-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
99-
return io.prometheus.metrics.model.registry.MetricType.GAUGE;
99+
public MetricType getMetricType() {
100+
return MetricType.GAUGE;
100101
}
101102

102103
@Override

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.prometheus.metrics.core.exemplars.ExemplarSampler;
88
import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig;
99
import io.prometheus.metrics.core.util.Scheduler;
10+
import io.prometheus.metrics.model.registry.MetricType;
1011
import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
1112
import io.prometheus.metrics.model.snapshots.Exemplars;
1213
import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
@@ -641,8 +642,8 @@ public HistogramSnapshot collect() {
641642
}
642643

643644
@Override
644-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
645-
return io.prometheus.metrics.model.registry.MetricType.HISTOGRAM;
645+
public MetricType getMetricType() {
646+
return MetricType.HISTOGRAM;
646647
}
647648

648649
@Override

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Info.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.prometheus.metrics.core.metrics;
22

33
import io.prometheus.metrics.config.PrometheusProperties;
4+
import io.prometheus.metrics.model.registry.MetricType;
45
import io.prometheus.metrics.model.snapshots.InfoSnapshot;
56
import io.prometheus.metrics.model.snapshots.Labels;
67
import io.prometheus.metrics.model.snapshots.Unit;
@@ -106,8 +107,8 @@ public InfoSnapshot collect() {
106107
}
107108

108109
@Override
109-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
110-
return io.prometheus.metrics.model.registry.MetricType.INFO;
110+
public MetricType getMetricType() {
111+
return MetricType.INFO;
111112
}
112113

113114
public static Builder builder() {

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StateSet.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io.prometheus.metrics.config.PrometheusProperties;
66
import io.prometheus.metrics.core.datapoints.StateSetDataPoint;
7+
import io.prometheus.metrics.model.registry.MetricType;
78
import io.prometheus.metrics.model.snapshots.Labels;
89
import io.prometheus.metrics.model.snapshots.StateSetSnapshot;
910
import java.util.ArrayList;
@@ -74,8 +75,8 @@ public StateSetSnapshot collect() {
7475
}
7576

7677
@Override
77-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
78-
return io.prometheus.metrics.model.registry.MetricType.STATESET;
78+
public MetricType getMetricType() {
79+
return MetricType.STATESET;
7980
}
8081

8182
@Override

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Summary.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.prometheus.metrics.core.datapoints.DistributionDataPoint;
88
import io.prometheus.metrics.core.exemplars.ExemplarSampler;
99
import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfig;
10+
import io.prometheus.metrics.model.registry.MetricType;
1011
import io.prometheus.metrics.model.snapshots.Exemplars;
1112
import io.prometheus.metrics.model.snapshots.Labels;
1213
import io.prometheus.metrics.model.snapshots.Quantile;
@@ -110,8 +111,8 @@ public SummarySnapshot collect() {
110111
}
111112

112113
@Override
113-
public io.prometheus.metrics.model.registry.MetricType getMetricType() {
114-
return io.prometheus.metrics.model.registry.MetricType.SUMMARY;
114+
public MetricType getMetricType() {
115+
return MetricType.SUMMARY;
115116
}
116117

117118
@Override

prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
package io.prometheus.metrics.expositionformats;
22

33
import io.prometheus.metrics.config.EscapingScheme;
4-
import io.prometheus.metrics.model.snapshots.*;
4+
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
5+
import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
6+
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
7+
import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
8+
import io.prometheus.metrics.model.snapshots.InfoSnapshot;
9+
import io.prometheus.metrics.model.snapshots.Labels;
10+
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
11+
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
12+
import io.prometheus.metrics.model.snapshots.PrometheusNaming;
13+
import io.prometheus.metrics.model.snapshots.SnapshotEscaper;
14+
import io.prometheus.metrics.model.snapshots.StateSetSnapshot;
15+
import io.prometheus.metrics.model.snapshots.SummarySnapshot;
16+
import io.prometheus.metrics.model.snapshots.UnknownSnapshot;
517

618
import java.io.IOException;
719
import java.io.Writer;

prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.prometheus.metrics.model.registry;
22

3+
import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
34
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
45
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
56
import java.util.List;
@@ -30,33 +31,63 @@ public void register(MultiCollector collector) {
3031

3132
/**
3233
* Validates that the new collector's type is consistent with any existing collectors that have
33-
* the same Prometheus name. This prevents registering, for example, a Counter and a Gauge with
34-
* the same name.
35-
*
36-
* <p>Uses O(1) lookup via cached metric identifiers for efficiency.
34+
* the same Prometheus name, and that there are no duplicate label sets.
3735
*/
3836
private void validateTypeConsistency(Collector newCollector) {
3937
String newName = newCollector.getPrometheusName();
4038
MetricType newType = newCollector.getMetricType();
4139

42-
// If name or type is null, skip validation
43-
if (newName == null || newType == null) {
40+
if (newName == null) {
4441
return;
4542
}
4643

47-
MetricIdentifier newIdentifier = new MetricIdentifier(newName, newType);
48-
49-
// O(1) lookup in cache
50-
MetricIdentifier existing = registeredMetrics.get(newName);
51-
if (existing != null && !newIdentifier.isCompatibleWith(existing)) {
52-
throw new IllegalArgumentException(
53-
"Collector with Prometheus name '"
54-
+ newName
55-
+ "' is already registered with type "
56-
+ existing.getType()
57-
+ ", but you are trying to register a new collector with type "
58-
+ newType
59-
+ ". All collectors with the same Prometheus name must have the same type.");
44+
// Validate type consistency if type is provided
45+
if (newType != null) {
46+
MetricIdentifier newIdentifier = new MetricIdentifier(newName, newType);
47+
MetricIdentifier existing = registeredMetrics.get(newName);
48+
if (existing != null && !newIdentifier.isCompatibleWith(existing)) {
49+
throw new IllegalArgumentException(
50+
"Collector with Prometheus name '"
51+
+ newName
52+
+ "' is already registered with type "
53+
+ existing.getType()
54+
+ ", but you are trying to register a new collector with type "
55+
+ newType
56+
+ ". All collectors with the same Prometheus name must have the same type.");
57+
}
58+
}
59+
60+
// Validate no duplicate labels by collecting and comparing snapshots
61+
MetricSnapshot newSnapshot = newCollector.collect();
62+
if (newSnapshot != null) {
63+
for (Collector existingCollector : collectors) {
64+
if (newName.equals(existingCollector.getPrometheusName())) {
65+
MetricSnapshot existingSnapshot = existingCollector.collect();
66+
if (existingSnapshot != null) {
67+
validateNoDuplicateLabels(newSnapshot, existingSnapshot);
68+
}
69+
}
70+
}
71+
}
72+
}
73+
74+
/**
75+
* Validates that two snapshots with the same Prometheus name don't have overlapping label sets.
76+
*/
77+
private void validateNoDuplicateLabels(MetricSnapshot snapshot1, MetricSnapshot snapshot2) {
78+
String metricName = snapshot1.getMetadata().getName();
79+
80+
for (DataPointSnapshot dp1 : snapshot1.getDataPoints()) {
81+
for (DataPointSnapshot dp2 : snapshot2.getDataPoints()) {
82+
if (dp1.getLabels().equals(dp2.getLabels())) {
83+
throw new IllegalArgumentException(
84+
"Duplicate labels detected for metric '"
85+
+ metricName
86+
+ "' with labels "
87+
+ dp1.getLabels()
88+
+ ". Each time series (metric name + label set) must be unique.");
89+
}
90+
}
6091
}
6192
}
6293

@@ -65,22 +96,20 @@ private void validateTypeConsistency(Collector newCollector) {
6596
*
6697
* <p>Validates each Prometheus name returned by the MultiCollector. If the MultiCollector
6798
* provides type information via {@link MultiCollector#getMetricType(String)}, validation happens
68-
* at registration time. Otherwise, validation is deferred to scrape time.
99+
* at registration time.
69100
*/
70101
private void validateTypeConsistency(MultiCollector newCollector) {
71102
List<String> names = newCollector.getPrometheusNames();
72103

73104
for (String name : names) {
74105
MetricType type = newCollector.getMetricType(name);
75106

76-
// Skip validation if type is unknown
77107
if (type == null) {
78108
continue;
79109
}
80110

81111
MetricIdentifier newIdentifier = new MetricIdentifier(name, type);
82112

83-
// O(1) lookup in cache
84113
MetricIdentifier existing = registeredMetrics.get(name);
85114
if (existing != null && !newIdentifier.isCompatibleWith(existing)) {
86115
throw new IllegalArgumentException(
@@ -94,13 +123,12 @@ private void validateTypeConsistency(MultiCollector newCollector) {
94123
+ " the same type.");
95124
}
96125

97-
// Cache the identifier for future lookups
98126
registeredMetrics.putIfAbsent(name, newIdentifier);
99127
}
100128
}
101129

102130
/**
103-
* Caches the metric identifier for fast O(1) lookup during future registrations.
131+
* Caches the metric identifier for lookup during future registrations.
104132
*
105133
* <p>Only caches if the collector provides both a Prometheus name and type.
106134
*/
@@ -116,8 +144,7 @@ private void cacheMetricIdentifier(Collector collector) {
116144
public void unregister(Collector collector) {
117145
collectors.remove(collector);
118146
// Note: We don't remove from cache because another collector with the same name might exist
119-
// The cache will be cleaned up when clear() is called or can be left as-is (it's just
120-
// metadata)
147+
// The cache will be cleaned up when clear() is called
121148
}
122149

123150
public void unregister(MultiCollector collector) {

prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/MetricSnapshots.java

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,67 +30,34 @@ public MetricSnapshots(MetricSnapshot... snapshots) {
3030
* #builder()}.
3131
*
3232
* @param snapshots the constructor creates a sorted copy of snapshots.
33-
* @throws IllegalArgumentException if there are duplicate metric names with different types, or
34-
* duplicate label sets within the same metric name
33+
* @throws IllegalArgumentException if snapshots with the same Prometheus name have conflicting types
3534
*/
3635
public MetricSnapshots(Collection<MetricSnapshot> snapshots) {
37-
validateSnapshots(snapshots);
36+
validateTypeConsistency(snapshots);
3837
List<MetricSnapshot> list = new ArrayList<>(snapshots);
3938
list.sort(comparing(s -> s.getMetadata().getPrometheusName()));
4039
this.snapshots = unmodifiableList(list);
4140
}
4241

4342
/**
44-
* Validates that there are no duplicate time series (same metric name + same label set), and that
45-
* all metrics with the same name have the same type.
43+
* Validates that all snapshots with the same Prometheus name have the same type.
4644
*/
47-
private static void validateSnapshots(Collection<MetricSnapshot> snapshots) {
48-
// Group snapshots by Prometheus name
49-
Map<String, List<MetricSnapshot>> groupedByName = new HashMap<>();
45+
private static void validateTypeConsistency(Collection<MetricSnapshot> snapshots) {
46+
Map<String, Class<? extends MetricSnapshot>> typesByName = new HashMap<>();
5047
for (MetricSnapshot snapshot : snapshots) {
5148
String prometheusName = snapshot.getMetadata().getPrometheusName();
52-
groupedByName.computeIfAbsent(prometheusName, k -> new ArrayList<>()).add(snapshot);
53-
}
54-
55-
// For each group with multiple snapshots, validate type consistency and check for duplicate
56-
// labels
57-
for (Map.Entry<String, List<MetricSnapshot>> entry : groupedByName.entrySet()) {
58-
if (entry.getValue().size() > 1) {
59-
String prometheusName = entry.getKey();
60-
List<MetricSnapshot> snapshotsWithSameName = entry.getValue();
61-
62-
// Check that all snapshots with the same name have the same type
63-
Class<?> firstType = snapshotsWithSameName.get(0).getClass();
64-
for (int i = 1; i < snapshotsWithSameName.size(); i++) {
65-
MetricSnapshot snapshot = snapshotsWithSameName.get(i);
66-
if (!firstType.equals(snapshot.getClass())) {
67-
throw new IllegalArgumentException(
68-
"Conflicting metric types for Prometheus name '"
69-
+ prometheusName
70-
+ "': "
71-
+ firstType.getSimpleName()
72-
+ " vs "
73-
+ snapshot.getClass().getSimpleName()
74-
+ ". All metrics with the same Prometheus name must have the same type.");
75-
}
76-
}
77-
78-
// Check for duplicate label sets
79-
Set<Labels> seenLabels = new HashSet<>();
80-
for (MetricSnapshot snapshot : snapshotsWithSameName) {
81-
for (DataPointSnapshot dataPoint : snapshot.getDataPoints()) {
82-
Labels labels = dataPoint.getLabels();
83-
if (!seenLabels.add(labels)) {
84-
throw new IllegalArgumentException(
85-
"Duplicate labels detected for metric '"
86-
+ prometheusName
87-
+ "': "
88-
+ labels
89-
+ ". Each time series (metric name + label set) must be unique.");
90-
}
91-
}
92-
}
49+
Class<? extends MetricSnapshot> existingType = typesByName.get(prometheusName);
50+
if (existingType != null && !existingType.equals(snapshot.getClass())) {
51+
throw new IllegalArgumentException(
52+
"Conflicting metric types for Prometheus name '"
53+
+ prometheusName
54+
+ "': "
55+
+ existingType.getSimpleName()
56+
+ " vs "
57+
+ snapshot.getClass().getSimpleName()
58+
+ ". All metrics with the same Prometheus name must have the same type.");
9359
}
60+
typesByName.put(prometheusName, snapshot.getClass());
9461
}
9562
}
9663

0 commit comments

Comments
 (0)