Skip to content

Commit 0517886

Browse files
committed
feat: Add OpenMetrics2 enabled flag for explicit OM2 writer activation
The OM2 writer selection previously activated when any feature flag was set, but there was no way to just enable OM2 without opting into a specific feature. This adds an explicit `enabled` gate (io.prometheus.openmetrics2.enabled) as the single control for OM2 writer selection. Feature flags alone no longer activate OM2. The programmatic `enableOpenMetrics2()` configurator sets enabled=true implicitly, matching its name. Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
1 parent 01f53e9 commit 0517886

File tree

5 files changed

+47
-43
lines changed

5 files changed

+47
-43
lines changed

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,39 @@
99
public class OpenMetrics2Properties {
1010

1111
private static final String PREFIX = "io.prometheus.openmetrics2";
12+
private static final String ENABLED = "enabled";
1213
private static final String CONTENT_NEGOTIATION = "content_negotiation";
1314
private static final String COMPOSITE_VALUES = "composite_values";
1415
private static final String EXEMPLAR_COMPLIANCE = "exemplar_compliance";
1516
private static final String NATIVE_HISTOGRAMS = "native_histograms";
1617

18+
@Nullable private final Boolean enabled;
1719
@Nullable private final Boolean contentNegotiation;
1820
@Nullable private final Boolean compositeValues;
1921
@Nullable private final Boolean exemplarCompliance;
2022
@Nullable private final Boolean nativeHistograms;
2123

2224
private OpenMetrics2Properties(
25+
@Nullable Boolean enabled,
2326
@Nullable Boolean contentNegotiation,
2427
@Nullable Boolean compositeValues,
2528
@Nullable Boolean exemplarCompliance,
2629
@Nullable Boolean nativeHistograms) {
30+
this.enabled = enabled;
2731
this.contentNegotiation = contentNegotiation;
2832
this.compositeValues = compositeValues;
2933
this.exemplarCompliance = exemplarCompliance;
3034
this.nativeHistograms = nativeHistograms;
3135
}
3236

37+
/**
38+
* Enable the OpenMetrics 2.0 text format writer. When {@code true}, the OM2 writer is used
39+
* instead of OM1 for OpenMetrics responses. Default is {@code false}.
40+
*/
41+
public boolean getEnabled() {
42+
return enabled != null && enabled;
43+
}
44+
3345
/** Gate OM2 features behind content negotiation. Default is {@code false}. */
3446
public boolean getContentNegotiation() {
3547
return contentNegotiation != null && contentNegotiation;
@@ -56,12 +68,13 @@ public boolean getNativeHistograms() {
5668
*/
5769
static OpenMetrics2Properties load(PropertySource propertySource)
5870
throws PrometheusPropertiesException {
71+
Boolean enabled = Util.loadBoolean(PREFIX, ENABLED, propertySource);
5972
Boolean contentNegotiation = Util.loadBoolean(PREFIX, CONTENT_NEGOTIATION, propertySource);
6073
Boolean compositeValues = Util.loadBoolean(PREFIX, COMPOSITE_VALUES, propertySource);
6174
Boolean exemplarCompliance = Util.loadBoolean(PREFIX, EXEMPLAR_COMPLIANCE, propertySource);
6275
Boolean nativeHistograms = Util.loadBoolean(PREFIX, NATIVE_HISTOGRAMS, propertySource);
6376
return new OpenMetrics2Properties(
64-
contentNegotiation, compositeValues, exemplarCompliance, nativeHistograms);
77+
enabled, contentNegotiation, compositeValues, exemplarCompliance, nativeHistograms);
6578
}
6679

6780
public static Builder builder() {
@@ -70,13 +83,20 @@ public static Builder builder() {
7083

7184
public static class Builder {
7285

86+
@Nullable private Boolean enabled;
7387
@Nullable private Boolean contentNegotiation;
7488
@Nullable private Boolean compositeValues;
7589
@Nullable private Boolean exemplarCompliance;
7690
@Nullable private Boolean nativeHistograms;
7791

7892
private Builder() {}
7993

94+
/** See {@link #getEnabled()} */
95+
public Builder enabled(boolean enabled) {
96+
this.enabled = enabled;
97+
return this;
98+
}
99+
80100
/** See {@link #getContentNegotiation()} */
81101
public Builder contentNegotiation(boolean contentNegotiation) {
82102
this.contentNegotiation = contentNegotiation;
@@ -103,6 +123,7 @@ public Builder nativeHistograms(boolean nativeHistograms) {
103123

104124
/** Enable all OpenMetrics 2.0 features */
105125
public Builder enableAll() {
126+
this.enabled = true;
106127
this.contentNegotiation = true;
107128
this.compositeValues = true;
108129
this.exemplarCompliance = true;
@@ -112,7 +133,7 @@ public Builder enableAll() {
112133

113134
public OpenMetrics2Properties build() {
114135
return new OpenMetrics2Properties(
115-
contentNegotiation, compositeValues, exemplarCompliance, nativeHistograms);
136+
enabled, contentNegotiation, compositeValues, exemplarCompliance, nativeHistograms);
116137
}
117138
}
118139
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ public Builder exporterOpenTelemetryProperties(
242242
}
243243

244244
public Builder enableOpenMetrics2(Consumer<OpenMetrics2Properties.Builder> configurator) {
245-
OpenMetrics2Properties.Builder openMetrics2Builder = OpenMetrics2Properties.builder();
245+
OpenMetrics2Properties.Builder openMetrics2Builder =
246+
OpenMetrics2Properties.builder().enabled(true);
246247
configurator.accept(openMetrics2Builder);
247248
this.openMetrics2Properties = openMetrics2Builder.build();
248249
return this;

prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/OpenMetrics2PropertiesTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void load() {
1515
load(
1616
new HashMap<>(
1717
Map.of(
18+
"io.prometheus.openmetrics2.enabled",
19+
"true",
1820
"io.prometheus.openmetrics2.content_negotiation",
1921
"true",
2022
"io.prometheus.openmetrics2.composite_values",
@@ -23,6 +25,7 @@ void load() {
2325
"true",
2426
"io.prometheus.openmetrics2.native_histograms",
2527
"true")));
28+
assertThat(properties.getEnabled()).isTrue();
2629
assertThat(properties.getContentNegotiation()).isTrue();
2730
assertThat(properties.getCompositeValues()).isTrue();
2831
assertThat(properties.getExemplarCompliance()).isTrue();
@@ -31,6 +34,11 @@ void load() {
3134

3235
@Test
3336
void loadInvalidValue() {
37+
assertThatExceptionOfType(PrometheusPropertiesException.class)
38+
.isThrownBy(
39+
() -> load(new HashMap<>(Map.of("io.prometheus.openmetrics2.enabled", "invalid"))))
40+
.withMessage(
41+
"io.prometheus.openmetrics2.enabled: Expecting 'true' or 'false'. Found: invalid");
3442
assertThatExceptionOfType(PrometheusPropertiesException.class)
3543
.isThrownBy(
3644
() ->
@@ -79,11 +87,13 @@ private static OpenMetrics2Properties load(Map<String, String> map) {
7987
void builder() {
8088
OpenMetrics2Properties properties =
8189
OpenMetrics2Properties.builder()
90+
.enabled(true)
8291
.contentNegotiation(true)
8392
.compositeValues(false)
8493
.exemplarCompliance(true)
8594
.nativeHistograms(false)
8695
.build();
96+
assertThat(properties.getEnabled()).isTrue();
8797
assertThat(properties.getContentNegotiation()).isTrue();
8898
assertThat(properties.getCompositeValues()).isFalse();
8999
assertThat(properties.getExemplarCompliance()).isTrue();
@@ -93,6 +103,7 @@ void builder() {
93103
@Test
94104
void builderEnableAll() {
95105
OpenMetrics2Properties properties = OpenMetrics2Properties.builder().enableAll().build();
106+
assertThat(properties.getEnabled()).isTrue();
96107
assertThat(properties.getContentNegotiation()).isTrue();
97108
assertThat(properties.getCompositeValues()).isTrue();
98109
assertThat(properties.getExemplarCompliance()).isTrue();
@@ -102,6 +113,7 @@ void builderEnableAll() {
102113
@Test
103114
void defaultValues() {
104115
OpenMetrics2Properties properties = OpenMetrics2Properties.builder().build();
116+
assertThat(properties.getEnabled()).isFalse();
105117
assertThat(properties.getContentNegotiation()).isFalse();
106118
assertThat(properties.getCompositeValues()).isFalse();
107119
assertThat(properties.getExemplarCompliance()).isFalse();

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,7 @@ public ExpositionFormatWriter findWriter(@Nullable String acceptHeader) {
7676
}
7777

7878
private boolean isOpenMetrics2Enabled() {
79-
OpenMetrics2Properties props = openMetrics2TextFormatWriter.getOpenMetrics2Properties();
80-
return props.getContentNegotiation()
81-
|| props.getCompositeValues()
82-
|| props.getExemplarCompliance()
83-
|| props.getNativeHistograms();
79+
return openMetrics2TextFormatWriter.getOpenMetrics2Properties().getEnabled();
8480
}
8581

8682
public PrometheusProtobufWriter getPrometheusProtobufWriter() {

prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -119,77 +119,51 @@ void testOM2DisabledByDefault() {
119119
}
120120

121121
@Test
122-
void testOM2EnabledWithContentNegotiation() {
122+
void testOM2EnabledOnly() {
123123
PrometheusProperties props =
124124
PrometheusProperties.builder()
125-
.openMetrics2Properties(
126-
OpenMetrics2Properties.builder().contentNegotiation(true).build())
125+
.openMetrics2Properties(OpenMetrics2Properties.builder().enabled(true).build())
127126
.build();
128127
ExpositionFormats formats = ExpositionFormats.init(props);
129128
ExpositionFormatWriter writer = formats.findWriter("application/openmetrics-text");
130-
// When contentNegotiation is enabled, should return OM2 writer
131129
assertThat(writer).isInstanceOf(OpenMetrics2TextFormatWriter.class);
132130
}
133131

134132
@Test
135-
void testOM2EnabledWithCompositeValues() {
136-
PrometheusProperties props =
137-
PrometheusProperties.builder()
138-
.openMetrics2Properties(OpenMetrics2Properties.builder().compositeValues(true).build())
139-
.build();
140-
ExpositionFormats formats = ExpositionFormats.init(props);
141-
ExpositionFormatWriter writer = formats.findWriter("application/openmetrics-text");
142-
assertThat(writer).isInstanceOf(OpenMetrics2TextFormatWriter.class);
143-
}
144-
145-
@Test
146-
void testOM2EnabledWithExemplarCompliance() {
133+
void testOM2NotEnabledByFeatureFlagAlone() {
134+
// Feature flags without enabled=true should not activate the OM2 writer
147135
PrometheusProperties props =
148136
PrometheusProperties.builder()
149137
.openMetrics2Properties(
150-
OpenMetrics2Properties.builder().exemplarCompliance(true).build())
151-
.build();
152-
ExpositionFormats formats = ExpositionFormats.init(props);
153-
ExpositionFormatWriter writer = formats.findWriter("application/openmetrics-text");
154-
// When exemplarCompliance is enabled, should return OM2 writer
155-
assertThat(writer).isInstanceOf(OpenMetrics2TextFormatWriter.class);
156-
}
157-
158-
@Test
159-
void testOM2EnabledWithNativeHistograms() {
160-
PrometheusProperties props =
161-
PrometheusProperties.builder()
162-
.openMetrics2Properties(OpenMetrics2Properties.builder().nativeHistograms(true).build())
138+
OpenMetrics2Properties.builder().contentNegotiation(true).build())
163139
.build();
164140
ExpositionFormats formats = ExpositionFormats.init(props);
165141
ExpositionFormatWriter writer = formats.findWriter("application/openmetrics-text");
166-
// When nativeHistograms is enabled, should return OM2 writer
167-
assertThat(writer).isInstanceOf(OpenMetrics2TextFormatWriter.class);
142+
assertThat(writer).isInstanceOf(OpenMetricsTextFormatWriter.class);
168143
}
169144

170145
@Test
171-
void testOM2EnabledWithMultipleFlags() {
146+
void testOM2EnabledWithFeatureFlags() {
172147
PrometheusProperties props =
173148
PrometheusProperties.builder()
174149
.openMetrics2Properties(
175150
OpenMetrics2Properties.builder()
151+
.enabled(true)
176152
.contentNegotiation(true)
177153
.compositeValues(true)
178154
.nativeHistograms(true)
179155
.build())
180156
.build();
181157
ExpositionFormats formats = ExpositionFormats.init(props);
182158
ExpositionFormatWriter writer = formats.findWriter("application/openmetrics-text");
183-
// When multiple OM2 flags are enabled, should return OM2 writer
184159
assertThat(writer).isInstanceOf(OpenMetrics2TextFormatWriter.class);
185160
}
186161

187162
@Test
188163
void testProtobufWriterTakesPrecedence() {
189164
PrometheusProperties props =
190165
PrometheusProperties.builder()
191-
.openMetrics2Properties(
192-
OpenMetrics2Properties.builder().contentNegotiation(true).build())
166+
.openMetrics2Properties(OpenMetrics2Properties.builder().enabled(true).build())
193167
.build();
194168
ExpositionFormats formats = ExpositionFormats.init(props);
195169
ExpositionFormatWriter writer =

0 commit comments

Comments
 (0)