001package io.freefair.spring.okhttp.autoconfigure.metrics;
002
003import io.freefair.spring.okhttp.autoconfigure.OkHttpProperties;
004import io.micrometer.core.instrument.binder.okhttp3.OkHttpConnectionPoolMetrics;
005import io.micrometer.core.instrument.binder.okhttp3.OkHttpMetricsEventListener;
006import io.micrometer.core.instrument.MeterRegistry;
007import io.micrometer.core.instrument.Tag;
008import okhttp3.ConnectionPool;
009import okhttp3.OkHttpClient;
010import org.springframework.beans.factory.annotation.Autowired;
011import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
012import org.springframework.boot.autoconfigure.AutoConfiguration;
013import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
014import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
015import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
016import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
017import org.springframework.boot.context.properties.EnableConfigurationProperties;
018import org.springframework.context.annotation.Bean;
019import org.springframework.util.CollectionUtils;
020
021import java.util.List;
022import java.util.Map;
023import java.util.stream.Collectors;
024
025@AutoConfiguration(after = CompositeMeterRegistryAutoConfiguration.class)
026@ConditionalOnBean(MeterRegistry.class)
027@ConditionalOnClass({MeterRegistry.class, OkHttpMetricsEventListener.class, OkHttpClient.class})
028@EnableConfigurationProperties(OkHttpMetricsProperties.class)
029public class OkHttpMetricsAutoConfiguration {
030
031    @Autowired
032    private OkHttpMetricsProperties properties;
033
034    @Bean
035    @ConditionalOnProperty(value = "okhttp.metrics.enabled", matchIfMissing = true, havingValue = "true")
036    @ConditionalOnMissingBean
037    public OkHttpMetricsEventListener okHttpMetricsEventListener(MeterRegistry meterRegistry) {
038        OkHttpMetricsEventListener.Builder builder = OkHttpMetricsEventListener
039                .builder(meterRegistry, properties.getName())
040                .includeHostTag(properties.isIncludeHostTag());
041
042        List<String> requestTagKeys = properties.getRequestTagKeys();
043        if (!CollectionUtils.isEmpty(requestTagKeys)) {
044            builder = builder.requestTagKeys(requestTagKeys);
045        }
046
047        Map<String, String> tags = properties.getTags();
048        if (!CollectionUtils.isEmpty(tags)) {
049            builder = builder.tags(getTags(tags));
050        }
051
052        return builder.build();
053    }
054
055    @Bean
056    @ConditionalOnProperty(value = "okhttp.metrics.pool.enabled", matchIfMissing = true, havingValue = "true")
057    @ConditionalOnBean(ConnectionPool.class)
058    @ConditionalOnMissingBean
059    public OkHttpConnectionPoolMetrics okHttpConnectionPoolMetrics(ConnectionPool connectionPool, OkHttpProperties okHttpProperties) {
060        OkHttpMetricsProperties.ConnectionPoolMetricsProperties poolProperties = properties.getPool();
061        return new OkHttpConnectionPoolMetrics(connectionPool,
062                poolProperties.getNamePrefix(),
063                getTags(poolProperties.getTags()),
064                okHttpProperties.getConnectionPool().getMaxIdleConnections()
065        );
066    }
067
068    private List<Tag> getTags(Map<String, String> tags) {
069        return tags.entrySet()
070                .stream()
071                .map(entry -> Tag.of(entry.getKey(), entry.getValue()))
072                .collect(Collectors.toList());
073    }
074
075}