Actuator health endpoint #2

Merged
schatz merged 3 commits from add_health_endpoint into master 2024-06-12 13:00:30 +02:00
6 changed files with 120 additions and 3 deletions

View File

@ -164,6 +164,12 @@
<version>2.0.1.Final</version>
</dependency>
<!-- Add actuator dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Add dump schema dependency -->
<dependency>
<groupId>eu.dnetlib.dhp</groupId>

View File

@ -0,0 +1,55 @@
package eu.openaire.api.config.health;
import eu.openaire.api.repositories.SolrRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class HealthCheck implements HealthIndicator {
@Autowired
private SolrRepository solrRepository;
private final Logger log = LogManager.getLogger(this.getClass());
@Override
public Health health() {
log.info("Health check triggered");
// Custom health check logic
boolean isHealthy = checkHealth();
if (isHealthy) {
String healthMsg = "Successfully pinged Solr cluster";
log.info(healthMsg);
return Health.up().withDetail("message", healthMsg).build();
} else {
String notHealthyMsg = "Could not ping Solr cluster; please check the logs for details";
log.error(notHealthyMsg);
return Health.down().withDetail("message", notHealthyMsg).build();
}
}
private boolean checkHealth() {
// Ping Solr cluster to check health
try {
if (solrRepository.ping().getStatus() != 0) {
return false;
}
} catch (SolrException | IOException | SolrServerException e) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,34 @@
package eu.openaire.api.config.health;
import eu.openaire.api.repositories.SolrRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class SolrStartupHealthCheck implements ApplicationRunner {
private final Logger log = LogManager.getLogger(this.getClass());
@Autowired
private SolrRepository solrRepository;
@Override
public void run(ApplicationArguments args) throws RuntimeException {
try {
if (solrRepository.ping().getStatus() != 0) {
throw new RuntimeException("Could not ping Solr cluster at startup");
}
} catch (SolrException | IOException | SolrServerException e) {
throw new RuntimeException("Failed to connect to Solr cluster at startup", e);
}
log.info("Successfully pinged Solr cluster at startup");
}
}

View File

@ -9,6 +9,7 @@ import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.common.SolrDocument;
import org.springframework.stereotype.Repository;
@ -62,4 +63,8 @@ public class SolrRepository {
return solrConnectionManager.getSolrClient().query(query);
}
public SolrPingResponse ping() throws SolrServerException, IOException {
return solrConnectionManager.ping();
}
}

View File

@ -8,6 +8,7 @@ import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@ -41,13 +42,20 @@ public class SolrConnectionManager {
// create SolrClient with ZooKeeper hosts
// TODO: add socket (or connection) timeout?
solrClient = new CloudSolrClient.Builder(zkHosts, Optional.empty()).build();
solrClient = new CloudSolrClient.Builder(zkHosts, Optional.empty())
// time to wait when trying to establish a connection
.withConnectionTimeout(3000)
// time to wait for data to be read from the socket
.withSocketTimeout(30000)
.build();
// set the appropriate Solr collection
((CloudSolrClient) solrClient).setDefaultCollection(solrProperties.getCollection());
log.info("Creating Solr client - Ping response: " + solrClient.ping().toString());
}
public SolrPingResponse ping() throws IOException, SolrServerException {
return solrClient.ping();
}
@PreDestroy
@ -58,6 +66,5 @@ public class SolrConnectionManager {
if (solrClient != null) {
solrClient.close();
}
}
}

View File

@ -12,3 +12,13 @@ logging.level.org.springframework.web=DEBUG
#removes 'trace' field from error responses; alternatively remove 'spring-boot-devtools' dependency
server.error.include-stacktrace=never
# Enable the health endpoint
management.endpoint.health.enabled=true
# Expose the health endpoint
management.endpoints.web.exposure.include=health,info
# Customize health endpoint settings
management.endpoint.health.show-details=always
management.endpoint.health.show-components=always