created prometheus reports and /metrics
This commit is contained in:
parent
84df31c87a
commit
500c379b8c
25
pom.xml
25
pom.xml
|
@ -295,6 +295,31 @@
|
||||||
<version>2.26.0</version>
|
<version>2.26.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Enable micrometer >> -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-actuator</artifactId>
|
||||||
|
<version>2.1.18.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
|
||||||
|
<version>2.1.18.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-core</artifactId>
|
||||||
|
<version>1.7.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||||
|
<version>1.7.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- << Enable micrometer -->
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -60,11 +60,14 @@ public class AaiSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.csrf().disable()
|
http
|
||||||
.anonymous().disable()
|
.csrf().disable()
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.anyRequest().authenticated()
|
.regexMatchers("/actuator/.*").permitAll()
|
||||||
|
.regexMatchers("/metrics").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
|
// .anonymous().disable()
|
||||||
.httpBasic()
|
.httpBasic()
|
||||||
.authenticationEntryPoint(authenticationEntryPoint())
|
.authenticationEntryPoint(authenticationEntryPoint())
|
||||||
.and()
|
.and()
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package eu.dnetlib.repo.manager.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration;
|
||||||
|
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||||
|
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||||
|
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
|
||||||
|
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebMvc
|
||||||
|
@Import({
|
||||||
|
EndpointAutoConfiguration.class,
|
||||||
|
PublicMetricsAutoConfiguration.class,
|
||||||
|
// HealthIndicatorAutoConfiguration.class
|
||||||
|
})
|
||||||
|
|
||||||
|
public class ActuatorConfig { // TODO: remove this with migration to Spring Boot 2
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Autowired
|
||||||
|
public EndpointHandlerMapping endpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
|
||||||
|
return new EndpointHandlerMapping(endpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Autowired
|
||||||
|
public EndpointMvcAdapter metricsEndPoint(MetricsEndpoint delegate) {
|
||||||
|
return new EndpointMvcAdapter(delegate);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package eu.dnetlib.repo.manager.controllers;
|
||||||
|
|
||||||
|
import eu.dnetlib.repo.manager.service.PiWikService;
|
||||||
|
import io.micrometer.core.instrument.binder.jvm.DiskSpaceMetrics;
|
||||||
|
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
|
||||||
|
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
|
||||||
|
import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
|
||||||
|
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
|
||||||
|
import io.micrometer.core.instrument.binder.system.UptimeMetrics;
|
||||||
|
import io.micrometer.prometheus.PrometheusConfig;
|
||||||
|
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||||
|
import io.prometheus.client.exporter.common.TextFormat;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/actuator/prometheus")
|
||||||
|
public class PrometheusController { // TODO: remove this with migration to Spring Boot 2
|
||||||
|
|
||||||
|
private final PiWikService piWikService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public PrometheusController(PiWikService piWikService) {
|
||||||
|
this.piWikService = piWikService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||||
|
public String getPiwikMetrics() {
|
||||||
|
PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
|
||||||
|
registry.counter("total").increment(piWikService.getTotal());
|
||||||
|
registry.counter("validated").increment(piWikService.getValidated(true));
|
||||||
|
|
||||||
|
return registry.scrape(TextFormat.CONTENT_TYPE_004);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, path = "metrics", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||||
|
public String getMetrics() {
|
||||||
|
PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
|
||||||
|
new JvmThreadMetrics().bindTo(registry);
|
||||||
|
new JvmGcMetrics().bindTo(registry);
|
||||||
|
new JvmMemoryMetrics().bindTo(registry);
|
||||||
|
new DiskSpaceMetrics(new File("/")).bindTo(registry);
|
||||||
|
new ProcessorMetrics().bindTo(registry); // metrics related to the CPU stats
|
||||||
|
new UptimeMetrics().bindTo(registry);
|
||||||
|
|
||||||
|
return registry.scrape(TextFormat.CONTENT_TYPE_004);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,4 +27,8 @@ public interface PiWikService {
|
||||||
ResponseEntity<Object> markPiwikSiteAsValidated(String repositoryId) throws RepositoryServiceException;
|
ResponseEntity<Object> markPiwikSiteAsValidated(String repositoryId) throws RepositoryServiceException;
|
||||||
|
|
||||||
PiwikInfo enableMetricsForRepository(String officialName, String repoWebsite, PiwikInfo piwikInfo) throws RepositoryServiceException;
|
PiwikInfo enableMetricsForRepository(String officialName, String repoWebsite, PiwikInfo piwikInfo) throws RepositoryServiceException;
|
||||||
|
|
||||||
|
Integer getTotal();
|
||||||
|
|
||||||
|
Integer getValidated(boolean validated);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,9 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PiwikInfo getPiwikSiteForRepo(String repositoryId) {
|
public PiwikInfo getPiwikSiteForRepo(String repositoryId) {
|
||||||
try{
|
try {
|
||||||
return new JdbcTemplate(dataSource).queryForObject(GET_PIWIK_SITE, new String[]{repositoryId}, new int[]{Types.VARCHAR}, piwikRowMapper);
|
return new JdbcTemplate(dataSource).queryForObject(GET_PIWIK_SITE, new String[]{repositoryId}, new int[]{Types.VARCHAR}, piwikRowMapper);
|
||||||
}catch (EmptyResultDataAccessException e){
|
} catch (EmptyResultDataAccessException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,59 +86,59 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PiwikInfo> getPiwikSitesForRepos(OrderByField orderByField, OrderByType orderByType, int from, int quantity, String searchField) {
|
public List<PiwikInfo> getPiwikSitesForRepos(OrderByField orderByField, OrderByType orderByType, int from, int quantity, String searchField) {
|
||||||
try{
|
try {
|
||||||
String finalizedQuery = GET_PIWIK_SITES + " where ("+
|
String finalizedQuery = GET_PIWIK_SITES + " where (" +
|
||||||
" repositoryid ilike ? " +
|
" repositoryid ilike ? " +
|
||||||
" or siteid ilike ?" +
|
" or siteid ilike ?" +
|
||||||
" or requestorname ilike ?" +
|
" or requestorname ilike ?" +
|
||||||
" or requestoremail ilike ?" +
|
" or requestoremail ilike ?" +
|
||||||
" or comment ilike ?" +
|
" or comment ilike ?" +
|
||||||
" or repositoryname ilike ?"+
|
" or repositoryname ilike ?" +
|
||||||
" or country ilike ?"
|
" or country ilike ?"
|
||||||
+") order by "+orderByField + " " + orderByType + " offset ? limit ?";
|
+ ") order by " + orderByField + " " + orderByType + " offset ? limit ?";
|
||||||
|
|
||||||
return new JdbcTemplate(dataSource).query(finalizedQuery, preparedStatement -> {
|
return new JdbcTemplate(dataSource).query(finalizedQuery, preparedStatement -> {
|
||||||
preparedStatement.setString(1,"%"+searchField+"%");
|
preparedStatement.setString(1, "%" + searchField + "%");
|
||||||
preparedStatement.setString(2,"%"+searchField+"%");
|
preparedStatement.setString(2, "%" + searchField + "%");
|
||||||
preparedStatement.setString(3,"%"+searchField+"%");
|
preparedStatement.setString(3, "%" + searchField + "%");
|
||||||
preparedStatement.setString(4,"%"+searchField+"%");
|
preparedStatement.setString(4, "%" + searchField + "%");
|
||||||
preparedStatement.setString(5,"%"+searchField+"%");
|
preparedStatement.setString(5, "%" + searchField + "%");
|
||||||
preparedStatement.setString(6,"%"+searchField+"%");
|
preparedStatement.setString(6, "%" + searchField + "%");
|
||||||
preparedStatement.setString(7,"%"+searchField+"%");
|
preparedStatement.setString(7, "%" + searchField + "%");
|
||||||
preparedStatement.setInt(8,from);
|
preparedStatement.setInt(8, from);
|
||||||
preparedStatement.setInt(9,quantity);
|
preparedStatement.setInt(9, quantity);
|
||||||
}, piwikRowMapper);
|
}, piwikRowMapper);
|
||||||
}catch (EmptyResultDataAccessException e){
|
} catch (EmptyResultDataAccessException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPiwikSitesTotals(String searchField){
|
public int getPiwikSitesTotals(String searchField) {
|
||||||
try{
|
try {
|
||||||
String finalizedQuery = GET_PIWIK_SITES_TOTAL + " where ("+
|
String finalizedQuery = GET_PIWIK_SITES_TOTAL + " where (" +
|
||||||
" repositoryid ilike ? " +
|
" repositoryid ilike ? " +
|
||||||
" or siteid ilike ?" +
|
" or siteid ilike ?" +
|
||||||
" or requestorname ilike ?" +
|
" or requestorname ilike ?" +
|
||||||
" or requestoremail ilike ?" +
|
" or requestoremail ilike ?" +
|
||||||
" or comment ilike ?" +
|
" or comment ilike ?" +
|
||||||
" or repositoryname ilike ?"+
|
" or repositoryname ilike ?" +
|
||||||
" or country ilike ?)";
|
" or country ilike ?)";
|
||||||
|
|
||||||
return new JdbcTemplate(dataSource).query(finalizedQuery, preparedStatement -> {
|
return new JdbcTemplate(dataSource).query(finalizedQuery, preparedStatement -> {
|
||||||
preparedStatement.setString(1,"%"+searchField+"%");
|
preparedStatement.setString(1, "%" + searchField + "%");
|
||||||
preparedStatement.setString(2,"%"+searchField+"%");
|
preparedStatement.setString(2, "%" + searchField + "%");
|
||||||
preparedStatement.setString(3,"%"+searchField+"%");
|
preparedStatement.setString(3, "%" + searchField + "%");
|
||||||
preparedStatement.setString(4,"%"+searchField+"%");
|
preparedStatement.setString(4, "%" + searchField + "%");
|
||||||
preparedStatement.setString(5,"%"+searchField+"%");
|
preparedStatement.setString(5, "%" + searchField + "%");
|
||||||
preparedStatement.setString(6,"%"+searchField+"%");
|
preparedStatement.setString(6, "%" + searchField + "%");
|
||||||
preparedStatement.setString(7,"%"+searchField+"%");
|
preparedStatement.setString(7, "%" + searchField + "%");
|
||||||
},rowMapper -> {
|
}, rowMapper -> {
|
||||||
rowMapper.next();
|
rowMapper.next();
|
||||||
return rowMapper.getInt("totals");
|
return rowMapper.getInt("totals");
|
||||||
});
|
});
|
||||||
}catch (EmptyResultDataAccessException e){
|
} catch (EmptyResultDataAccessException e) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasAuthority('SUPER_ADMINISTRATOR') or hasAuthority('CONTENT_PROVIDER_DASHBOARD_ADMINISTRATOR')")
|
@PreAuthorize("hasAuthority('SUPER_ADMINISTRATOR') or hasAuthority('CONTENT_PROVIDER_DASHBOARD_ADMINISTRATOR')")
|
||||||
public ResponseEntity<Object> approvePiwikSite(String repositoryId) {
|
public ResponseEntity<Object> approvePiwikSite(String repositoryId) {
|
||||||
new JdbcTemplate(dataSource).update(APPROVE_PIWIK_SITE, new Object[] {repositoryId}, new int[] {Types.VARCHAR});
|
new JdbcTemplate(dataSource).update(APPROVE_PIWIK_SITE, new Object[]{repositoryId}, new int[]{Types.VARCHAR});
|
||||||
return new ResponseEntity<>("OK",HttpStatus.OK);
|
return new ResponseEntity<>("OK", HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -175,7 +175,7 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
LOGGER.error("Error while sending email to administrator or user about the enabling of metrics", e);
|
LOGGER.error("Error while sending email to administrator or user about the enabling of metrics", e);
|
||||||
emailUtils.reportException(e);
|
emailUtils.reportException(e);
|
||||||
}
|
}
|
||||||
return new ResponseEntity<>("OK",HttpStatus.OK);
|
return new ResponseEntity<>("OK", HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,7 +188,7 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
+ URLEncoder.encode(repoWebsite, "UTF-8");
|
+ URLEncoder.encode(repoWebsite, "UTF-8");
|
||||||
Map map = new ObjectMapper().readValue(new URL(URL), Map.class);
|
Map map = new ObjectMapper().readValue(new URL(URL), Map.class);
|
||||||
String siteId = null;
|
String siteId = null;
|
||||||
if(map.get("value")!=null) {
|
if (map.get("value") != null) {
|
||||||
siteId = map.get("value").toString();
|
siteId = map.get("value").toString();
|
||||||
}
|
}
|
||||||
piwikInfo.setSiteId(siteId);
|
piwikInfo.setSiteId(siteId);
|
||||||
|
@ -217,5 +217,14 @@ public class PiWikServiceImpl implements PiWikService {
|
||||||
return piwikInfo;
|
return piwikInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getTotal() {
|
||||||
|
return new JdbcTemplate(dataSource).queryForObject(GET_PIWIK_SITES_TOTAL, new Object[]{}, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getValidated(boolean validated) {
|
||||||
|
String finalizedQuery = GET_PIWIK_SITES_TOTAL + " where validated = ?";
|
||||||
|
return new JdbcTemplate(dataSource).queryForObject(finalizedQuery, new Object[]{validated}, Integer.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package metrics;
|
||||||
|
|
||||||
|
import eu.dnetlib.repo.manager.controllers.PrometheusController;
|
||||||
|
import eu.dnetlib.repo.manager.service.PiWikService;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class PrometheusTest {
|
||||||
|
|
||||||
|
private static final int TOTAL = 10;
|
||||||
|
private static final int VALIDATED = 8;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Mock
|
||||||
|
PiWikService piWikService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@InjectMocks
|
||||||
|
private PrometheusController prometheusController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
when(piWikService.getTotal()).thenReturn(TOTAL);
|
||||||
|
when(piWikService.getValidated(true)).thenReturn(VALIDATED);
|
||||||
|
when(piWikService.getValidated(false)).thenReturn(TOTAL - VALIDATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetrics() {
|
||||||
|
String report = prometheusController.getMetrics();
|
||||||
|
assertTrue(report.startsWith("#"));
|
||||||
|
System.out.println(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPiwikMetrics() {
|
||||||
|
assertTrue(piWikService.getValidated(false).equals(TOTAL - VALIDATED));
|
||||||
|
String report = prometheusController.getPiwikMetrics();
|
||||||
|
assertTrue(report.contains("total_total " + TOTAL));
|
||||||
|
assertTrue(report.contains("validated_total " + VALIDATED));
|
||||||
|
System.out.println(report);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue