added metrics for prometheus
All checks were successful
CD / build-and-push (push) Successful in 3m48s
CD / deploy (push) Successful in 10s

This commit is contained in:
RM
2026-10-15 11:54:45 +03:00
parent 7438e2b57a
commit 76aa1ab253
3 changed files with 56 additions and 14 deletions

View File

@@ -88,6 +88,10 @@
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.17</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>

View File

@@ -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);

View File

@@ -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<String, Lot> 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<String, Lot> 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<String> cadastral = List.of(CADASTRAL);
try (MockedConstruction<SendEmailService> 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<SendEmailService> ignored = mockConstruction(SendEmailService.class,
(mock, context) -> doThrow(new RuntimeException("smtp failure"))
@@ -215,7 +216,7 @@ class DownloadHeadlessControllerTest {
lot.setCadastral(CADASTRAL);
Map<String, Lot> 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<String, Lot> 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<String, Lot> 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<String, Lot> 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")