Spring Boot 直接访问Sping Boot Actuator健康bean/数据?

62o28rlo  于 2023-01-17  发布在  Spring
关注(0)|答案(4)|浏览(151)

通过Sprig Boot 应用程序,是否可以直接访问执行器/健康数据,而无需进行rest调用并解析结果?
理想情况下,我可以自动连接bean,然后能够通过方法调用获取健康数据的对象表示。
例如,如果我的健康端点显示如下内容:

{
    "status": "UP",
    "components": {
        "db": {
            "status": "UP",
            "details": {
                "database": "PostgreSQL",
                "result": 1,
                "validationQuery": "SELECT 1"
            }
        },
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 499963174912,
                "free": 389081399296,
                "threshold": 10485760
            }
        },
        "ping": {
            "status": "UP"
        },
        "redis": {
            "status": "UP",
            "details": {
                "version": "3.2.12"
            }
        }
    }
}

那么,我可以自动连接哪些组件来找出这些信息中的每一位呢?

vdgimpew

vdgimpew1#

此外,信息和健康点在actuator中默认是启用的,您不需要手动公开它们。当您将依赖项添加到pom.xml时,它将被启用,您可以访问url端点而无需公开它们

klh5stk1

klh5stk12#

这个例子使用HealthContributorRegistry来检索HealthIndicator的名称。它还考虑了CompositeHealthContributors。

import org.springframework.boot.actuate.health.CompositeHealthContributor;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.health.HealthContributorRegistry;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.NamedContributor;
import org.springframework.stereotype.Service;

@Service
public class CustomHealthService {
    private final HealthContributorRegistry healthContributorRegistry;

    public CustomHealthService(HealthContributorRegistry healthContributorRegistry) {
        this.healthContributorRegistry = healthContributorRegistry;
    }

    public void printHealth() {
        healthContributorRegistry.forEach(this::printHealthIndicatorStatus);
    }

    private void printHealthIndicatorStatus(NamedContributor<HealthContributor> contributor) {
        if (contributor.getContributor() instanceof HealthIndicator) {
            System.out.println("Health indicator '" + contributor.getName() + "' has health: '" + ((HealthIndicator) contributor.getContributor()).health() + "'");
        } else if (contributor.getContributor() instanceof CompositeHealthContributor) {
            ((CompositeHealthContributor) contributor.getContributor()).forEach(this::printHealthIndicatorStatus);
        } else {
            throw new RuntimeException("Unexpected HealthContributor type " + contributor.getClass().getName());
        }
    }
}
nnsrf1az

nnsrf1az3#

也许有更好的方法来获得健康数据,但这对我很有效。

@RestController
public class HealthController {
    @Autowired
    HealthContributor[] healthContributors;
    
    
    @GetMapping("/health")
    public Map<String, String> health() {
        Map<String, String> components = new HashMap<String, String>();
        for(HealthContributor healthContributor : healthContributors) {
            String componentName = healthContributor.getClass().getSimpleName().replace("HealthIndicator", "").replace("HealthCheckIndicator", "");
            String status = ((HealthIndicator)(healthContributor)).health().getStatus().toString();
            //To get details
            //Map<String,Object> details = ((HealthIndicator)(healthContributor)).health().getDetails();
            
            components.put(componentName, status);
            
        }
        return components;
    }
    
}

输出示例:

{
  "Mail":"UP",
  "Ping":"UP",
  "Camel":"UP",
  "DiskSpace":"UP"
}

要模拟HealthContributor [],您可以尝试使用Mockito如下:

@Profile("test")
@Configuration
public class HealthContributorsMockConfig {

    @Primary
    @Bean(name = "healthContributors")
    public HealthContributor[] healthContributors() {
        HealthContributor[] healthContributors = new HealthContributor[2];
        
        HealthContributor healthContributorA = Mockito.mock(HealthIndicator.class, new Answer<Object>() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                // TODO Auto-generated method stub
                Health health = Health.up().build();
                return health;
            }
            
        });
        
        HealthContributor healthContributorB = Mockito.mock(HealthIndicator.class, new Answer<Object>() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                // TODO Auto-generated method stub
                Health health = Health.down().build();
                return health;
            }
            
        });
        
        healthContributors[0] = healthContributorA;
        healthContributors[1] = healthContributorB;
        return healthContributors;
        
    }
}
dbf7pr2w

dbf7pr2w4#

当然,您可以注入相应的Endpoint。例如,如果您对HealthEndpoint感兴趣,您可以:

@RestController
public class ActuatorController {

    private final HealthEndpoint healthEndpoint;

    public ActuatorController(HealthEndpoint healthEndpoint) {
        this.healthEndpoint = healthEndpoint;
    }

    @GetMapping("health")
    public String health() {
        return healthEndpoint.health().getStatus().getCode();
    }
}

相关问题