Skip to content

Commit fc2a655

Browse files
committed
Merge pull request #30472 from jonatan-ivanov
* gh-30472: Add support for Prometheus Exemplars Closes gh-30472
2 parents 51c45d5 + d0bc31a commit fc2a655

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@
2525
import io.micrometer.prometheus.PrometheusConfig;
2626
import io.micrometer.prometheus.PrometheusMeterRegistry;
2727
import io.prometheus.client.CollectorRegistry;
28+
import io.prometheus.client.exemplars.DefaultExemplarSampler;
29+
import io.prometheus.client.exemplars.ExemplarSampler;
30+
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
2831
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
2932
import io.prometheus.client.exporter.PushGateway;
3033
import org.apache.commons.logging.Log;
3134
import org.apache.commons.logging.LogFactory;
3235

36+
import org.springframework.beans.factory.ObjectProvider;
3337
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
3438
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
3539
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
@@ -56,6 +60,7 @@
5660
*
5761
* @author Jon Schneider
5862
* @author David J. M. Karlsen
63+
* @author Jonatan Ivanov
5964
* @since 2.0.0
6065
*/
6166
@AutoConfiguration(
@@ -76,8 +81,9 @@ public PrometheusConfig prometheusConfig(PrometheusProperties prometheusProperti
7681
@Bean
7782
@ConditionalOnMissingBean
7883
public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig prometheusConfig,
79-
CollectorRegistry collectorRegistry, Clock clock) {
80-
return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock);
84+
CollectorRegistry collectorRegistry, Clock clock, ObjectProvider<ExemplarSampler> exemplarSamplerProvider) {
85+
return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock,
86+
exemplarSamplerProvider.getIfAvailable());
8187
}
8288

8389
@Bean
@@ -86,6 +92,13 @@ public CollectorRegistry collectorRegistry() {
8692
return new CollectorRegistry(true);
8793
}
8894

95+
@Bean
96+
@ConditionalOnMissingBean
97+
@ConditionalOnBean(SpanContextSupplier.class)
98+
public ExemplarSampler exemplarSampler(SpanContextSupplier spanContextSupplier) {
99+
return new DefaultExemplarSampler(spanContextSupplier);
100+
}
101+
89102
@Configuration(proxyBeanMethods = false)
90103
@ConditionalOnAvailableEndpoint(endpoint = PrometheusScrapeEndpoint.class)
91104
public static class PrometheusScrapeEndpointConfiguration {

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfigurationTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import io.micrometer.prometheus.PrometheusConfig;
2323
import io.micrometer.prometheus.PrometheusMeterRegistry;
2424
import io.prometheus.client.CollectorRegistry;
25+
import io.prometheus.client.exemplars.ExemplarSampler;
26+
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
2527
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
2628
import io.prometheus.client.exporter.DefaultHttpConnectionFactory;
2729
import io.prometheus.client.exporter.HttpConnectionFactory;
@@ -50,6 +52,7 @@
5052
*
5153
* @author Andy Wilkinson
5254
* @author Stephane Nicoll
55+
* @author Jonatan Ivanov
5356
*/
5457
@ExtendWith(OutputCaptureExtension.class)
5558
class PrometheusMetricsExportAutoConfigurationTests {
@@ -109,6 +112,20 @@ void allowsCustomCollectorRegistryToBeUsed() {
109112
.hasSingleBean(PrometheusConfig.class));
110113
}
111114

115+
@Test
116+
void autoConfiguresExemplarSamplerIfSpanContextSupplierIsPresent() {
117+
this.contextRunner.withUserConfiguration(ExemplarsConfiguration.class)
118+
.run((context) -> assertThat(context).hasSingleBean(SpanContextSupplier.class)
119+
.hasSingleBean(ExemplarSampler.class).hasSingleBean(PrometheusMeterRegistry.class));
120+
}
121+
122+
@Test
123+
void exemplarSamplerIsNotAutoConfiguredIfSpanContextSupplierIsMissing() {
124+
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
125+
.run((context) -> assertThat(context).doesNotHaveBean(SpanContextSupplier.class)
126+
.doesNotHaveBean(ExemplarSampler.class).hasSingleBean(PrometheusMeterRegistry.class));
127+
}
128+
112129
@Test
113130
void addsScrapeEndpointToManagementContext() {
114131
this.contextRunner.withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class))
@@ -271,4 +288,25 @@ PrometheusScrapeEndpoint customEndpoint(CollectorRegistry collectorRegistry) {
271288

272289
}
273290

291+
@Configuration(proxyBeanMethods = false)
292+
@Import(BaseConfiguration.class)
293+
static class ExemplarsConfiguration {
294+
295+
@Bean
296+
SpanContextSupplier spanContextSupplier() {
297+
return new SpanContextSupplier() {
298+
@Override
299+
public String getTraceId() {
300+
return null;
301+
}
302+
303+
@Override
304+
public String getSpanId() {
305+
return null;
306+
}
307+
};
308+
}
309+
310+
}
311+
274312
}

spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,9 @@ The following example `scrape_config` adds to `prometheus.yml`:
455455
- targets: ["HOST:PORT"]
456456
----
457457

458+
https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage[Prometheus Exemplars] are also supported. To enable this feature, a `SpanContextSupplier` bean should present. If you use https://spring.io/projects/spring-cloud-sleuth[Spring Cloud Sleuth], this will be auto-configured for you, but you can always create your own if you want. +
459+
Please check the https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage[Prometheus Docs], since this feature needs to be explicitly enabled on Prometheus' side, and it is only supported using the https://github.com/OpenObservability/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#exemplars[OpenMetrics] format.
460+
458461
For ephemeral or batch jobs that may not exist long enough to be scraped, you can use https://github.com/prometheus/pushgateway[Prometheus Pushgateway] support to expose the metrics to Prometheus.
459462
To enable Prometheus Pushgateway support, add the following dependency to your project:
460463

0 commit comments

Comments
 (0)