001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
018
019import java.time.Duration;
020import java.util.Map;
021
022import io.micrometer.core.instrument.Clock;
023import io.micrometer.prometheus.PrometheusConfig;
024import io.micrometer.prometheus.PrometheusMeterRegistry;
025import io.prometheus.client.CollectorRegistry;
026import io.prometheus.client.exporter.PushGateway;
027
028import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
029import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
030import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
031import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
032import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
033import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
034import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
035import org.springframework.boot.autoconfigure.AutoConfigureAfter;
036import org.springframework.boot.autoconfigure.AutoConfigureBefore;
037import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
038import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
039import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
040import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
041import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
042import org.springframework.boot.context.properties.EnableConfigurationProperties;
043import org.springframework.context.annotation.Bean;
044import org.springframework.context.annotation.Configuration;
045import org.springframework.core.env.Environment;
046
047/**
048 * {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
049 *
050 * @since 2.0.0
051 * @author Jon Schneider
052 * @author David J. M. Karlsen
053 */
054@Configuration
055@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class,
056                SimpleMetricsExportAutoConfiguration.class })
057@AutoConfigureAfter(MetricsAutoConfiguration.class)
058@ConditionalOnBean(Clock.class)
059@ConditionalOnClass(PrometheusMeterRegistry.class)
060@ConditionalOnProperty(prefix = "management.metrics.export.prometheus", name = "enabled", havingValue = "true", matchIfMissing = true)
061@EnableConfigurationProperties(PrometheusProperties.class)
062public class PrometheusMetricsExportAutoConfiguration {
063
064        @Bean
065        @ConditionalOnMissingBean
066        public PrometheusConfig prometheusConfig(PrometheusProperties prometheusProperties) {
067                return new PrometheusPropertiesConfigAdapter(prometheusProperties);
068        }
069
070        @Bean
071        @ConditionalOnMissingBean
072        public PrometheusMeterRegistry prometheusMeterRegistry(
073                        PrometheusConfig prometheusConfig, CollectorRegistry collectorRegistry,
074                        Clock clock) {
075                return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock);
076        }
077
078        @Bean
079        @ConditionalOnMissingBean
080        public CollectorRegistry collectorRegistry() {
081                return new CollectorRegistry(true);
082        }
083
084        @Configuration
085        public static class PrometheusScrapeEndpointConfiguration {
086
087                @Bean
088                @ConditionalOnEnabledEndpoint
089                @ConditionalOnMissingBean
090                public PrometheusScrapeEndpoint prometheusEndpoint(
091                                CollectorRegistry collectorRegistry) {
092                        return new PrometheusScrapeEndpoint(collectorRegistry);
093                }
094
095        }
096
097        /**
098         * Configuration for <a href="https://github.com/prometheus/pushgateway">Prometheus
099         * Pushgateway</a>.
100         */
101        @Configuration
102        @ConditionalOnClass(PushGateway.class)
103        @ConditionalOnProperty(prefix = "management.metrics.export.prometheus.pushgateway", name = "enabled")
104        public static class PrometheusPushGatewayConfiguration {
105
106                /**
107                 * The fallback job name. We use 'spring' since there's a history of Prometheus
108                 * spring integration defaulting to that name from when Prometheus integration
109                 * didn't exist in Spring itself.
110                 */
111                private static final String FALLBACK_JOB = "spring";
112
113                @Bean
114                @ConditionalOnMissingBean
115                public PrometheusPushGatewayManager prometheusPushGatewayManager(
116                                CollectorRegistry collectorRegistry,
117                                PrometheusProperties prometheusProperties, Environment environment) {
118                        PrometheusProperties.Pushgateway properties = prometheusProperties
119                                        .getPushgateway();
120                        PushGateway pushGateway = new PushGateway(properties.getBaseUrl());
121                        Duration pushRate = properties.getPushRate();
122                        String job = getJob(properties, environment);
123                        Map<String, String> groupingKey = properties.getGroupingKey();
124                        ShutdownOperation shutdownOperation = properties.getShutdownOperation();
125                        return new PrometheusPushGatewayManager(pushGateway, collectorRegistry,
126                                        pushRate, job, groupingKey, shutdownOperation);
127                }
128
129                private String getJob(PrometheusProperties.Pushgateway properties,
130                                Environment environment) {
131                        String job = properties.getJob();
132                        job = (job != null) ? job
133                                        : environment.getProperty("spring.application.name");
134                        return (job != null) ? job : FALLBACK_JOB;
135                }
136
137        }
138
139}