diff --git a/README.md b/README.md index f8a0a9f..aa1a97b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,44 @@ compilazione dei timesheet tenendo in considerazione vincoli e suggerimenti che UGov PJ UWeb Timesheet prevede la possibilità di inserire in una tabella di frontiera *Oracle* le informazioni relative a tempo a lavoro e assenze che vengono prelevate via REST da un server ePAS. +## Endpoint REST del servizio + +Questo servizio integra alcuni endpoint REST di amministrazione che permettono di lanciare su richiesta +nuova richieste di sincronizzazione dei dati, oltre a vari task di amministrazione. +Gli endpoint REST sono protetti tramite Basic Auth, con utente e password configurato tramite +le application.properties del servizio, oppure tramite le variabili d'ambiente +security.username,security.password nel caso di avvio tramite docker/docker-compose. + +# Visualizzazione task schedulati + +È possibile visualizzare le informazioni dei task cron schedulati per la sincronizzazone +delle informazioni tra ePAS e le tabelle Oracle di UGOV PJ UWeb Timesheet. + +L'endpoint da consultare è **/actuator/scheduledtasks**. + +## Metriche del servizio + +Il servizio esporta alcune metriche in formato Prometheus, è possibile consultarle all'endpoint +**/actuator/prometheus**. + +Le metriche presenti contengono anche le tempistiche di sincronizzazione di tutti i dati e dei +singoli uffici, del tipo: + +``` +# HELP epas_sync_office_month_seconds Timer della sincronizzazione dei dati di un mese di un ufficio +# TYPE epas_sync_office_month_seconds summary +epas_sync_office_month_seconds_count{officeId="2",yearMonth="2024-01",} 1.0 +epas_sync_office_month_seconds_sum{officeId="2",yearMonth="2024-01",} 0.237913661 +epas_sync_office_month_seconds_count{officeId="2",yearMonth="2023-12",} 1.0 +epas_sync_office_month_seconds_sum{officeId="2",yearMonth="2023-12",} 0.287619208 +epas_sync_office_month_seconds_count{officeId="1",yearMonth="2024-02",} 1.0 + +# HELP epas_sync_all_time_seconds Time taken to sync all the details +# TYPE epas_sync_all_time_seconds summary +epas_sync_all_time_seconds_count{class="it.cnr.iit.epas.timesheet.ugovpj.service.SyncService",exception="none",method="syncAll",} 1.0 +epas_sync_all_time_seconds_sum{class="it.cnr.iit.epas.timesheet.ugovpj.service.SyncService",exception="none",method="syncAll",} 6.734464188 +``` + ## 👏 Come Contribuire E' possibile contribuire a questo progetto utilizzando le modalità standard della comunità opensource @@ -25,4 +63,4 @@ E' possibile contribuire a questo progetto utilizzando le modalità standard del ePAS - UGov PJ UWeb Timesheet è concesso in licenza GNU AFFERO GENERAL PUBLIC LICENSE, come si trova nel file [LICENSE][l]. -[l]: https://github.com/consiglionazionaledellericerche/epas-ugov-pj-timesheet/blob/master/LICENSE +[l]: https://github.com/consiglionazionaledellericerche/epas-ugov-pj-timesheet/blob/master/LICENSE \ No newline at end of file diff --git a/pom.xml b/pom.xml index 141a0c1..f4ff6e5 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,14 @@ org.springframework.boot spring-boot-starter-quartz + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-aop + org.flywaydb flyway-core diff --git a/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/SecurityFilter.java b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/SecurityFilter.java index bf52a21..c9e37b7 100644 --- a/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/SecurityFilter.java +++ b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/SecurityFilter.java @@ -21,6 +21,7 @@ import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -64,6 +65,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .authorizeHttpRequests(authorize -> authorize .requestMatchers("/v3/api-docs/**", "/swagger-ui/**").permitAll() .anyRequest().authenticated()) + .csrf(AbstractHttpConfigurer::disable) .httpBasic(Customizer.withDefaults()); return http.build(); } diff --git a/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/TimedAspectForPrometheus.java b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/TimedAspectForPrometheus.java new file mode 100644 index 0000000..d209d93 --- /dev/null +++ b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/config/TimedAspectForPrometheus.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Consiglio Nazionale delle Ricerche + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.cnr.iit.epas.timesheet.ugovpj.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.aop.TimedAspect; +import io.micrometer.core.instrument.MeterRegistry; + +/** + * Registra il tempo delle invocazioni dei metodi in modo che possa + * essere utilizzato dal Prometheus. + */ +@Configuration +public class TimedAspectForPrometheus { + + @Bean + public TimedAspect timedAspect(MeterRegistry registry) { + return new TimedAspect(registry); + } + +} \ No newline at end of file diff --git a/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/service/SyncService.java b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/service/SyncService.java index 5d665e2..db4b315 100644 --- a/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/service/SyncService.java +++ b/src/main/java/it/cnr/iit/epas/timesheet/ugovpj/service/SyncService.java @@ -16,9 +16,24 @@ */ package it.cnr.iit.epas.timesheet.ugovpj.service; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; + +import io.micrometer.core.annotation.Timed; +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; import it.cnr.iit.epas.timesheet.ugovpj.client.EpasClient; import it.cnr.iit.epas.timesheet.ugovpj.client.dto.PersonDayShowTerseDto; import it.cnr.iit.epas.timesheet.ugovpj.client.dto.PersonMonthRecapDto; @@ -28,17 +43,9 @@ import it.cnr.iit.epas.timesheet.ugovpj.model.TimeDetailType; import it.cnr.iit.epas.timesheet.ugovpj.repo.PersonTimeDetailRepo; import it.cnr.iit.epas.timesheet.ugovpj.repo.TimeDetailTypeRepo; -import java.time.LocalDate; -import java.time.YearMonth; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.val; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; /** * Servizio con i metodi che effettuano la sincronizzazione dei dati del tempo a lavoro @@ -57,6 +64,8 @@ public class SyncService { private final EpasClient epasClient; private final TimesheetConfig timesheetConfig; + private final MeterRegistry meterRegistry; + /** * Sincronizza il dato del tempo a lavoro di una persona in un giorno specifico. */ @@ -150,6 +159,7 @@ public List syncOfficeMonth( log.debug("Inizio sincronizzazione dell'ufficio id={} del {}, notBefore={}", officeId, yearMonth, notBefore); long startTime = System.currentTimeMillis(); + Timer.Sample timer = Timer.start(meterRegistry); List details = Lists.newArrayList(); val monthRecaps = epasClient.getMonthRecap(officeId, yearMonth.getYear(), yearMonth.getMonthValue()); monthRecaps.forEach(monthRecap -> { @@ -157,6 +167,11 @@ public List syncOfficeMonth( }); log.info("Terminata sincronizzazione dell'ufficio id={} del {} in {} secondi", officeId, yearMonth, ((System.currentTimeMillis() - startTime) / 1000)); + timer.stop(Timer.builder("epas_sync_office_month") + .description("Timer della sincronizzazione dei dati di un mese di un ufficio") + .tag("officeId", String.valueOf(officeId)) + .tag("yearMonth", yearMonth.toString()) + .register(meterRegistry)); return details; } @@ -173,6 +188,7 @@ public List syncMonth(YearMonth yearMonth, Optional return details; } + @Timed(value = "epas_sync_all_time", description = "Time taken to sync all the details") public List syncAll() { List details = Lists.newArrayList(); LocalDate startingDate = LocalDate.now().minusDays(timesheetConfig.getDaysInThePast()); @@ -180,9 +196,12 @@ public List syncAll() { log.info("Starting synchronization since {}", startingDate); YearMonth yearMonth = YearMonth.from(startingDate); while (!yearMonth.isAfter(YearMonth.from(LocalDate.now()))) { - syncMonth(yearMonth, Optional.of(startingDate)); + details.addAll(syncMonth(yearMonth, Optional.of(startingDate))); yearMonth = yearMonth.plusMonths(1); } + Gauge.builder("epas_synch_details_count", () -> details.size()) + .description("A current number of books in the system") + .register(meterRegistry); log.info("Synchronization ended in {} seconds", ((System.currentTimeMillis() - startTime) / 1000)); return details; } @@ -190,5 +209,4 @@ public List syncAll() { private Set timeDetailTypes() { return typeRepo.findAll().stream().map(TimeDetailType::getCode).collect(Collectors.toSet()); } - } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8ea5b69..ca15a58 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,6 +19,8 @@ springdoc.packagesToScan=it.cnr.iit.epas.timesheet #logging logging.level.it.cnr.iit.epas=DEBUG +management.endpoints.web.exposure.include=info,health,prometheus,scheduledtasks + #Impostazioni dell'applicazione # Informazioni per l'accesso di questo servizio ai servizi REST di ePAS