Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.requestMatchers("/actuator/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/api/**").permitAll()
.requestMatchers("/admin/**").authenticated()
.anyRequest().authenticated()
);
return http.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package br.com.fiap.vigisus.controller;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.search.Search;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Dashboard de monitoramento operacional — acesso restrito (requer autenticação).
* Disponível na porta de gestão (9090) e oculto do Swagger público.
*
* @Hidden oculta do Swagger público.
*/
@Hidden
@RestController
@RequestMapping("/admin")
@RequiredArgsConstructor
public class AdminDashboardController {

private final MeterRegistry meterRegistry;

/** Retorna top municípios mais buscados (nome, UF e contagem de buscas) */
@GetMapping("/top-municipios")
public List<Map<String, Object>> getTopMunicipios() {
return Search.in(meterRegistry)
.name("busca.municipio")
.counters()
.stream()
.map(counter -> {
String municipio = counter.getId().getTag("municipio");
String uf = counter.getId().getTag("uf");
long buscas = (long) counter.count();
return Map.<String, Object>of(
"municipio", municipio != null ? municipio : "",
"uf", uf != null ? uf : "",
"buscas", buscas);
})
.sorted(Comparator.comparingLong(m -> -((Long) m.get("buscas"))))
.limit(10)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import br.com.fiap.vigisus.application.busca.BuscaCompletaUseCase;
import br.com.fiap.vigisus.dto.BuscaCompletaResponse;
import br.com.fiap.vigisus.dto.BuscaRequest;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand All @@ -24,6 +26,7 @@
public class BuscaController {

private final BuscaCompletaUseCase buscaCompletaUseCase;
private final MeterRegistry meterRegistry;

@PostMapping
@Operation(
Expand All @@ -40,6 +43,11 @@ public ResponseEntity<BuscaCompletaResponse> buscarDireto(
@RequestParam String uf,
@RequestParam(defaultValue = "dengue") String doenca,
@RequestParam(required = false) Integer ano) {
Counter.builder("busca.municipio")
.tag("municipio", municipio)
.tag("uf", uf)
.register(meterRegistry)
.increment();
return ResponseEntity.ok(buscaCompletaUseCase.buscarDireto(municipio, uf, doenca, ano));
}
}
4 changes: 3 additions & 1 deletion backend/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ server:
port: 8080

management:
server:
port: 9090
endpoints:
web:
exposure:
include: health,info
include: health,info,metrics
endpoint:
health:
show-details: always
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package br.com.fiap.vigisus.controller;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

class AdminDashboardControllerTest {

private SimpleMeterRegistry meterRegistry;
private AdminDashboardController controller;

@BeforeEach
void setUp() {
meterRegistry = new SimpleMeterRegistry();
controller = new AdminDashboardController(meterRegistry);
}

@Test
void getTopMunicipios_retornaListaVaziaQuandoSemBuscas() {
List<Map<String, Object>> result = controller.getTopMunicipios();
assertThat(result).isEmpty();
}

@Test
void getTopMunicipios_retornaMunicipiosOrdenadosPorBuscas() {
Counter.builder("busca.municipio").tag("municipio", "Campinas").tag("uf", "SP").register(meterRegistry).increment();
Counter.builder("busca.municipio").tag("municipio", "Campinas").tag("uf", "SP").register(meterRegistry).increment();
Counter.builder("busca.municipio").tag("municipio", "Sao Paulo").tag("uf", "SP").register(meterRegistry).increment();

List<Map<String, Object>> result = controller.getTopMunicipios();

assertThat(result).hasSize(2);
assertThat(result.get(0).get("municipio")).isEqualTo("Campinas");
assertThat(result.get(0).get("buscas")).isEqualTo(2L);
assertThat(result.get(1).get("municipio")).isEqualTo("Sao Paulo");
assertThat(result.get(1).get("buscas")).isEqualTo(1L);
}

@Test
void getTopMunicipios_limita10Resultados() {
for (int i = 1; i <= 15; i++) {
Counter.builder("busca.municipio")
.tag("municipio", "Municipio" + i)
.tag("uf", "SP")
.register(meterRegistry)
.increment();
}

List<Map<String, Object>> result = controller.getTopMunicipios();

assertThat(result).hasSize(10);
}

@Test
void getTopMunicipios_incluiCampoUf() {
Counter.builder("busca.municipio").tag("municipio", "Manaus").tag("uf", "AM").register(meterRegistry).increment();

List<Map<String, Object>> result = controller.getTopMunicipios();

assertThat(result).hasSize(1);
assertThat(result.get(0).get("uf")).isEqualTo("AM");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import br.com.fiap.vigisus.dto.BuscaCompletaResponse;
import br.com.fiap.vigisus.dto.BuscaRequest;
import br.com.fiap.vigisus.exception.RecursoNaoEncontradoException;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand All @@ -20,7 +21,7 @@ class BuscaControllerTest {
@BeforeEach
void setUp() {
buscaCompletaUseCase = mock(BuscaCompletaUseCase.class);
controller = new BuscaController(buscaCompletaUseCase);
controller = new BuscaController(buscaCompletaUseCase, new SimpleMeterRegistry());
}

@Test
Expand Down