diff --git a/pom.xml b/pom.xml index fc75c5f..372cb99 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,10 @@ javax.annotation-api 1.3.2 + + org.springframework.boot + spring-boot-starter-actuator + eu.dnetlib.dhp dhp-schemas diff --git a/src/main/java/eu/dnetlib/scholexplorer/api/ScholexplorerApiApplication.java b/src/main/java/eu/dnetlib/scholexplorer/api/ScholexplorerApiApplication.java index 7fb87a7..df5ab5a 100644 --- a/src/main/java/eu/dnetlib/scholexplorer/api/ScholexplorerApiApplication.java +++ b/src/main/java/eu/dnetlib/scholexplorer/api/ScholexplorerApiApplication.java @@ -82,6 +82,14 @@ public class ScholexplorerApiApplication { .build(); } + @Bean + public GroupedOpenApi publicApiKPI() { + return GroupedOpenApi.builder() + .group("Scholexplorer KPI") + .pathsToMatch("/kpi/**") + .build(); + } + @Bean public OpenAPI newSwaggerDocket() { @@ -95,6 +103,7 @@ public class ScholexplorerApiApplication { return new OpenAPI() .servers(servers) + .info(getSwaggerInfo()) .tags(new ArrayList<>()); } diff --git a/src/main/java/eu/dnetlib/scholexplorer/api/controller/KPIController.java b/src/main/java/eu/dnetlib/scholexplorer/api/controller/KPIController.java new file mode 100644 index 0000000..41df90d --- /dev/null +++ b/src/main/java/eu/dnetlib/scholexplorer/api/controller/KPIController.java @@ -0,0 +1,34 @@ +package eu.dnetlib.scholexplorer.api.controller; +import eu.dnetlib.dhp.schema.sx.api.model.v1.LinkPublisher; +import eu.dnetlib.scholexplorer.api.ScholixException; +import eu.dnetlib.scholexplorer.api.index.ScholixIndexManager; +import eu.dnetlib.scholexplorer.api.model.KPIMetric; +import io.micrometer.core.annotation.Timed; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/kpi") +@Tag(name = "kpi") +public class KPIController { + @Autowired + private ScholixIndexManager manager; + + @Operation(summary = "Get Scholix KPI", description = "returns the current KPI") + @GetMapping("/getKPI") + public KPIMetric getKPI() throws ScholixException { + + return manager.getKPI(); + + } + +} diff --git a/src/main/java/eu/dnetlib/scholexplorer/api/index/ScholixIndexManager.java b/src/main/java/eu/dnetlib/scholexplorer/api/index/ScholixIndexManager.java index bb67e1d..f6ac483 100644 --- a/src/main/java/eu/dnetlib/scholexplorer/api/index/ScholixIndexManager.java +++ b/src/main/java/eu/dnetlib/scholexplorer/api/index/ScholixIndexManager.java @@ -10,6 +10,7 @@ import eu.dnetlib.dhp.schema.sx.scholix.ScholixResource; import eu.dnetlib.dhp.schema.sx.scholix.flat.ScholixFlat; import eu.dnetlib.scholexplorer.api.ScholixException; import eu.dnetlib.scholexplorer.api.TaggedCounter; +import eu.dnetlib.scholexplorer.api.model.KPIMetric; import eu.dnetlib.scholexplorer.api.model.Summary; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -19,6 +20,10 @@ import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; +import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder; +import org.elasticsearch.search.aggregations.bucket.composite.ParsedComposite; +import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder; import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; @@ -31,10 +36,7 @@ import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.elasticsearch.index.query.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -197,6 +199,66 @@ public class ScholixIndexManager { } + public KPIMetric getKPI() throws ScholixException{ + + + List> sources = new ArrayList<>(); + + sources.add(new TermsValuesSourceBuilder("relationTypeSource") + .field("sourceType")); + sources.add(new TermsValuesSourceBuilder("relationTypeTarget") + .field("targetType")); + CompositeAggregationBuilder compositeAggregationBuilder = new CompositeAggregationBuilder( + "Composite_relationTypes", sources) + .size(10000); + + final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() + .withSearchType(SearchType.DEFAULT) + .withPageable(PageRequest.of(0, 10)) + .addAggregation( + compositeAggregationBuilder) + .build(); + + Pair resource = null; + try { + resource = connectionPool.getResource(); + ElasticsearchRestTemplate client = resource.getValue(); + + + + final long total = client.count(new NativeSearchQueryBuilder().withSearchType(SearchType.DEFAULT).build(), ScholixFlat.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + final long totalItem = client.count(new NativeSearchQueryBuilder().withSearchType(SearchType.DEFAULT).build(), ScholixFlat.class, IndexCoordinates.of(elasticSearchProperties.getIndexResourceName())); + + + + final KPIMetric metric = new KPIMetric(); + + metric.setNumberOfRelationships(total); + metric.setNumerOfEntity(totalItem); + + final SearchHits hits = client.search(searchQuery, ScholixFlat.class, IndexCoordinates.of(elasticSearchProperties.getIndexName())); + + final Aggregations aggregations = hits.getAggregations(); + if (aggregations == null) + return null; + metric.setRelationMetrics( + ((ParsedComposite) aggregations.get("Composite_relationTypes")) + .getBuckets() + .stream() + .map(b -> new KPIMetric.ScholixRelMetric( + b.getKey().get("relationTypeSource").toString(), + b.getKey().get("relationTypeTarget").toString(), + b.getDocCount())).toList()); + return metric; + } catch (ScholixException e) { + throw e; + } finally { + if (connectionPool != null) { + connectionPool.returnResource(resource); + } + } + } + public List> totalLinksPublisher(final RelationPrefix prefix, final String filterName) throws ScholixException { diff --git a/src/main/java/eu/dnetlib/scholexplorer/api/model/KPIMetric.java b/src/main/java/eu/dnetlib/scholexplorer/api/model/KPIMetric.java new file mode 100644 index 0000000..8bd2306 --- /dev/null +++ b/src/main/java/eu/dnetlib/scholexplorer/api/model/KPIMetric.java @@ -0,0 +1,57 @@ +package eu.dnetlib.scholexplorer.api.model; + +import java.util.List; + + + +public class KPIMetric { + + public static class ScholixRelMetric { + public String sourceType; + public String targetType; + public long numberOfrelationships; + + public ScholixRelMetric(String sourceType, String targetType, long numberOfrelationships) { + this.sourceType = sourceType; + this.targetType = targetType; + this.numberOfrelationships = numberOfrelationships; + } + } + + private Long numberOfRelationships; + + + private List relationMetrics; + + private Long numerOfEntity; + + public Long getNumberOfRelationships() { + return numberOfRelationships; + } + + public KPIMetric setNumberOfRelationships(Long numberOfRelationships) { + this.numberOfRelationships = numberOfRelationships; + return this; + } + + public Long getNumerOfEntity() { + return numerOfEntity; + } + + public KPIMetric setNumerOfEntity(Long numerOfEntity) { + this.numerOfEntity = numerOfEntity; + return this; + } + + public List getRelationMetrics() { + return relationMetrics; + } + + public KPIMetric setRelationMetrics(List relationMetrics) { + this.relationMetrics = relationMetrics; + return this; + } +} + + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9b7468a..2cb293d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -10,6 +10,7 @@ dhp.swagger.api.host = localhost:8080 #dhp.swagger.api.host = api.scholexplorer.openaire.eu dhp.swagger.api.basePath = / +management.endpoint.health.show-details=always management.endpoints.web.exposure.include = health, metrics, prometheus management.metrics.tags.application=${spring.application.name}