All Downloads are FREE. Search and download functionalities are using the official Maven repository.

club.zhcs.lina.starter.monitor.MonitorAutoConfiguration Maven / Gradle / Ivy

package club.zhcs.lina.starter.monitor;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceUnwrapper;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;

import club.zhcs.lina.starter.monitor.filter.ActuatorFilter;
import club.zhcs.lina.starter.monitor.health.ChainHealthIndicator;
import club.zhcs.lina.starter.monitor.health.HealthChecker;
import club.zhcs.lina.starter.monitor.metrics.druid.DruidDataSourcePoolMetadata;
import club.zhcs.lina.starter.monitor.metrics.druid.DruidMetrics;
import club.zhcs.lina.starter.monitor.metrics.http.PoolingHttpClientConnectionManagerMetricsBinder;
import jakarta.servlet.Filter;
import lombok.RequiredArgsConstructor;

/**
 * @author Kerbores([email protected])
 *
 */
@AutoConfiguration
@RequiredArgsConstructor
@EnableConfigurationProperties(MonitorConfigurationProperties.class)
public class MonitorAutoConfiguration {

    private final MonitorConfigurationProperties config;
    private static final String DATASOURCE_SUFFIX = "dataSource";

    @Bean
    @ConditionalOnBean(DruidDataSource.class)
    @ConditionalOnExpression("${lina.monitor.druid.enabled:false}")
    DataSourcePoolMetadataProvider dataSourcePoolMetadataProvider() {
        return dataSource -> {
            DruidDataSource druidDataSource = DataSourceUnwrapper.unwrap(dataSource, DruidDataSource.class);
            if (druidDataSource != null) {
                return new DruidDataSourcePoolMetadata(druidDataSource);
            }
            return null;
        };
    }

    @Bean
    @ConditionalOnBean(DruidDataSource.class)
    @ConditionalOnClass(StatFilter.class)
    @ConditionalOnExpression("${lina.monitor.druid.enabled:false}")
    @ConditionalOnMissingBean
    StatFilter statFilter() {
        return new StatFilter();
    }

    @Bean
    @ConditionalOnBean(DruidDataSource.class)
    @ConditionalOnExpression("${lina.monitor.druid.enabled:false}")
    DruidMetrics druidMetrics(ObjectProvider> dataSourcesProvider) {
        Map dataSourceMap = dataSourcesProvider.getIfAvailable(HashMap::new);
        Map druidDataSourceMap = new HashMap<>(2);
        dataSourceMap.forEach((name, dataSource) -> {
            // 保证连接池数据和 DataSourcePoolMetadataProvider 的一致
            DruidDataSource druidDataSource = DataSourceUnwrapper.unwrap(dataSource, DruidDataSource.class);
            if (druidDataSource != null) {
                druidDataSourceMap.put(MonitorAutoConfiguration.getDataSourceName(name), druidDataSource);
            }
        });
        return druidDataSourceMap.isEmpty() ? null : new DruidMetrics(druidDataSourceMap);
    }

    /**
     * Get the name of a DataSource based on its {@code beanName}.
     *
     * @param beanName
     *            the name of the data source bean
     * @return a name for the given data source
     */
    private static String getDataSourceName(String beanName) {
        if (beanName.length() > MonitorAutoConfiguration.DATASOURCE_SUFFIX.length()
            && StringUtils.endsWithIgnoreCase(beanName, MonitorAutoConfiguration.DATASOURCE_SUFFIX)) {
            return beanName.substring(0, beanName.length() - MonitorAutoConfiguration.DATASOURCE_SUFFIX.length());
        }
        return beanName;
    }

    @Bean
    @ConditionalOnBean(RestTemplate.class)
    HealthChecker healthChecker(RestTemplate restTemplate) {
        return new HealthChecker(restTemplate);
    }

    @Bean
    @ConditionalOnExpression("${lina.monitor.chain.enabled:false}")
    ChainHealthIndicator chainHealthIndicator(HealthChecker healthChecker) {
        return new ChainHealthIndicator(this.config.getChain().getServices(), this.config.getInterval(), healthChecker);
    }

    @Bean
    @ConditionalOnBean(PoolingHttpClientConnectionManager.class)
    @ConditionalOnExpression("${lina.monitor.http.enabled:false}")
    PoolingHttpClientConnectionManagerMetricsBinder httpClientConnectionManagerMetricsBinder(
                                                                                             PoolingHttpClientConnectionManager manager) {
        return new PoolingHttpClientConnectionManagerMetricsBinder(manager, "default", "default");
    }

    @Bean
    ActuatorFilter actuatorFilter() {
        return new ActuatorFilter(this.config.getSecurity().getIpWhitelist(), this.config.getSecurity().isAllowPrivate());
    }

    @Bean
    FilterRegistrationBean registerAuthFilter(ActuatorFilter actuatorFilter) {
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        registration.setFilter(actuatorFilter);
        registration.addUrlPatterns(this.config.getSecurity().getPaths());
        registration.setName("actuatorFilter");
        registration.setOrder(1); // 值越小,Filter越靠前。
        // 传入参数
        return registration;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy