Skip to content

Commit bb573de

Browse files
committed
allow duplicate metric names
1 parent ae79b3f commit bb573de

File tree

9 files changed

+1312
-20
lines changed

9 files changed

+1312
-20
lines changed

prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class PrometheusProperties {
2121
private final ExporterHttpServerProperties exporterHttpServerProperties;
2222
private final ExporterOpenTelemetryProperties exporterOpenTelemetryProperties;
2323
private final ExporterPushgatewayProperties exporterPushgatewayProperties;
24+
private final RegistryProperties registryProperties;
2425

2526
/**
2627
* Get the properties instance. When called for the first time, {@code get()} loads the properties
@@ -49,7 +50,8 @@ public PrometheusProperties(
4950
ExporterFilterProperties exporterFilterProperties,
5051
ExporterHttpServerProperties httpServerConfig,
5152
ExporterPushgatewayProperties pushgatewayProperties,
52-
ExporterOpenTelemetryProperties otelConfig) {
53+
ExporterOpenTelemetryProperties otelConfig,
54+
RegistryProperties registryProperties) {
5355
this.defaultMetricsProperties = defaultMetricsProperties;
5456
this.metricProperties.putAll(metricProperties);
5557
this.exemplarProperties = exemplarProperties;
@@ -58,6 +60,7 @@ public PrometheusProperties(
5860
this.exporterHttpServerProperties = httpServerConfig;
5961
this.exporterPushgatewayProperties = pushgatewayProperties;
6062
this.exporterOpenTelemetryProperties = otelConfig;
63+
this.registryProperties = registryProperties;
6164
}
6265

6366
/**
@@ -102,6 +105,10 @@ public ExporterOpenTelemetryProperties getExporterOpenTelemetryProperties() {
102105
return exporterOpenTelemetryProperties;
103106
}
104107

108+
public RegistryProperties getRegistryProperties() {
109+
return registryProperties;
110+
}
111+
105112
public static class Builder {
106113
private MetricsProperties defaultMetricsProperties = MetricsProperties.builder().build();
107114
private Map<String, MetricsProperties> metricProperties = new HashMap<>();
@@ -115,6 +122,7 @@ public static class Builder {
115122
ExporterPushgatewayProperties.builder().build();
116123
private ExporterOpenTelemetryProperties otelConfig =
117124
ExporterOpenTelemetryProperties.builder().build();
125+
private RegistryProperties registryProperties = RegistryProperties.builder().build();
118126

119127
private Builder() {}
120128

@@ -166,6 +174,11 @@ public Builder exporterOpenTelemetryProperties(
166174
return this;
167175
}
168176

177+
public Builder registryProperties(RegistryProperties registryProperties) {
178+
this.registryProperties = registryProperties;
179+
return this;
180+
}
181+
169182
public PrometheusProperties build() {
170183
return new PrometheusProperties(
171184
defaultMetricsProperties,
@@ -175,7 +188,8 @@ public PrometheusProperties build() {
175188
exporterFilterProperties,
176189
exporterHttpServerProperties,
177190
pushgatewayProperties,
178-
otelConfig);
191+
otelConfig,
192+
registryProperties);
179193
}
180194
}
181195
}

prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static PrometheusProperties load(Map<Object, Object> externalProperties)
4242
ExporterPushgatewayProperties.load(properties);
4343
ExporterOpenTelemetryProperties exporterOpenTelemetryProperties =
4444
ExporterOpenTelemetryProperties.load(properties);
45+
RegistryProperties registryProperties = RegistryProperties.load(properties);
4546
validateAllPropertiesProcessed(properties);
4647
return new PrometheusProperties(
4748
defaultMetricsProperties,
@@ -51,7 +52,8 @@ public static PrometheusProperties load(Map<Object, Object> externalProperties)
5152
exporterFilterProperties,
5253
exporterHttpServerProperties,
5354
exporterPushgatewayProperties,
54-
exporterOpenTelemetryProperties);
55+
exporterOpenTelemetryProperties,
56+
registryProperties);
5557
}
5658

5759
// This will remove entries from properties when they are processed.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package io.prometheus.metrics.config;
2+
3+
import java.util.Map;
4+
import javax.annotation.Nullable;
5+
6+
/** Properties starting with io.prometheus.registry */
7+
public class RegistryProperties {
8+
9+
private static final String ALLOW_DUPLICATE_REGISTRATION = "allowDuplicateRegistration";
10+
private static final String PREFIX = "io.prometheus.registry";
11+
12+
@Nullable private final Boolean allowDuplicateRegistration;
13+
14+
private RegistryProperties(@Nullable Boolean allowDuplicateRegistration) {
15+
this.allowDuplicateRegistration = allowDuplicateRegistration;
16+
}
17+
18+
/**
19+
* If true, allows registering multiple collectors with the same metric name but potentially
20+
* different label sets. Default is false for backward compatibility.
21+
*
22+
* <p>When enabled, metrics with the same name but different labels can coexist, which is useful
23+
* for integration with frameworks like Micrometer that may create multiple collectors for the
24+
* same metric with varying label sets.
25+
*
26+
* <p>Note: Registering metrics with the same name AND the same label set may produce confusing
27+
* results in Prometheus queries, as multiple time series with identical labels will be present.
28+
*
29+
* <p>This property only affects registries created with {@code new
30+
* PrometheusRegistry(allowDuplicateRegistration)}. The static {@code
31+
* PrometheusRegistry.defaultRegistry} always uses the default value (false).
32+
*
33+
* <p>Property: {@code io.prometheus.registry.allowDuplicateRegistration}
34+
*
35+
* @return true if duplicate registration is allowed, false otherwise (default: false)
36+
*/
37+
public boolean getAllowDuplicateRegistration() {
38+
return allowDuplicateRegistration != null && allowDuplicateRegistration;
39+
}
40+
41+
/**
42+
* Note that this will remove entries from {@code properties}. This is because we want to know if
43+
* there are unused properties remaining after all properties have been loaded.
44+
*/
45+
static RegistryProperties load(Map<Object, Object> properties)
46+
throws PrometheusPropertiesException {
47+
Boolean allowDuplicateRegistration =
48+
Util.loadBoolean(PREFIX + "." + ALLOW_DUPLICATE_REGISTRATION, properties);
49+
return new RegistryProperties(allowDuplicateRegistration);
50+
}
51+
52+
public static Builder builder() {
53+
return new Builder();
54+
}
55+
56+
public static class Builder {
57+
58+
@Nullable private Boolean allowDuplicateRegistration;
59+
60+
private Builder() {}
61+
62+
/** See {@link RegistryProperties#getAllowDuplicateRegistration()} */
63+
public Builder allowDuplicateRegistration(boolean allowDuplicateRegistration) {
64+
this.allowDuplicateRegistration = allowDuplicateRegistration;
65+
return this;
66+
}
67+
68+
public RegistryProperties build() {
69+
return new RegistryProperties(allowDuplicateRegistration);
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)