package eu.eudat.logic.managers; import eu.eudat.data.dao.criteria.*; import eu.eudat.data.entities.DatasetProfile; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.utilities.helpers.StreamDistinctBy; import eu.eudat.types.MetricNames; import io.micrometer.prometheus.PrometheusMeterRegistry; import io.prometheus.client.Gauge; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.transaction.Transactional; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @Component public class MetricsManager { private final static Logger logger = LoggerFactory.getLogger(MetricsManager.class); private final Map gauges; public void increaseValue(String name, int amount, String label) { if(label != null) { gauges.get(name).labels(label).inc(amount); } else { gauges.get(name).inc(amount); } } public void decreaseValue(String name, int amount, String label) { if(label != null) { gauges.get(name).labels(label).dec(amount); } else { gauges.get(name).dec(amount); } } public Integer getValue(String name, String label) { if(label != null) { return Double.valueOf(gauges.get(name).labels(label).get()).intValue(); } else { return Double.valueOf(gauges.get(name).get()).intValue(); } } public void calculateValue(String name, int amount, String label) { Integer orig = getValue(name, label); int diff = orig - amount; if (diff != 0) { if (diff > 0) { decreaseValue(name, diff, label); } else { increaseValue(name, Math.abs(diff), label); } } } private final ApiContext apiContext; private final UserManager userManager; private final Environment environment; @Autowired public MetricsManager(ApiContext apiContext, UserManager userManager, Environment environment, PrometheusMeterRegistry registry) { this.apiContext = apiContext; this.userManager = userManager; this.environment = environment; registry.clear(); this.gauges = Stream.of( new Object[][]{ {MetricNames.DMP, Gauge.build().name(MetricNames.DMP).help("Number of managed DMPs").labelNames("status").register(registry.getPrometheusRegistry())}, {MetricNames.FUNDERS, Gauge.build().name(MetricNames.FUNDERS).help("Number of registered Funders").register(registry.getPrometheusRegistry())}, {MetricNames.GRANTS, Gauge.build().name(MetricNames.GRANTS).help("Number of registered Grants").register(registry.getPrometheusRegistry())}, {MetricNames.PROJECT, Gauge.build().name(MetricNames.PROJECT).help("Number of registered Projects").register(registry.getPrometheusRegistry())}, {MetricNames.RESEARCHER, Gauge.build().name(MetricNames.RESEARCHER).help("Number of Colaborators/Researchers").register(registry.getPrometheusRegistry())}, {MetricNames.DATASET, Gauge.build().name(MetricNames.DATASET).help("Number of managed Dataset Descriptions").labelNames("status").register(registry.getPrometheusRegistry())}, {MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates").labelNames("status").register(registry.getPrometheusRegistry())}, {MetricNames.USERS, Gauge.build().name(MetricNames.USERS).help("Number of users").labelNames("type").register(registry.getPrometheusRegistry())}, {MetricNames.LANGUAGES, Gauge.build().name(MetricNames.LANGUAGES).help("Number of Languages").register(registry.getPrometheusRegistry())}, }).collect(Collectors.toMap(data -> (String)data[0], data -> (Gauge) data[1])); } @PostConstruct @Transactional @Scheduled(initialDelay = 1000 * 60 * 60, fixedDelay = 1000 * 60 * 60) public void init() throws IOException { logger.info("Start calculating Metrics"); calculateValue(MetricNames.DMP, (int) countAllDraftDMPs(), MetricNames.DRAFT); calculateValue(MetricNames.DMP, (int) countAllFinalizedDMPs(), MetricNames.FINALIZED); calculateValue(MetricNames.DMP, (int) countAllPublishedDMPs(), MetricNames.PUBLISHED); calculateValue(MetricNames.DMP, (int) countAllDoiedDMPs(), MetricNames.DOIED); calculateValue(MetricNames.FUNDERS, (int) countAllFunders(), null); calculateValue(MetricNames.GRANTS, (int) countAllGrants(), null); calculateValue(MetricNames.PROJECT, (int) countAllProjects(), null); calculateValue(MetricNames.RESEARCHER, (int) countAllResearchers(), null); calculateValue(MetricNames.DATASET, (int) countAllDraftDatasets(), MetricNames.DRAFT); calculateValue(MetricNames.DATASET, (int) countAllFinalizedDatasets(), MetricNames.FINALIZED); calculateValue(MetricNames.DATASET, (int) countAllPublicDatasets(), MetricNames.PUBLISHED); calculateValue(MetricNames.DATASET, (int) countAllDatasetsWithDoi(), MetricNames.DOIED); calculateValue(MetricNames.DATASET_TEMPLATE, (int) countAllDraftTemplates(), MetricNames.DRAFT); calculateValue(MetricNames.DATASET_TEMPLATE, (int) countAllFinalizedTemplates(), MetricNames.ACTIVE); calculateValue(MetricNames.DATASET_TEMPLATE, (int) countAllUsedTemplates(), MetricNames.USED); calculateValue(MetricNames.USERS, (int) userManager.countActiveUsers().intValue(), MetricNames.LOGGEDIN); calculateValue(MetricNames.USERS, (int) userManager.countAllUsers().intValue(), MetricNames.TOTAL); long files = Files.list(Paths.get(this.environment.getProperty("userguide.path"))).count(); calculateValue(MetricNames.LANGUAGES, (int) files, null); logger.info("Metrics calculation Completed"); } private long countAllDraftDMPs() { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); criteria.setStatus(0); return apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).count(); } private long countAllFinalizedDMPs() { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); criteria.setStatus(1); return apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).count(); } private long countAllPublishedDMPs() { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); criteria.setIsPublic(true); criteria.setOnlyPublic(true); return apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).count(); } private long countAllDoiedDMPs() { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); criteria.setHasDoi(true); return apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria).count(); } private long countAllResearchers() { ResearcherCriteria criteria = new ResearcherCriteria(); return apiContext.getOperationsContext().getDatabaseRepository().getResearcherDao().getWithCriteria(criteria).count(); } private long countAllProjects() { ProjectCriteria criteria = new ProjectCriteria(); return apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getWithCritetia(criteria).count(); } private long countAllFunders() { FunderCriteria criteria = new FunderCriteria(); return apiContext.getOperationsContext().getDatabaseRepository().getFunderDao().getWithCritetia(criteria).count(); } private long countAllGrants() { GrantCriteria criteria = new GrantCriteria(); return apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().getWithCriteria(criteria).count(); } public long countAllDraftDatasets() { eu.eudat.data.dao.criteria.DatasetCriteria criteria = new eu.eudat.data.dao.criteria.DatasetCriteria(); criteria.setStatus(0); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(criteria).count(); } public long countAllFinalizedDatasets() { eu.eudat.data.dao.criteria.DatasetCriteria criteria = new eu.eudat.data.dao.criteria.DatasetCriteria(); criteria.setStatus(1); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(criteria).count(); } public long countAllPublicDatasets() { eu.eudat.data.dao.criteria.DatasetCriteria criteria = new eu.eudat.data.dao.criteria.DatasetCriteria(); criteria.setIsPublic(true); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(criteria).count(); } public long countAllDatasetsWithDoi() { eu.eudat.data.dao.criteria.DatasetCriteria criteria = new eu.eudat.data.dao.criteria.DatasetCriteria(); criteria.setHasDoi(true); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(criteria).count(); } public long countAllDraftTemplates() { DatasetProfileCriteria criteria = new DatasetProfileCriteria(); criteria.setStatus(0); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).count(); } public long countAllFinalizedTemplates() { DatasetProfileCriteria criteria = new DatasetProfileCriteria(); criteria.setStatus(1); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).count(); } @Transactional public long countAllUsedTemplates() { DatasetProfileCriteria criteria = new DatasetProfileCriteria(); criteria.setStatus(1); criteria.setAllVersions(false); List datasetProfiles = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).toList(); List filteredProfiles = new ArrayList<>(); for (DatasetProfile datasetProfile : datasetProfiles) { DatasetCriteria datasetCriteria = new DatasetCriteria(); datasetCriteria.setDatasetTemplates(Collections.singletonList(datasetProfile.getId())); Long datasetCount = apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(datasetCriteria).count(); if (datasetCount > 0) { filteredProfiles.add(datasetProfile); } } return filteredProfiles.stream().filter(StreamDistinctBy.distinctByKey(DatasetProfile::getId)).count(); } }