From 6e239f3c73f458fed62f5facce3c8295833653db Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Fri, 2 May 2025 15:00:29 +0300 Subject: [PATCH 1/7] Created metrics endpoints for general TMF-related information --- .../tmf/metrics/api/GeneralMetricsApi.java | 48 +++++++ .../api/GerenalMetricsApiController.java | 64 +++++++++ .../GeneralMetricsRepoService.java | 41 ++++++ .../tmf/pm632/repo/IndividualRepository.java | 7 + .../repo/ResourceSpecificationRepository.java | 8 ++ .../GerenalMetricsApiControllerTest.java | 122 ++++++++++++++++++ 6 files changed, 290 insertions(+) create mode 100644 src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java create mode 100644 src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java create mode 100644 src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java create mode 100644 src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java b/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java new file mode 100644 index 00000000..27aba886 --- /dev/null +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java @@ -0,0 +1,48 @@ +package org.etsi.osl.tmf.metrics.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +@Tag(name = "GeneralMetricsApi") +public interface GeneralMetricsApi { + + Logger log = LoggerFactory.getLogger(GeneralMetricsApi.class); + + @Operation(summary = "Get total number of registered individuals", operationId = "getRegisteredIndividuals") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + }) + @RequestMapping(value = "/tmf-api/metrics/registeredIndividuals", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + ResponseEntity> getRegisteredIndividuals(); + + @Operation(summary = "Get total number of published service specifications", operationId = "getPublishedServiceSpecifications") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + }) + @RequestMapping(value = "/tmf-api/metrics/publishedServiceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + ResponseEntity> getPublishedServiceSpecifications(); + + @Operation(summary = "Get total number of registered resource specifications", operationId = "getRegisteredResourceSpecifications") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "500", description = "Internal Server Error") + }) + @RequestMapping(value = "/tmf-api/metrics/registeredResourceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + ResponseEntity> getRegisteredResourceSpecifications(); +} diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java b/src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java new file mode 100644 index 00000000..9fad6620 --- /dev/null +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java @@ -0,0 +1,64 @@ +package org.etsi.osl.tmf.metrics.api; + +import org.etsi.osl.tmf.metrics.reposervices.GeneralMetricsRepoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; + +import java.util.HashMap; +import java.util.Map; + +@Controller +public class GerenalMetricsApiController implements GeneralMetricsApi { + + private static final Logger log = LoggerFactory.getLogger(GerenalMetricsApiController.class); + + private final GeneralMetricsRepoService generalMetricsRepoService; + + @Autowired + public GerenalMetricsApiController(GeneralMetricsRepoService generalMetricsRepoService) { + this.generalMetricsRepoService = generalMetricsRepoService; + } + + @Override + public ResponseEntity> getRegisteredIndividuals() { + try { + int totalIndividuals = generalMetricsRepoService.countRegisteredIndividuals(); + Map response = new HashMap<>(); + response.put("registeredIndividuals", totalIndividuals); + return new ResponseEntity<>(response, HttpStatus.OK); + } catch (Exception e) { + log.error("Couldn't retrieve total registered individuals. ", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + public ResponseEntity> getPublishedServiceSpecifications() { + try { + int totalSpecifications = generalMetricsRepoService.countPublishedServiceSpecifications(); + Map response = new HashMap<>(); + response.put("publishedServiceSpecifications", totalSpecifications); + return new ResponseEntity<>(response, HttpStatus.OK); + } catch (Exception e) { + log.error("Couldn't retrieve total published service specifications. ", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + public ResponseEntity> getRegisteredResourceSpecifications() { + try { + int totalResourceSpecifications = generalMetricsRepoService.countRegisteredResourceSpecifications(); + Map response = new HashMap<>(); + response.put("registeredResourceSpecifications", totalResourceSpecifications); + return new ResponseEntity<>(response, HttpStatus.OK); + } catch (Exception e) { + log.error("Couldn't retrieve total registered resource specifications. ", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java new file mode 100644 index 00000000..854b047c --- /dev/null +++ b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java @@ -0,0 +1,41 @@ +package org.etsi.osl.tmf.metrics.reposervices; + +import org.etsi.osl.tmf.pm632.repo.IndividualRepository; +import org.etsi.osl.tmf.rcm634.repo.ResourceSpecificationRepository; +import org.etsi.osl.tmf.scm633.model.ServiceCategory; +import org.etsi.osl.tmf.scm633.repo.CategoriesRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class GeneralMetricsRepoService { + + @Autowired + IndividualRepository individualRepository; + + @Autowired + ResourceSpecificationRepository resourceSpecificationRepository; + + @Autowired + CategoriesRepository categoriesRepository; + + public int countRegisteredIndividuals() { + return individualRepository.countAll(); + } + + public int countPublishedServiceSpecifications() { + List serviceCategories = categoriesRepository.findByOrderByName(); + int count = 0; + + for (ServiceCategory serviceCategory : serviceCategories) { + count += serviceCategory.getServiceCandidateObj().size() + serviceCategory.getServiceCandidateRefs().size(); + } + return count; + } + + public int countRegisteredResourceSpecifications() { + return resourceSpecificationRepository.countLogical() + resourceSpecificationRepository.countPhysical(); + } +} diff --git a/src/main/java/org/etsi/osl/tmf/pm632/repo/IndividualRepository.java b/src/main/java/org/etsi/osl/tmf/pm632/repo/IndividualRepository.java index 1e16ed9f..214a5bfd 100644 --- a/src/main/java/org/etsi/osl/tmf/pm632/repo/IndividualRepository.java +++ b/src/main/java/org/etsi/osl/tmf/pm632/repo/IndividualRepository.java @@ -22,6 +22,7 @@ package org.etsi.osl.tmf.pm632.repo; import java.util.List; import java.util.Optional; import org.etsi.osl.tmf.pm632.model.Individual; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; @@ -40,4 +41,10 @@ public interface IndividualRepository extends CrudRepository, Optional findByPreferredGivenName(String username); + //Methods for metrics + + @Query("SELECT COUNT(ind) FROM Individual ind") + int countAll(); + + } diff --git a/src/main/java/org/etsi/osl/tmf/rcm634/repo/ResourceSpecificationRepository.java b/src/main/java/org/etsi/osl/tmf/rcm634/repo/ResourceSpecificationRepository.java index 456b8907..c7726f9b 100644 --- a/src/main/java/org/etsi/osl/tmf/rcm634/repo/ResourceSpecificationRepository.java +++ b/src/main/java/org/etsi/osl/tmf/rcm634/repo/ResourceSpecificationRepository.java @@ -52,4 +52,12 @@ public interface ResourceSpecificationRepository extends CrudRepository findAllPhysical(); + // Methods for metrics + + @Query("SELECT COUNT(sc) FROM LogicalRspec sc") + int countLogical(); + + @Query("SELECT COUNT(sc) FROM PhysicalRspec sc") + int countPhysical(); + } diff --git a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java new file mode 100644 index 00000000..edd6926c --- /dev/null +++ b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java @@ -0,0 +1,122 @@ +package org.etsi.osl.services.api.metrics; + +import com.jayway.jsonpath.JsonPath; +import org.etsi.osl.tmf.OpenAPISpringBoot; +import org.etsi.osl.tmf.pm632.model.IndividualCreate; +import org.etsi.osl.tmf.pm632.reposervices.IndividualRepoService; +import org.etsi.osl.tmf.rcm634.reposervices.ResourceSpecificationRepoService; +import org.etsi.osl.tmf.scm633.model.ServiceCategory; +import org.etsi.osl.tmf.scm633.reposervices.CategoryRepoService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@Transactional +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.MOCK, + classes = OpenAPISpringBoot.class +) +//@AutoConfigureTestDatabase //this automatically uses h2 +@AutoConfigureMockMvc +@ActiveProfiles("testing") +//@TestPropertySource( +// locations = "classpath:application-testing.yml") + +public class GerenalMetricsApiControllerTest { + + @Autowired + private MockMvc mvc; + + @Autowired + private WebApplicationContext context; + + @Autowired + IndividualRepoService individualRepoService; + + @Autowired + ResourceSpecificationRepoService resourceSpecificationRepoService; + + @Autowired + CategoryRepoService categoryRepoService; + + + @Before + public void setup() throws Exception { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .apply(springSecurity()) + .build(); + } + + @WithMockUser(username="osadmin", roles = {"ADMIN","USER"}) + @Test + public void testGetRegisteredIndividuals() throws Exception { + + IndividualCreate individualCreate = new IndividualCreate(); + individualCreate.setFullName("John Doe"); + individualRepoService.addIndividual(individualCreate); + + String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/registeredIndividuals" ) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk() ) + .andReturn().getResponse().getContentAsString(); + + int totalIndividuals = JsonPath.read(response, "$.registeredIndividuals"); + + assertThat(totalIndividuals).isEqualTo(individualRepoService.findAll().size()); + } + + @WithMockUser(username="osadmin", roles = {"ADMIN","USER"}) + @Test + public void testGetPublishedServiceSpecifications() throws Exception { + + String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/publishedServiceSpecifications" ) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk() ) + .andReturn().getResponse().getContentAsString(); + + int totalSpecs = JsonPath.read(response, "$.publishedServiceSpecifications"); + + List serviceCategories = categoryRepoService.findAll(); + int count = 0; + + for (ServiceCategory serviceCategory : serviceCategories) { + count += serviceCategory.getServiceCandidateObj().size() + serviceCategory.getServiceCandidateRefs().size(); + } + + assertThat(totalSpecs).isEqualTo(count); + } + + @WithMockUser(username="osadmin", roles = {"ADMIN","USER"}) + @Test + public void testGetRegisteredResourceSpecifications() throws Exception { + + String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/registeredResourceSpecifications" ) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk() ) + .andReturn().getResponse().getContentAsString(); + + int totalSpecs = JsonPath.read(response, "$.registeredResourceSpecifications"); + + assertThat(totalSpecs).isEqualTo(resourceSpecificationRepoService.findAll().size()); + } +} -- GitLab From 4aca351a1b978b806885bd5e295cfdc8dbf9487d Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Mon, 5 May 2025 15:15:59 +0300 Subject: [PATCH 2/7] Improved pubilshedServiceSpecifications endpoint by directly retrieving ServiceCandidate objects with Category --- .../reposervices/GeneralMetricsRepoService.java | 15 ++++++++++++--- .../osl/tmf/scm633/repo/CandidateRepository.java | 5 +++++ .../metrics/GerenalMetricsApiControllerTest.java | 14 ++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java index 854b047c..97d048e2 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java @@ -2,7 +2,9 @@ package org.etsi.osl.tmf.metrics.reposervices; import org.etsi.osl.tmf.pm632.repo.IndividualRepository; import org.etsi.osl.tmf.rcm634.repo.ResourceSpecificationRepository; +import org.etsi.osl.tmf.scm633.model.ServiceCandidate; import org.etsi.osl.tmf.scm633.model.ServiceCategory; +import org.etsi.osl.tmf.scm633.repo.CandidateRepository; import org.etsi.osl.tmf.scm633.repo.CategoriesRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -21,16 +23,23 @@ public class GeneralMetricsRepoService { @Autowired CategoriesRepository categoriesRepository; + @Autowired + CandidateRepository candidateRepository; + public int countRegisteredIndividuals() { return individualRepository.countAll(); } public int countPublishedServiceSpecifications() { - List serviceCategories = categoriesRepository.findByOrderByName(); + + List serviceCandidates = candidateRepository.findAll(); int count = 0; - for (ServiceCategory serviceCategory : serviceCategories) { - count += serviceCategory.getServiceCandidateObj().size() + serviceCategory.getServiceCandidateRefs().size(); + for (ServiceCandidate serviceCandidate : serviceCandidates) { + System.out.println("ServiceCandidate Category: " + serviceCandidate.getCategoryObj()); + if (serviceCandidate.getCategory() != null) { + count += 1; + } } return count; } diff --git a/src/main/java/org/etsi/osl/tmf/scm633/repo/CandidateRepository.java b/src/main/java/org/etsi/osl/tmf/scm633/repo/CandidateRepository.java index df131d4b..85e56f4b 100644 --- a/src/main/java/org/etsi/osl/tmf/scm633/repo/CandidateRepository.java +++ b/src/main/java/org/etsi/osl/tmf/scm633/repo/CandidateRepository.java @@ -19,6 +19,7 @@ */ package org.etsi.osl.tmf.scm633.repo; +import java.util.List; import java.util.Optional; import org.etsi.osl.tmf.scm633.model.ServiceCandidate; import org.springframework.data.jpa.repository.Query; @@ -36,4 +37,8 @@ public interface CandidateRepository extends CrudRepository findByServiceSpecUuid(String id); + // Methods for metrics + @Query("SELECT sc FROM ServiceCandidate sc") + List findAll(); + } diff --git a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java index edd6926c..71dc4999 100644 --- a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java +++ b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java @@ -5,8 +5,8 @@ import org.etsi.osl.tmf.OpenAPISpringBoot; import org.etsi.osl.tmf.pm632.model.IndividualCreate; import org.etsi.osl.tmf.pm632.reposervices.IndividualRepoService; import org.etsi.osl.tmf.rcm634.reposervices.ResourceSpecificationRepoService; -import org.etsi.osl.tmf.scm633.model.ServiceCategory; -import org.etsi.osl.tmf.scm633.reposervices.CategoryRepoService; +import org.etsi.osl.tmf.scm633.model.ServiceCandidate; +import org.etsi.osl.tmf.scm633.reposervices.CandidateRepoService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,7 +56,7 @@ public class GerenalMetricsApiControllerTest { ResourceSpecificationRepoService resourceSpecificationRepoService; @Autowired - CategoryRepoService categoryRepoService; + CandidateRepoService candidateRepoService; @Before @@ -96,11 +96,13 @@ public class GerenalMetricsApiControllerTest { int totalSpecs = JsonPath.read(response, "$.publishedServiceSpecifications"); - List serviceCategories = categoryRepoService.findAll(); + List serviceCandidates = candidateRepoService.findAll(); int count = 0; - for (ServiceCategory serviceCategory : serviceCategories) { - count += serviceCategory.getServiceCandidateObj().size() + serviceCategory.getServiceCandidateRefs().size(); + for (ServiceCandidate serviceCandidate : serviceCandidates) { + if (serviceCandidate.getCategory() != null) { + count += 1; + } } assertThat(totalSpecs).isEqualTo(count); -- GitLab From 8fe94fd5f5f6a5b35d51dfee97fa2fea1038bcae Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Tue, 6 May 2025 17:31:40 +0300 Subject: [PATCH 3/7] Removed duplicate 'tmf-api' prefix from metrics API endpoints --- .../org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java b/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java index 27aba886..7566808e 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java @@ -25,7 +25,7 @@ public interface GeneralMetricsApi { @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "500", description = "Internal Server Error") }) - @RequestMapping(value = "/tmf-api/metrics/registeredIndividuals", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + @RequestMapping(value = "/metrics/registeredIndividuals", method = RequestMethod.GET, produces = "application/json;charset=utf-8") ResponseEntity> getRegisteredIndividuals(); @Operation(summary = "Get total number of published service specifications", operationId = "getPublishedServiceSpecifications") @@ -34,7 +34,7 @@ public interface GeneralMetricsApi { @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "500", description = "Internal Server Error") }) - @RequestMapping(value = "/tmf-api/metrics/publishedServiceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + @RequestMapping(value = "/metrics/publishedServiceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") ResponseEntity> getPublishedServiceSpecifications(); @Operation(summary = "Get total number of registered resource specifications", operationId = "getRegisteredResourceSpecifications") @@ -43,6 +43,6 @@ public interface GeneralMetricsApi { @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "500", description = "Internal Server Error") }) - @RequestMapping(value = "/tmf-api/metrics/registeredResourceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") + @RequestMapping(value = "/metrics/registeredResourceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") ResponseEntity> getRegisteredResourceSpecifications(); } -- GitLab From 03559a714be9b773276c2358bea0d91b2d3808ef Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Tue, 6 May 2025 17:37:21 +0300 Subject: [PATCH 4/7] Removed duplicate 'tmf-api' prefix in the unit tests --- .../api/metrics/GerenalMetricsApiControllerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java index 71dc4999..1a7421f2 100644 --- a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java +++ b/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java @@ -75,7 +75,7 @@ public class GerenalMetricsApiControllerTest { individualCreate.setFullName("John Doe"); individualRepoService.addIndividual(individualCreate); - String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/registeredIndividuals" ) + String response = mvc.perform(MockMvcRequestBuilders.get("/metrics/registeredIndividuals" ) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk() ) .andReturn().getResponse().getContentAsString(); @@ -89,7 +89,7 @@ public class GerenalMetricsApiControllerTest { @Test public void testGetPublishedServiceSpecifications() throws Exception { - String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/publishedServiceSpecifications" ) + String response = mvc.perform(MockMvcRequestBuilders.get("/metrics/publishedServiceSpecifications" ) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk() ) .andReturn().getResponse().getContentAsString(); @@ -112,7 +112,7 @@ public class GerenalMetricsApiControllerTest { @Test public void testGetRegisteredResourceSpecifications() throws Exception { - String response = mvc.perform(MockMvcRequestBuilders.get("/tmf-api/metrics/registeredResourceSpecifications" ) + String response = mvc.perform(MockMvcRequestBuilders.get("/metrics/registeredResourceSpecifications" ) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk() ) .andReturn().getResponse().getContentAsString(); -- GitLab From f612eba1967ee306602f936b21357a70b5207be2 Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Wed, 7 May 2025 16:32:46 +0300 Subject: [PATCH 5/7] Changed structure to gather all metrics endpoints under one Controller --- .../api/{GeneralMetricsApi.java => MetricsApi.java} | 8 +++----- ...icsApiController.java => MetricsApiController.java} | 10 +++++----- ...MetricsRepoService.java => MetricsRepoService.java} | 3 +-- ...ntrollerTest.java => MetricsApiControllerTest.java} | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) rename src/main/java/org/etsi/osl/tmf/metrics/api/{GeneralMetricsApi.java => MetricsApi.java} (91%) rename src/main/java/org/etsi/osl/tmf/metrics/api/{GerenalMetricsApiController.java => MetricsApiController.java} (85%) rename src/main/java/org/etsi/osl/tmf/metrics/reposervices/{GeneralMetricsRepoService.java => MetricsRepoService.java} (94%) rename src/test/java/org/etsi/osl/services/api/metrics/{GerenalMetricsApiControllerTest.java => MetricsApiControllerTest.java} (99%) diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java similarity index 91% rename from src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java rename to src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java index 7566808e..dc4e7b1d 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/api/GeneralMetricsApi.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java @@ -4,20 +4,18 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; -@Tag(name = "GeneralMetricsApi") -public interface GeneralMetricsApi { +@Tag(name = "MetricsApi") +public interface MetricsApi { - Logger log = LoggerFactory.getLogger(GeneralMetricsApi.class); + Logger log = LoggerFactory.getLogger(MetricsApi.class); @Operation(summary = "Get total number of registered individuals", operationId = "getRegisteredIndividuals") @ApiResponses(value = { diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java similarity index 85% rename from src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java rename to src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java index 9fad6620..be8f980e 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/api/GerenalMetricsApiController.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java @@ -1,6 +1,6 @@ package org.etsi.osl.tmf.metrics.api; -import org.etsi.osl.tmf.metrics.reposervices.GeneralMetricsRepoService; +import org.etsi.osl.tmf.metrics.reposervices.MetricsRepoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -12,14 +12,14 @@ import java.util.HashMap; import java.util.Map; @Controller -public class GerenalMetricsApiController implements GeneralMetricsApi { +public class MetricsApiController implements MetricsApi { - private static final Logger log = LoggerFactory.getLogger(GerenalMetricsApiController.class); + private static final Logger log = LoggerFactory.getLogger(MetricsApiController.class); - private final GeneralMetricsRepoService generalMetricsRepoService; + private final MetricsRepoService generalMetricsRepoService; @Autowired - public GerenalMetricsApiController(GeneralMetricsRepoService generalMetricsRepoService) { + public MetricsApiController(MetricsRepoService generalMetricsRepoService) { this.generalMetricsRepoService = generalMetricsRepoService; } diff --git a/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/MetricsRepoService.java similarity index 94% rename from src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java rename to src/main/java/org/etsi/osl/tmf/metrics/reposervices/MetricsRepoService.java index 97d048e2..834699b8 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/reposervices/GeneralMetricsRepoService.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/reposervices/MetricsRepoService.java @@ -3,7 +3,6 @@ package org.etsi.osl.tmf.metrics.reposervices; import org.etsi.osl.tmf.pm632.repo.IndividualRepository; import org.etsi.osl.tmf.rcm634.repo.ResourceSpecificationRepository; import org.etsi.osl.tmf.scm633.model.ServiceCandidate; -import org.etsi.osl.tmf.scm633.model.ServiceCategory; import org.etsi.osl.tmf.scm633.repo.CandidateRepository; import org.etsi.osl.tmf.scm633.repo.CategoriesRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -12,7 +11,7 @@ import org.springframework.stereotype.Service; import java.util.List; @Service -public class GeneralMetricsRepoService { +public class MetricsRepoService { @Autowired IndividualRepository individualRepository; diff --git a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java b/src/test/java/org/etsi/osl/services/api/metrics/MetricsApiControllerTest.java similarity index 99% rename from src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java rename to src/test/java/org/etsi/osl/services/api/metrics/MetricsApiControllerTest.java index 1a7421f2..4841b8ec 100644 --- a/src/test/java/org/etsi/osl/services/api/metrics/GerenalMetricsApiControllerTest.java +++ b/src/test/java/org/etsi/osl/services/api/metrics/MetricsApiControllerTest.java @@ -41,7 +41,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. //@TestPropertySource( // locations = "classpath:application-testing.yml") -public class GerenalMetricsApiControllerTest { +public class MetricsApiControllerTest { @Autowired private MockMvc mvc; -- GitLab From 71f6400146b794eede27709d431aeabadb5d9f77 Mon Sep 17 00:00:00 2001 From: Kostis Trantzas Date: Mon, 12 May 2025 13:37:29 +0300 Subject: [PATCH 6/7] Adding OpenAPI UI --- .../SwaggerDocumentationConfig.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/etsi/osl/tmf/configuration/SwaggerDocumentationConfig.java b/src/main/java/org/etsi/osl/tmf/configuration/SwaggerDocumentationConfig.java index b8e5b11a..796d26a3 100644 --- a/src/main/java/org/etsi/osl/tmf/configuration/SwaggerDocumentationConfig.java +++ b/src/main/java/org/etsi/osl/tmf/configuration/SwaggerDocumentationConfig.java @@ -830,7 +830,7 @@ public GroupedOpenApi pim637() { SpringDocUtils.getConfig().replaceWithClass(java.time.OffsetDateTime.class, java.util.Date.class); return GroupedOpenApi.builder() - .group("OpensliceLCMRulesspecificationAPI") + .group("OpenSliceLCMRulesspecificationAPI") .addOpenApiCustomizer( this.lcmOpenAPI() ) .packagesToScan("org.etsi.osl.tmf.lcm.api") .build(); @@ -947,6 +947,39 @@ public GroupedOpenApi pim637() { .build(); } + + + /** + * Metrics + * @return + */ + @Bean + public OpenApiCustomizer metricsOpenAPI() { + return openApi -> openApi + .specVersion( SpecVersion.V30 ).addSecurityItem(new SecurityRequirement().addList("security_auth")) + .info(new Info().title("OpenSlice Metrics API") + .description("OpenAPI environment for OpenSlice Metrics") + .version("4.0.0") + .license(new License() + .name("Apache 2.0") + .url("https://osl.etsi.org"))) + .externalDocs(new ExternalDocumentation() + .description("OpenSlice Metrics") + .url("https://osl.etsi.org")); + } + + @Bean + public GroupedOpenApi metrics(){ + + SpringDocUtils.getConfig().replaceWithClass(java.time.LocalDate.class, java.sql.Date.class); + SpringDocUtils.getConfig().replaceWithClass(java.time.OffsetDateTime.class, java.util.Date.class); + return GroupedOpenApi.builder() + .group("OpenSliceMetricsAPI") + .addOpenApiCustomizer( this.metricsOpenAPI() ) + .packagesToScan("org.etsi.osl.tmf.metrics.api") + .build(); + + } // @Bean -- GitLab From a62e051d1b9bc31f2092521330ca0907e795cfd6 Mon Sep 17 00:00:00 2001 From: Nikos Kyriakoulis Date: Mon, 12 May 2025 16:53:16 +0300 Subject: [PATCH 7/7] Use metrics models for API responses --- .../etsi/osl/tmf/metrics/api/MetricsApi.java | 9 ++++++--- .../tmf/metrics/api/MetricsApiController.java | 18 +++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java index dc4e7b1d..0ddf35e4 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApi.java @@ -4,6 +4,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import org.etsi.osl.tmf.metrics.PublishedServiceSpecifications; +import org.etsi.osl.tmf.metrics.RegisteredIndividuals; +import org.etsi.osl.tmf.metrics.RegisteredResourceSpecifications; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; @@ -24,7 +27,7 @@ public interface MetricsApi { @ApiResponse(responseCode = "500", description = "Internal Server Error") }) @RequestMapping(value = "/metrics/registeredIndividuals", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - ResponseEntity> getRegisteredIndividuals(); + ResponseEntity getRegisteredIndividuals(); @Operation(summary = "Get total number of published service specifications", operationId = "getPublishedServiceSpecifications") @ApiResponses(value = { @@ -33,7 +36,7 @@ public interface MetricsApi { @ApiResponse(responseCode = "500", description = "Internal Server Error") }) @RequestMapping(value = "/metrics/publishedServiceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - ResponseEntity> getPublishedServiceSpecifications(); + ResponseEntity getPublishedServiceSpecifications(); @Operation(summary = "Get total number of registered resource specifications", operationId = "getRegisteredResourceSpecifications") @ApiResponses(value = { @@ -42,5 +45,5 @@ public interface MetricsApi { @ApiResponse(responseCode = "500", description = "Internal Server Error") }) @RequestMapping(value = "/metrics/registeredResourceSpecifications", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - ResponseEntity> getRegisteredResourceSpecifications(); + ResponseEntity getRegisteredResourceSpecifications(); } diff --git a/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java index be8f980e..089f7252 100644 --- a/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java +++ b/src/main/java/org/etsi/osl/tmf/metrics/api/MetricsApiController.java @@ -1,5 +1,8 @@ package org.etsi.osl.tmf.metrics.api; +import org.etsi.osl.tmf.metrics.PublishedServiceSpecifications; +import org.etsi.osl.tmf.metrics.RegisteredIndividuals; +import org.etsi.osl.tmf.metrics.RegisteredResourceSpecifications; import org.etsi.osl.tmf.metrics.reposervices.MetricsRepoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,11 +27,10 @@ public class MetricsApiController implements MetricsApi { } @Override - public ResponseEntity> getRegisteredIndividuals() { + public ResponseEntity getRegisteredIndividuals() { try { int totalIndividuals = generalMetricsRepoService.countRegisteredIndividuals(); - Map response = new HashMap<>(); - response.put("registeredIndividuals", totalIndividuals); + RegisteredIndividuals response = new RegisteredIndividuals(totalIndividuals); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { log.error("Couldn't retrieve total registered individuals. ", e); @@ -37,11 +39,10 @@ public class MetricsApiController implements MetricsApi { } @Override - public ResponseEntity> getPublishedServiceSpecifications() { + public ResponseEntity getPublishedServiceSpecifications() { try { int totalSpecifications = generalMetricsRepoService.countPublishedServiceSpecifications(); - Map response = new HashMap<>(); - response.put("publishedServiceSpecifications", totalSpecifications); + PublishedServiceSpecifications response = new PublishedServiceSpecifications(totalSpecifications); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { log.error("Couldn't retrieve total published service specifications. ", e); @@ -50,11 +51,10 @@ public class MetricsApiController implements MetricsApi { } @Override - public ResponseEntity> getRegisteredResourceSpecifications() { + public ResponseEntity getRegisteredResourceSpecifications() { try { int totalResourceSpecifications = generalMetricsRepoService.countRegisteredResourceSpecifications(); - Map response = new HashMap<>(); - response.put("registeredResourceSpecifications", totalResourceSpecifications); + RegisteredResourceSpecifications response = new RegisteredResourceSpecifications(totalResourceSpecifications); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { log.error("Couldn't retrieve total registered resource specifications. ", e); -- GitLab