diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ActuatorConfig.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ActuatorConfig.java new file mode 100644 index 00000000..7e6ae506 --- /dev/null +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ActuatorConfig.java @@ -0,0 +1,64 @@ +package au.org.aodn.ogcapi.server.core.configuration; + +import au.org.aodn.ogcapi.server.core.model.enumeration.ErrorCode; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.indices.ExistsRequest; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ActuatorConfig { + + @Bean + public HealthIndicator ogcApiHealth( + @Value("${elasticsearch.vocabs_index.name}") String vocabIndexName, + @Value("${elasticsearch.index.name}") String indexName, + @Value("${elasticsearch.cloud_optimized_index.name}") String coIndexName, + ElasticsearchClient client) { + return () -> { + try { + // Is elastic up and run? + String status = client.cluster().health(r -> r).status().toString(); + if ("yellow".equalsIgnoreCase(status) || "red".equalsIgnoreCase(status)) { + return Health.status(ErrorCode.ELASTICSEARCH_UNAVAILABLE.getStatus()) + .withDetail("reason", ErrorCode.ELASTICSEARCH_UNAVAILABLE.getMessage()) + .withDetail("code", ErrorCode.ELASTICSEARCH_UNAVAILABLE.getCode()) + .build(); + } + + // Now if our target index exist? + if(!client.indices().exists(ExistsRequest.of(b -> b.index(indexName))).value()) { + return Health.status(ErrorCode.MISSING_CORE_INDEX.getStatus()) + .withDetail("reason", ErrorCode.MISSING_CORE_INDEX.getMessage()) + .withDetail("code", ErrorCode.MISSING_CORE_INDEX.getCode()) + .build(); + } + + if(!client.indices().exists(ExistsRequest.of(b -> b.index(coIndexName))).value()) { + return Health.status(ErrorCode.MISSING_CO_CORE_INDEX.getStatus()) + .withDetail("reason", ErrorCode.MISSING_CO_CORE_INDEX.getMessage()) + .withDetail("code", ErrorCode.MISSING_CO_CORE_INDEX.getCode()) + .build(); + } + + if(!client.indices().exists(ExistsRequest.of(b -> b.index(vocabIndexName))).value()) { + return Health.status(ErrorCode.MISSING_VOCAB_INDEX.getStatus()) + .withDetail("reason", ErrorCode.MISSING_VOCAB_INDEX.getMessage()) + .withDetail("code", ErrorCode.MISSING_VOCAB_INDEX.getCode()) + .build(); + } + + return Health.up().build(); + } catch (Exception e) { + return Health.status(ErrorCode.ELASTICSEARCH_UNAVAILABLE.getStatus()) + .withDetail("reason", ErrorCode.ELASTICSEARCH_UNAVAILABLE.getMessage()) + .withDetail("code", ErrorCode.ELASTICSEARCH_UNAVAILABLE.getCode()) + .withException(e) + .build(); + } + }; + } +} diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java index 723b3f97..4ba8baef 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/Config.java @@ -21,7 +21,7 @@ public class Config { ObjectMapper mapper; @Autowired - public void initConstrucUtils(ObjectMapper mapper) { + public void initConstructUtils(ObjectMapper mapper) { ConstructUtils.setObjectMapper(mapper); } diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ElasticSearchConfig.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ElasticSearchConfig.java index 3bdcabc3..30f42b73 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ElasticSearchConfig.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/configuration/ElasticSearchConfig.java @@ -56,7 +56,7 @@ public ElasticsearchClient geoNetworkElasticsearchClient(RestClientTransport tra * @param indexName - The elastic index name that store the STAC from es-indexer * @param pageSize - Do not set this value too high, say 5000 will crash elastic search * @param searchAsYouTypeSize - The number of search result return for search as you type - * @return + * @return The search object */ @Bean public Search createElasticSearch(ElasticsearchClient client, diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/Constants.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/Constants.java deleted file mode 100644 index 672f2b23..00000000 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/Constants.java +++ /dev/null @@ -1,5 +0,0 @@ -package au.org.aodn.ogcapi.server.core.model.enumeration; - -public class Constants { - public static final String MEDIA_TYPE_MAPBOX = "vnd.mapbox-vector-tile"; -} diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/ErrorCode.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/ErrorCode.java new file mode 100644 index 00000000..34bf525b --- /dev/null +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/ErrorCode.java @@ -0,0 +1,21 @@ +package au.org.aodn.ogcapi.server.core.model.enumeration; + +import lombok.Getter; + +@Getter +public enum ErrorCode { + ELASTICSEARCH_UNAVAILABLE("DOWN", "E1000", "Dependency unavailable"), + MISSING_CO_CORE_INDEX("DEGRADED", "E1001","Missing cloud optimized index"), + MISSING_VOCAB_INDEX("DEGRADED", "E1002","Missing vocab index"), + MISSING_CORE_INDEX("DOWN", "E1003","Missing core index"); + + private final String status; + private final String code; + private final String message; + + ErrorCode(String status, String code, String message) { + this.status = status; + this.code = code; + this.message = message; + } +} diff --git a/server/src/main/resources/application.yaml b/server/src/main/resources/application.yaml index 94cfe602..e8768374 100644 --- a/server/src/main/resources/application.yaml +++ b/server/src/main/resources/application.yaml @@ -456,12 +456,16 @@ management: health: elasticsearch: enabled: false + diskspace: + enabled: false endpoints: web: base-path: /api/v1/ogc/manage exposure: include: "health,info" endpoint: + health: + show-details: always logfile: external-file: /tmp/logs/ogcapi.log # Actuator info point