From d1b57b2f766a2ad9a07aa8a5aa0430a071d07320 Mon Sep 17 00:00:00 2001 From: Anton Skalkin Date: Fri, 7 Apr 2023 22:25:54 +0400 Subject: [PATCH] add Prometheus HTTP API --- build.gradle | 2 + .../configuration/WebClientConfiguration.java | 14 ++++ src/main/java/ru/ulstu/http/HttpService.java | 66 +++++++++++++++++++ .../ru/ulstu/service/PrometheusService.java | 66 +++++++++++++++++++ src/main/resources/application.properties | 1 + 5 files changed, 149 insertions(+) create mode 100644 src/main/java/ru/ulstu/configuration/WebClientConfiguration.java create mode 100644 src/main/java/ru/ulstu/http/HttpService.java create mode 100644 src/main/java/ru/ulstu/service/PrometheusService.java diff --git a/build.gradle b/build.gradle index 96922ab..1cd9974 100644 --- a/build.gradle +++ b/build.gradle @@ -34,10 +34,12 @@ dependencies { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-test' + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux' implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.0.0' implementation group: 'org.javassist', name: 'javassist', version: '3.25.0-GA' implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: versionJetty + implementation group: 'org.json', name: 'json', version: '20220320' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations' diff --git a/src/main/java/ru/ulstu/configuration/WebClientConfiguration.java b/src/main/java/ru/ulstu/configuration/WebClientConfiguration.java new file mode 100644 index 0000000..e477de4 --- /dev/null +++ b/src/main/java/ru/ulstu/configuration/WebClientConfiguration.java @@ -0,0 +1,14 @@ +package ru.ulstu.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.*; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfiguration { + @Bean + public WebClient webClient(WebClient.Builder webClientBuilder) { + return webClientBuilder.build(); //contentType(MediaType.APPLICATION_FORM_URLENCODED) + } +} diff --git a/src/main/java/ru/ulstu/http/HttpService.java b/src/main/java/ru/ulstu/http/HttpService.java new file mode 100644 index 0000000..093f58a --- /dev/null +++ b/src/main/java/ru/ulstu/http/HttpService.java @@ -0,0 +1,66 @@ +package ru.ulstu.http; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; + +import java.time.Duration; +import java.util.Optional; + +@Service +public class HttpService { + private final Logger log = LoggerFactory.getLogger(HttpService.class); + private final WebClient client; + + public HttpService(WebClient client) { + this.client = client; + } + + public JSONObject post(String url, JSONObject postData) { + log.debug("Service call: {}", url); + JSONObject response = null; + try { + response = new JSONObject(Optional.ofNullable(client + .post() + .uri(url) + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(postData.toString())) + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(String.class) + .toFuture().get()).orElse("{response:\"empty\"}")); + } catch (Exception e) { + return new JSONObject("{response:\"empty\"}"); + } + log.debug("Service response: {}", response); + return response; + } + + public JSONArray get(String url) { + log.debug("Service call: {}", url); + try { + String response = client + .get() + .uri(url) + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(String.class) + .timeout(Duration.ofMinutes(1)) + .toFuture().get(); + if (response.startsWith("[")) { + return new JSONArray(response); + } else { + JSONArray jsonArray = new JSONArray(); + jsonArray.put(0, new JSONObject(response)); + return jsonArray; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/ru/ulstu/service/PrometheusService.java b/src/main/java/ru/ulstu/service/PrometheusService.java new file mode 100644 index 0000000..35e9631 --- /dev/null +++ b/src/main/java/ru/ulstu/service/PrometheusService.java @@ -0,0 +1,66 @@ +package ru.ulstu.service; + +import org.json.JSONObject; +import org.springframework.stereotype.Service; +import ru.ulstu.datamodel.ts.TimeSeries; +import ru.ulstu.http.HttpService; + +@Service +public class PrometheusService { + + private static final String PROMETHEUS_API_URL = "http://prometheus.athene.tech/api/v1/"; + private final HttpService httpService; + + public PrometheusService(HttpService httpService) { + this.httpService = httpService; + } + + public TimeSeries executionQuery(String query){ // example: pve_cpu_usage_ratio{id="lxc/111"}[5h] + var timeSeries = new TimeSeries(); + var response = httpService.get(PROMETHEUS_API_URL + "query?query=" + query); + if (response.getJSONObject(0).getString("status").equals("success")){ + + } + return timeSeries; + } + + public TimeSeries executionQueryPost(String query){ // example: pve_cpu_usage_ratio{id="lxc/111"}[5h] + var timeSeries = new TimeSeries(); + var postData = new JSONObject(); + postData.put("query", query); + var response = httpService.post(PROMETHEUS_API_URL + "query", postData); +// if (response.getJSONObject(0).getString("status").equals("success")){ +// +// } + return timeSeries; + } + + public TimeSeries executionQueryRange(String query){ + var timeSeries = new TimeSeries(); + var response = httpService.get(PROMETHEUS_API_URL + "query_range?query=" + query + + "&start=2023-04-06T00:00:00.004Z&end=2023-04-07T00:00:00.004Z&step=15s"); + if (response.getJSONObject(0).getString("status").equals("success")){ + var array = response.getJSONObject(0).getJSONObject("data").getJSONArray("result"); + int a = 5; + } + return timeSeries; + } + + public TimeSeries executionQueryRangePost(String query){ + var timeSeries = new TimeSeries(); + var postData = new JSONObject(); + postData.put("query", query); + postData.put("start", "2023-04-06T00:00:00.004Z"); + postData.put("end", "2023-04-07T00:00:00.004Z"); + postData.put("step", "15s"); + + var response = httpService.post(PROMETHEUS_API_URL + "query_range", postData); +// response.getJSONObject(); +// if (response.getJSONObject(0).getString("status").equals("success")){ +// var array = response.getJSONObject(0).getJSONObject("data").getJSONArray("result"); +// int a = 5; +// } + return timeSeries; + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bac6dd5..9fa1de2 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,6 +2,7 @@ spring.main.banner-mode=off logging.level.tech.athene=DEBUG server.port=8080 spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false +spring.codec.max-in-memory-size=50MB joinfaces.primefaces.theme=afterwork joinfaces.primefaces.font-awesome=true time-series.db-path=time-series-db