From 549c38246b1abfbb89c3ab333104f06a9519d38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Maisse?= Date: Thu, 2 Nov 2023 14:44:46 +0100 Subject: [PATCH] fix: create a count method in AlertEvent repository and improve the way analytics are fetched in AlertService https://gravitee.atlassian.net/browse/APIM-3190 https://github.com/gravitee-io/issues/issues/9362 (cherry picked from commit 0583ec4c65800cdb33e3aac9a002a87569d13b30) # Conflicts: # gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/resources/scripts/create-index.js --- .../management/api/AlertEventRepository.java | 8 ++++ .../management/JdbcAlertEventRepository.java | 31 +++++++++++++ .../management/MongoAlertEventRepository.java | 5 ++ .../api/AlertEventMongoRepositoryCustom.java | 2 + .../api/AlertEventMongoRepositoryImpl.java | 34 ++++++++------ .../main/resources/scripts/create-index.js | 1 + .../management/AlertEventRepositoryTest.java | 18 ++++++++ .../data/alertevent-tests/alertEvents.json | 4 +- .../api/service/impl/AlertServiceImpl.java | 46 +++++++++---------- 9 files changed, 111 insertions(+), 38 deletions(-) diff --git a/gravitee-apim-repository/gravitee-apim-repository-api/src/main/java/io/gravitee/repository/management/api/AlertEventRepository.java b/gravitee-apim-repository/gravitee-apim-repository-api/src/main/java/io/gravitee/repository/management/api/AlertEventRepository.java index b308012ad29..e91db408de7 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-api/src/main/java/io/gravitee/repository/management/api/AlertEventRepository.java +++ b/gravitee-apim-repository/gravitee-apim-repository-api/src/main/java/io/gravitee/repository/management/api/AlertEventRepository.java @@ -38,6 +38,14 @@ public interface AlertEventRepository extends CrudRepository */ Page search(AlertEventCriteria criteria, Pageable pageable); + /** + * Counts the number of {@link AlertEvent}s that match the given criteria. + * + * @param criteria The criteria to match the {@link AlertEvent}s against. + * @return The number of {@link AlertEvent}s that match the given criteria. + */ + long count(AlertEventCriteria criteria); + /** * delete all events of the provided alert * @param alertId diff --git a/gravitee-apim-repository/gravitee-apim-repository-jdbc/src/main/java/io/gravitee/repository/jdbc/management/JdbcAlertEventRepository.java b/gravitee-apim-repository/gravitee-apim-repository-jdbc/src/main/java/io/gravitee/repository/jdbc/management/JdbcAlertEventRepository.java index 000786c15fb..322c53520e3 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-jdbc/src/main/java/io/gravitee/repository/jdbc/management/JdbcAlertEventRepository.java +++ b/gravitee-apim-repository/gravitee-apim-repository-jdbc/src/main/java/io/gravitee/repository/jdbc/management/JdbcAlertEventRepository.java @@ -122,6 +122,37 @@ public Page search(AlertEventCriteria criteria, Pageable pageable) { return getResultAsPage(pageable, events); } + @Override + public long count(AlertEventCriteria criteria) { + final List args = new ArrayList<>(); + final StringBuilder builder = new StringBuilder("select count(*) from " + this.tableName + " ev "); + + boolean started = false; + if (criteria.getFrom() > 0) { + builder.append(WHERE_CLAUSE); + builder.append("created_at >= ?"); + args.add(new Timestamp(criteria.getFrom())); + started = true; + } + if (criteria.getTo() > 0) { + builder.append(started ? AND_CLAUSE : WHERE_CLAUSE); + builder.append("created_at < ?"); + args.add(new Timestamp(criteria.getTo())); + started = true; + } + + if (criteria.getAlert() != null && !criteria.getAlert().isEmpty()) { + builder.append(started ? AND_CLAUSE : WHERE_CLAUSE); + builder.append("alert = ?"); + args.add(criteria.getAlert()); + } + + String sql = builder.toString(); + LOGGER.debug("SQL: {}", sql); + LOGGER.debug("Args: {}", args); + return jdbcTemplate.queryForObject(sql, args.toArray(), Long.class); + } + @Override public void deleteAll(String alertId) { jdbcTemplate.update("delete from " + this.tableName + " where alert = ?", alertId); diff --git a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/MongoAlertEventRepository.java b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/MongoAlertEventRepository.java index df3216ff1bd..ad909401f46 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/MongoAlertEventRepository.java +++ b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/MongoAlertEventRepository.java @@ -126,6 +126,11 @@ public Page search(AlertEventCriteria criteria, Pageable pageable) { ); } + @Override + public long count(AlertEventCriteria criteria) { + return internalAlertEventRepo.count(criteria); + } + @Override public Set findAll() throws TechnicalException { return internalAlertEventRepo.findAll().stream().map(alertEventMongo -> mapper.map(alertEventMongo)).collect(Collectors.toSet()); diff --git a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryCustom.java b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryCustom.java index 5b01c895b91..0b7711f816a 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryCustom.java +++ b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryCustom.java @@ -28,4 +28,6 @@ public interface AlertEventMongoRepositoryCustom { Page search(AlertEventCriteria criteria, Pageable pageable); void deleteAll(String alertId); + + long count(AlertEventCriteria criteria); } diff --git a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryImpl.java b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryImpl.java index 6c447d0d20f..8aae2830353 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryImpl.java +++ b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/java/io/gravitee/repository/mongodb/management/internal/api/AlertEventMongoRepositoryImpl.java @@ -40,22 +40,11 @@ public class AlertEventMongoRepositoryImpl implements AlertEventMongoRepositoryC @Override public Page search(AlertEventCriteria criteria, Pageable pageable) { - Query query = new Query(); - - if (criteria.getAlert() != null) { - query.addCriteria(Criteria.where("alert").is(criteria.getAlert())); - } - - // set range query - if (criteria.getFrom() != 0 && criteria.getTo() != 0) { - query.addCriteria(Criteria.where("createdAt").gte(new Date(criteria.getFrom())).lt(new Date(criteria.getTo()))); - } + Query query = buildQueryFromCriteria(criteria); + long total = mongoTemplate.count(query, AlertEventMongo.class); - // set sort by updated at query.with(Sort.by(Sort.Direction.DESC, "createdAt")); - long total = mongoTemplate.count(query, AlertEventMongo.class); - // set pageable if (pageable != null) { query.with(PageRequest.of(pageable.pageNumber(), pageable.pageSize())); @@ -71,4 +60,23 @@ public void deleteAll(String alertId) { Query query = new Query().addCriteria(Criteria.where("alert").is(alertId)); mongoTemplate.remove(query, AlertEventMongo.class); } + + @Override + public long count(AlertEventCriteria criteria) { + Query query = buildQueryFromCriteria(criteria); + return mongoTemplate.count(query, AlertEventMongo.class); + } + + private static Query buildQueryFromCriteria(AlertEventCriteria criteria) { + Query query = new Query(); + + if (criteria.getAlert() != null) { + query.addCriteria(Criteria.where("alert").is(criteria.getAlert())); + } + + if (criteria.getFrom() != 0 && criteria.getTo() != 0) { + query.addCriteria(Criteria.where("createdAt").gte(new Date(criteria.getFrom())).lt(new Date(criteria.getTo()))); + } + return query; + } } diff --git a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/resources/scripts/create-index.js b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/resources/scripts/create-index.js index 5dbb92819bd..7047ff50ad0 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/resources/scripts/create-index.js +++ b/gravitee-apim-repository/gravitee-apim-repository-mongodb/src/main/resources/scripts/create-index.js @@ -147,6 +147,7 @@ db.getCollection(`${prefix}alert_triggers`).reIndex(); db.getCollection(`${prefix}alert_events`).dropIndexes(); db.getCollection(`${prefix}alert_events`).createIndex({ alert: 1 }, { name: "a1" }); db.getCollection(`${prefix}alert_events`).createIndex({ createdAt: 1 }, { name: "c1" }); +db.getCollection(`${prefix}alert_events`).createIndex({"alert": 1, "createdAt": 1}, {"name": "a1c1"}); db.getCollection(`${prefix}alert_events`).reIndex(); // "customUserFields" collection diff --git a/gravitee-apim-repository/gravitee-apim-repository-test/src/test/java/io/gravitee/repository/management/AlertEventRepositoryTest.java b/gravitee-apim-repository/gravitee-apim-repository-test/src/test/java/io/gravitee/repository/management/AlertEventRepositoryTest.java index 1de6f73ba31..25858eacc14 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-test/src/test/java/io/gravitee/repository/management/AlertEventRepositoryTest.java +++ b/gravitee-apim-repository/gravitee-apim-repository-test/src/test/java/io/gravitee/repository/management/AlertEventRepositoryTest.java @@ -141,4 +141,22 @@ public void shouldDeleteAll() throws Exception { assertEquals("2 before", 2, before); assertEquals("0 after", 0, after); } + + @Test + public void shouldCountWithCriteria() { + long count = alertEventRepository.count( + new AlertEventCriteria.Builder().alert("alert-parent-id").from(1439022010900L).to(1439022010999L).build() + ); + assertEquals(1, count); + } + + @Test + public void shouldSearchWithCriteria() { + Page result = alertEventRepository.search( + new AlertEventCriteria.Builder().alert("alert-parent-id").from(1439022010900L).to(1439022010999L).build(), + null + ); + assertEquals(1, result.getTotalElements()); + assertEquals("an-alert-to-update", result.getContent().get(0).getId()); + } } diff --git a/gravitee-apim-repository/gravitee-apim-repository-test/src/test/resources/data/alertevent-tests/alertEvents.json b/gravitee-apim-repository/gravitee-apim-repository-test/src/test/resources/data/alertevent-tests/alertEvents.json index 4f9d664d6da..92948b0c651 100644 --- a/gravitee-apim-repository/gravitee-apim-repository-test/src/test/resources/data/alertevent-tests/alertEvents.json +++ b/gravitee-apim-repository/gravitee-apim-repository-test/src/test/resources/data/alertevent-tests/alertEvents.json @@ -9,8 +9,8 @@ "id": "an-alert-to-update", "alert": "alert-parent-id", "message": "Message of the alert to update", - "createdAt": 1439022010883, - "updatedAt": 1439022010883 + "createdAt": 1439022010920, + "updatedAt": 1439022010920 }, { "id": "latest-alert", diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/AlertServiceImpl.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/AlertServiceImpl.java index 580806ffe54..e539f9dc248 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/AlertServiceImpl.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/AlertServiceImpl.java @@ -334,23 +334,27 @@ public List findByReferenceWithEventCounts(final AlertRefere final Date from = new Date(System.currentTimeMillis()); - Map counters = new HashMap<>(); - counters.put( - "5m", - countEvents(entity.getId(), from.toInstant().minus(Duration.ofMinutes(5)).toEpochMilli(), from.getTime()) - ); - counters.put( - "1h", - countEvents(entity.getId(), from.toInstant().minus(Duration.ofHours(1)).toEpochMilli(), from.getTime()) - ); - counters.put( - "1d", - countEvents(entity.getId(), from.toInstant().minus(Duration.ofDays(1)).toEpochMilli(), from.getTime()) - ); - counters.put( - "1M", - countEvents(entity.getId(), from.toInstant().minus(Duration.ofDays(30)).toEpochMilli(), from.getTime()) - ); + Map counters = Map + .of( + "5m", + from.toInstant().minus(Duration.ofMinutes(5)), + "1h", + from.toInstant().minus(Duration.ofHours(1)), + "1d", + from.toInstant().minus(Duration.ofDays(1)), + "1M", + from.toInstant().minus(Duration.ofDays(30)) + ) + .entrySet() + // Get the count of events for each time period in parallel to speed up the process + .parallelStream() + .map(entry -> + new AbstractMap.SimpleEntry<>( + entry.getKey(), + countEvents(entity.getId(), entry.getValue().toEpochMilli(), from.getTime()) + ) + ) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); entity.setCounters(counters); return entity; @@ -796,12 +800,8 @@ private Map getPlanMetadata(String plan) { } private int countEvents(final String triggerId, final long from, final long to) { - return (int) alertEventRepository - .search( - new AlertEventCriteria.Builder().alert(triggerId).from(from).to(to).build(), - new PageableBuilder().pageNumber(0).pageSize(1).build() - ) - .getTotalElements(); + AlertEventCriteria criteria = new AlertEventCriteria.Builder().alert(triggerId).from(from).to(to).build(); + return Math.toIntExact(alertEventRepository.count(criteria)); } private Optional getLastEvent(final String triggerId) {