diff --git a/pom.xml b/pom.xml index f975e64..9027928 100644 --- a/pom.xml +++ b/pom.xml @@ -88,6 +88,10 @@ springdoc-openapi-starter-webmvc-ui 2.8.17 + + io.micrometer + micrometer-registry-prometheus + com.fasterxml.jackson.core jackson-databind diff --git a/src/main/java/com/pledge/torgi/controller/DownloadHeadlessController.java b/src/main/java/com/pledge/torgi/controller/DownloadHeadlessController.java index 5ea169b..fd84fcf 100644 --- a/src/main/java/com/pledge/torgi/controller/DownloadHeadlessController.java +++ b/src/main/java/com/pledge/torgi/controller/DownloadHeadlessController.java @@ -8,6 +8,8 @@ import com.pledge.torgi.service.DownloadHeadlessService; import com.pledge.torgi.service.Lot; import com.pledge.torgi.service.SendEmailService; import com.pledge.torgi.utils.StartParams; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.PageRequest; @@ -17,8 +19,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.time.Instant; import java.time.LocalDate; import java.util.*; +import java.util.concurrent.atomic.AtomicLong; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -34,12 +38,21 @@ public class DownloadHeadlessController { private final TorgiEventRepository eventRepository; private final MissedDataRepository missedDataRepository; private final DownloadHeadlessService downloadHeadlessService; + private final Counter diffAdded; + private final Counter missedAdded; + private final AtomicLong lastPollTimestamp; public DownloadHeadlessController(TorgiEventRepository eventRepository, MissedDataRepository missedDataRepository, - DownloadHeadlessService downloadHeadlessService) { + DownloadHeadlessService downloadHeadlessService, MeterRegistry meterRegistry) { this.eventRepository = eventRepository; this.missedDataRepository = missedDataRepository; this.downloadHeadlessService = downloadHeadlessService; + this.diffAdded = Counter.builder("torgi.events.added").tag("source", "diff") + .description("Torgi events added from scheduled diff").register(meterRegistry); + this.missedAdded = Counter.builder("torgi.events.added").tag("source", "missed") + .description("Torgi events added from missed-data queue").register(meterRegistry); + this.lastPollTimestamp = new AtomicLong(0); + meterRegistry.gauge("torgi.last.poll.timestamp", lastPollTimestamp); eventRepository.findAllByOrderByCreatedAtDesc(PageRequest.of(0, 10000)).forEach(event -> content.add(event.getKey())); } @@ -57,9 +70,11 @@ public class DownloadHeadlessController { newEvents.add(new TorgiEvent(key, currentContent.get(key))); content.add(key); businessLogger.info("added new diff content"); + diffAdded.increment(); } } eventRepository.saveAll(newEvents); + lastPollTimestamp.set(Instant.now().getEpochSecond()); businessLogger.info("completeProcessing readed from torgi = {}, added to DB = {}", currentContent.size(), newEvents.size()); } @@ -156,6 +171,7 @@ public class DownloadHeadlessController { newEvents.add(new TorgiEvent(key, currentContent.get(key))); content.add(key); businessLogger.info("added new missed content"); + missedAdded.increment(); } } eventRepository.saveAll(newEvents); diff --git a/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java b/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java index c616d22..22e6812 100644 --- a/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java +++ b/src/test/java/com/pledge/torgi/controller/DownloadHeadlessControllerTest.java @@ -8,6 +8,7 @@ import com.pledge.torgi.service.DownloadHeadlessService; import com.pledge.torgi.service.Lot; import com.pledge.torgi.service.SendEmailService; import com.pledge.torgi.utils.StartParams; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -76,7 +77,7 @@ class DownloadHeadlessControllerTest { .thenReturn(page); // when - new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // then verify(eventRepository).findAllByOrderByCreatedAtDesc(any(PageRequest.class)); @@ -93,7 +94,7 @@ class DownloadHeadlessControllerTest { .thenReturn(new PageImpl<>(List.of(event1, event2))); // when - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // then assertThat(getContent(controller)).containsExactlyInAnyOrder("key-1", "key-2"); @@ -110,7 +111,7 @@ class DownloadHeadlessControllerTest { lot.setFullInfo("Full info"); Map downloaded = Map.of(EVENT_KEY, lot); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.process(); @@ -138,7 +139,7 @@ class DownloadHeadlessControllerTest { .thenReturn(new PageImpl<>(List.of(existing))); Map downloaded = Map.of(EVENT_KEY, new Lot()); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.process(); @@ -159,7 +160,7 @@ class DownloadHeadlessControllerTest { List cadastral = List.of(CADASTRAL); try (MockedConstruction emailConstruction = mockConstruction(SendEmailService.class)) { - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.sendNewContent(params, cadastral, "to@example.com"); @@ -186,7 +187,7 @@ class DownloadHeadlessControllerTest { StartParams params = new StartParams(); params.setFrom("from@example.com"); params.setToken("token"); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); try (MockedConstruction ignored = mockConstruction(SendEmailService.class, (mock, context) -> doThrow(new RuntimeException("smtp failure")) @@ -215,7 +216,7 @@ class DownloadHeadlessControllerTest { lot.setCadastral(CADASTRAL); Map downloaded = Map.of(EVENT_KEY, lot); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.richData(); @@ -241,7 +242,7 @@ class DownloadHeadlessControllerTest { Map downloaded = Map.of(EVENT_KEY, new Lot()); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.richData(); @@ -260,7 +261,7 @@ class DownloadHeadlessControllerTest { missed.setCadastral(CADASTRAL); when(missedDataRepository.findAll(any(PageRequest.class))).thenReturn(new PageImpl<>(List.of(missed))); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(Collections.emptyMap()); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.richData(); @@ -281,7 +282,7 @@ class DownloadHeadlessControllerTest { Map downloaded = Map.of(EVENT_KEY, new Lot()); when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when controller.richData(); @@ -295,7 +296,7 @@ class DownloadHeadlessControllerTest { void richData_shouldHandleExceptionGracefully() { // given when(missedDataRepository.findAll(any(PageRequest.class))).thenThrow(new RuntimeException("Database error")); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when / then assertThatCode(controller::richData).doesNotThrowAnyException(); @@ -308,7 +309,7 @@ class DownloadHeadlessControllerTest { File deeper = new File(nested, "deeper"); assertThat(deeper.mkdirs()).isTrue(); writeFile(new File(deeper, "file.txt"), "content"); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); // when boolean result = invokeDeleteDirectory(controller, nested); @@ -371,7 +372,7 @@ class DownloadHeadlessControllerTest { File nested = new File(sourceDir, "nested"); assertThat(nested.mkdirs()).isTrue(); writeFile(new File(nested, "data.txt"), "archive-content"); - DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, new SimpleMeterRegistry()); try { // when @@ -388,6 +389,27 @@ class DownloadHeadlessControllerTest { } } + @Test + void process_shouldIncrementMetrics() throws Exception { + // given + Lot lot = new Lot(); + lot.setStatus("PUBLISHED"); + lot.setNotice("Notice1"); + lot.setLotNumber(1); + lot.setCadastral(CADASTRAL); + Map downloaded = Map.of(EVENT_KEY, lot); + when(downloadHeadlessService.downloadExcel(anyString())).thenReturn(downloaded); + SimpleMeterRegistry registry = new SimpleMeterRegistry(); + DownloadHeadlessController controller = new DownloadHeadlessController(eventRepository, missedDataRepository, downloadHeadlessService, registry); + + // when + controller.process(); + + // then + assertThat(registry.get("torgi.events.added").tag("source", "diff").counter().count()).isEqualTo(1.0); + assertThat(registry.get("torgi.last.poll.timestamp").gauge().value()).isGreaterThan(0.0); + } + // Helpers @SuppressWarnings("unchecked")