partial work on dashboard capture

This commit is contained in:
Jonathan Shook 2020-12-22 12:56:06 -06:00
parent 4a8c4cf390
commit e561b4b847
23 changed files with 1159 additions and 20 deletions

View File

@ -0,0 +1,4 @@
package io.nosqlbench.engine.clients.grafana;
public class GRangeResult {
}

View File

@ -0,0 +1,33 @@
package io.nosqlbench.engine.clients.grafana;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GStitcher {
private final Map<String, Set<String>> values;
private final static Pattern pattern = Pattern.compile("\\$(\\w+)");
public GStitcher(Map<String, Set<String>> values) {
this.values = values;
}
public String stitchRegex(String spec) {
StringBuilder sb = new StringBuilder();
Matcher matcher = pattern.matcher(spec);
while (matcher.find()) {
String word = matcher.group(1);
if (values.containsKey(word)) {
Set<String> elems = values.get(word);
String replacement = "(" + String.join("|", elems) + ")";
matcher.appendReplacement(sb, replacement);
} else {
matcher.appendReplacement(sb, "NOTFOUND[" + word + "]");
}
}
matcher.appendTail(sb);
return sb.toString();
}
}

View File

@ -0,0 +1,83 @@
package io.nosqlbench.engine.clients.grafana;
import java.time.ZonedDateTime;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GTimeUnit {
private enum Durations {
s("second", 1000L),
m("minute", 60000L),
h("hour", 3600000L),
d("day", 86400000L),
w("week", 86400000L * 7L),
M("month", 86400000L * 30L),
y("year", 86400000L * 365L);
private final String unitName;
private final long millisPerUnit;
Durations(String unitName, long millisPerUnit) {
this.unitName = unitName;
this.millisPerUnit = millisPerUnit;
}
public long durationInMillis(long count) {
return count * millisPerUnit;
}
public long durationInSeconds(long count) {
return (count * millisPerUnit) / 1000L;
}
}
private static final Pattern absolute = Pattern.compile("\\d+");
private static final Pattern ISO_INSTANT = Pattern.compile(
"(?<year>\\d+)-(?<month>\\d+)-(?<day>\\d+) " +
"(?<hour>\\d+):(?<minute>\\d+):(?<second>\\d+)(\\.(?<millis>\\d+))?Z?"
);
private static final Pattern relUnit = Pattern.compile(
"now((?<value>[-+]\\d+)(?<unit>[smhdwMy]))?(\\/(?<interval>[smhdwMy]))?"
);
public static long epochSecondsFor(String spec) {
if (spec.startsWith("now")) {
Matcher relative = relUnit.matcher(spec);
if (relative.matches()) {
if (relative.group("interval") != null) {
throw new RuntimeException("date field boundaries like '"
+ spec +
"' are not supported yet.");
}
long now = System.currentTimeMillis() / 1000L;
long delta = 0L;
String v = relative.group("value");
String u = relative.group("unit");
if (v != null && u != null) {
long value = Long.parseLong(v);
Durations duration = Durations.valueOf(u);
delta = duration.durationInSeconds(value);
}
long timevalue = now + delta;
return timevalue;
} else {
throw new RuntimeException("unable to match input '" + spec + "'");
}
} else if (spec.matches("\\\\d+")) {
return Long.parseLong(spec);
} else {
Matcher matcher = ISO_INSTANT.matcher(spec);
if (matcher.matches()) {
ZonedDateTime parsed = ZonedDateTime.parse(spec);
return parsed.toEpochSecond();
} else {
throw new RuntimeException("Unrecognized format for grafana time unit '" + spec + "'");
}
}
}
}

View File

@ -5,18 +5,22 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.nosqlbench.engine.clients.grafana.annotator.GrafanaMetricsAnnotator;
import io.nosqlbench.engine.clients.grafana.transfer.*;
import io.nosqlbench.engine.clients.prometheus.*;
import java.io.File;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @see <a href="https://grafana.com/docs/grafana/latest/http_api/annotations/">Grafana Annotations API Docs</a>
@ -25,6 +29,7 @@ public class GrafanaClient {
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private final GrafanaClientConfig config;
private List<GDataSource> datasources;
public GrafanaClient(GrafanaClientConfig config) {
this.config = config;
@ -273,7 +278,7 @@ public class GrafanaClient {
}
public GDashboardMeta getDashboardByUid(String uid) {
public GDashboardResponse getDashboardByUid(String uid) {
HttpClient client = config.newClient();
HttpRequest.Builder rqb = config.newRequest("api/dashboards/uid/" + uid);
rqb = rqb.GET();
@ -290,7 +295,7 @@ public class GrafanaClient {
}
String body = response.body();
GDashboardMeta dashboardMeta = gson.fromJson(body, GDashboardMeta.class);
GDashboardResponse dashboardMeta = gson.fromJson(body, GDashboardResponse.class);
return dashboardMeta;
}
@ -511,4 +516,174 @@ public class GrafanaClient {
return result;
}
public <T> T doProxyQuery(String dsname, String path, String query, TypeToken<? extends T> asType) {
GDataSource datasource = getCachedDatasource(dsname);
long dsid = datasource.getId();
String composedQuery = path;
if (query != null && !query.isBlank()) {
composedQuery = composedQuery + "?" + query;
}
HttpClient client = config.newClient();
HttpRequest.Builder rqb =
config.newRequest("api/datasources/proxy/" + dsid + "/" + composedQuery);
rqb.setHeader("Accept", "application/json");
rqb = rqb.GET();
HttpResponse<String> response = null;
try {
response = client.send(rqb.build(), HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
throw new RuntimeException(e);
}
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("Executing proxy query failed with status code " + response.statusCode() +
" at baseuri " + config.getBaseUri() + ": " + response.body() + " for datasource '" + dsid + "' and query '" + query + "'");
}
String body = response.body();
T result = gson.fromJson(body, asType.getType());
return result;
}
private GDataSource getCachedDatasource(String dsname) {
return getCachedDatasources().stream()
.filter(gd -> gd.getName().equals(dsname))
.findFirst()
.orElseThrow();
}
public Map<String, Set<String>> resolveAllTplValues(List<GTemplate> tpls, String timeStart, String timeEnd) {
Map<String, Set<String>> allTplValues = new HashMap<>();
for (GTemplate gTemplate : tpls) {
Set<String> strings = resolveTplValues(gTemplate, timeStart, timeEnd, getCachedDatasources());
allTplValues.put(gTemplate.getName(), strings);
}
return allTplValues;
}
public Set<String> resolveTplValues(GTemplate tpl, String timeStart, String timeEnd, List<GDataSource> dss) {
Set<String> resolved = new HashSet<>();
List<String> values = tpl.getCurrent().getValues();
if (values.size() == 1 && values.get(0).equals("$__all")) {
if (tpl.getAllValue() != null && !tpl.getAllValue().isBlank()) {
resolved.add(tpl.getAllValue());
} else {
String dsname = tpl.getDatasource();
Optional<GDataSource> dso = dss.stream().filter(n -> n.getName().equals(dsname)).findFirst();
GDataSource ds = dso.orElseThrow();
String query = tpl.getQuery();
String formatted = formatSeriesQuery(ds.getType(), query, timeStart, timeEnd);
if (ds.getType().equals("prometheus")) {
long startSpec = GTimeUnit.epochSecondsFor(timeStart);
long endSpec = GTimeUnit.epochSecondsFor(timeEnd);
String q = "api/v1/series?match[]=" + URLEncoder.encode(tpl.getQuery()) +
"&start=" + startSpec +
"&end=" + endSpec;
PromSeriesLookupResult psr = doProxyQuery("prometheus", "api/v1/series", q, new TypeToken<PromSeriesLookupResult>() {
});
for (PromSeriesLookupResult.Element elem : psr.getData()) {
String elementSpec = elem.toString();
String regex = tpl.getRegex();
if (regex != null && !regex.isBlank()) {
if (regex.startsWith("/")) {
regex = regex.substring(1, regex.length() - 2);
}
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(elementSpec);
if (m.find()) {
String group = m.group(1);
resolved.add(group);
}
} else {
resolved.add(elem.toString());
}
}
} else {
throw new RuntimeException("datasource type not supported yet for template values: '" + ds.getType() + "'");
}
}
} else {
for (String value : tpl.getCurrent().getValues()) {
resolved.add(value);
}
}
return resolved;
}
private String formatSeriesQuery(String type, String query, String startTime, String endTime) {
if (type.equals("prometheus")) {
long startSpec = GTimeUnit.epochSecondsFor(startTime);
long endSpec = GTimeUnit.epochSecondsFor(endTime);
return "api/v1/series?match[]=" + URLEncoder.encode(query, StandardCharsets.UTF_8) + "&start=" + startSpec +
"&end=" + endSpec;
} else {
throw new RuntimeException("Unknown query target type '" + type + "'");
}
}
public List<GDataSource> getDatasources() {
HttpClient client = config.newClient();
HttpRequest.Builder rqb = config.newRequest("api/datasources");
rqb = rqb.GET();
HttpResponse<String> response = null;
try {
response = client.send(rqb.build(), HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
throw new RuntimeException(e);
}
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("Getting datasources failed with status code " + response.statusCode() +
" at baseuri " + config.getBaseUri() + ": " + response.body());
}
String body = response.body();
Type dsListType = new TypeToken<List<GDataSource>>() {
}.getType();
List<GDataSource> dataSourcesList = gson.fromJson(body, dsListType);
return dataSourcesList;
}
private List<GDataSource> getCachedDatasources() {
if (datasources == null) {
datasources = getDatasources();
}
return datasources;
}
public GRangeResult doRangeQuery(String datasource, String expr, String startSpec, String endSpec) {
GDataSource ds = getCachedDatasource(datasource);
if (ds.getType().equals("prometheus")) {
long start = GTimeUnit.epochSecondsFor(startSpec);
long end = GTimeUnit.epochSecondsFor(endSpec);
// http://44.242.139.57:3000/api/datasources/proxy/1/api/v1/query_range?query=result%7Btype%3D%22avg_rate%22%2Cavg_of%3D%221m%22%2Calias%3D~%22keyvalue_main_001%22%7D&start=1608534000&end=1608620400&step=300
// http://44.242.139.57:3000/api/datasources/proxy/1/api/v1/query_range?query=result%7Btype%3D%22avg_rate%22%2Cavg_of%3D%221m%22%2Calias%3D%7E%22%28.*%29%22%7D&start=1608611971&end=1608622771&step=300
String path = "api/v1/query_range?query=" +
URLEncoder.encode(expr) + "&start=" + start + "&end=" + end + "&step=300";
PromQueryResult<PMatrixData> vectorData = doProxyQuery(
datasource,
"api/v1/query_range",
"query=" + URLEncoder.encode(expr) + "&start=" + start + "&end=" + end + "&step=300",
new TypeToken<PromQueryResult<PMatrixData>>() {
});
System.out.println(vectorData);
return null;
} else {
throw new RuntimeException("data source " + datasource + " is not yet supported.");
}
// TODO: Distinguish between datasources named "prometheus" and data source types "prometheus"
// TODO: Figure out how to set step equivalently
}
}

View File

@ -0,0 +1,6 @@
package io.nosqlbench.engine.clients.grafana.analyzer;
import java.util.LinkedHashMap;
public class GQueryResult extends LinkedHashMap<String, Object> {
}

View File

@ -1,11 +1,10 @@
package io.nosqlbench.engine.clients.grafana.analyzer;
import io.nosqlbench.engine.clients.grafana.GRangeResult;
import io.nosqlbench.engine.clients.grafana.GStitcher;
import io.nosqlbench.engine.clients.grafana.GrafanaClient;
import io.nosqlbench.engine.clients.grafana.GrafanaClientConfig;
import io.nosqlbench.engine.clients.grafana.transfer.GAnnotation;
import io.nosqlbench.engine.clients.grafana.transfer.GDashboard;
import io.nosqlbench.engine.clients.grafana.transfer.GPanelDef;
import io.nosqlbench.engine.clients.grafana.transfer.GSnapshotInfo;
import io.nosqlbench.engine.clients.grafana.transfer.*;
import io.nosqlbench.nb.api.SystemId;
import java.nio.file.Path;
@ -14,6 +13,8 @@ import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -87,13 +88,56 @@ public class GrafanaRegionAnalyzer implements Runnable {
}
public void getQueries(GDashboard db) {
List<GPanelDef> graphs = db.getPanels().stream()
List<GDataSource> datasources = getClient().getDatasources();
List<GPanelDef> mainpanels = db.getPanels().stream()
.filter(p -> p.getType().equals("graph"))
.collect(Collectors.toList());
System.out.println(graphs.size() + " graphs...");
Map<String, Set<String>> tplValues = getClient().resolveAllTplValues(
db.getTemplating().getList(),
db.getTime().getFrom(),
db.getTime().getTo());
GStitcher stitcher = new GStitcher(tplValues);
for (GPanelDef mainpanel : mainpanels) {
long id = mainpanel.getId();
String title = mainpanel.getTitle();
String description = mainpanel.getDescription();
List<GPanelDef> panels = mainpanel.getPanels();
String datasource = mainpanel.getDatasource();
Map<String, Object> fieldConfig = mainpanel.getFieldConfig();
Map<String, String> options = mainpanel.getOptions();
List<GPanelDef.GTarget> targets = mainpanel.getTargets();
System.out.println("targets:\n" + targets);
for (GPanelDef.GTarget target : targets) {
String expr = target.getExpr();
expr = stitcher.stitchRegex(expr);
// expr = GStitcher.resolve(expr,tplValues,GStitcher.Regex);
System.out.println("expr now:" + expr);
GRangeResult result = getClient().doRangeQuery(mainpanel.getDatasource(), expr, db.getTime().getFrom(), db.getTime().getTo());
// GQueryResult gqr = getClient().doProxyQuery(mainpanel.getDatasource(), expr, new TypeToken<GQueryResult>() {});
System.out.println(result);
}
//System.out.println(mainpanel);
}
System.out.println(mainpanels.size() + " graphs...");
//http://44.242.139.57:3000/api/datasources/proxy/1/
// api/v1/query_range?query= result{
// type="avg_rate",
// avg_of="1m",
// alias=~"(keyvalue_default_main|keyvalue_default_rampup|keyvalue_default_schema|keyvalue_main_001
// |keyvalue_rampup_001|keyvalue_schema_001)"}&start=1607996100&end=1608600900&step=300
}
@Override
public void run() {
@ -127,4 +171,7 @@ public class GrafanaRegionAnalyzer implements Runnable {
System.out.println("end");
}
public GDashboard getDashboard(String dbUid) {
return getClient().getDashboardByUid(dbUid).getDashboard();
}
}

View File

@ -25,7 +25,7 @@ public class GDashboard {
long schemaVersion;
String style;
List<Object> tags;
Map<String, Object> templating;
GTemplating templating;
Time time;
Map<String, List<String>> timepicker;
String timezone;
@ -129,11 +129,11 @@ public class GDashboard {
this.tags = tags;
}
public Map<String, Object> getTemplating() {
public GTemplating getTemplating() {
return templating;
}
public void setTemplating(Map<String, Object> templating) {
public void setTemplating(GTemplating templating) {
this.templating = templating;
}
@ -185,6 +185,8 @@ public class GDashboard {
// URL resource = GDashboard.class.getClassLoader().getResource(path);
String json = null;
try {
URL url = GDashboard.class.getClassLoader().getResource(path);
if (url == null) {
@ -192,7 +194,7 @@ public class GDashboard {
}
Path found = Paths.get(url.toURI());
byte[] bytes = Files.readAllBytes(found);
String json = new String(bytes, StandardCharsets.UTF_8);
json = new String(bytes, StandardCharsets.UTF_8);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
GDashboard db = gson.fromJson(json, GDashboard.class);
return db;

View File

@ -1,6 +1,6 @@
package io.nosqlbench.engine.clients.grafana.transfer;
public class GDashboardMeta {
public class GDashboardResponse {
GMeta meta;
GDashboard dashboard;

View File

@ -0,0 +1,133 @@
package io.nosqlbench.engine.clients.grafana.transfer;
import java.util.Map;
public class GDataSource {
long id;
long orgId;
String name;
String type;
String typeLogoUrl;
String access;
String url;
String password;
String user;
String database;
boolean basicAuth;
boolean isDefault;
Map<String, Object> jsonData;
boolean readOnly;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getOrgId() {
return orgId;
}
public void setOrgId(long orgId) {
this.orgId = orgId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTypeLogoUrl() {
return typeLogoUrl;
}
public void setTypeLogoUrl(String typeLogoUrl) {
this.typeLogoUrl = typeLogoUrl;
}
public String getAccess() {
return access;
}
public void setAccess(String access) {
this.access = access;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public boolean isBasicAuth() {
return basicAuth;
}
public void setBasicAuth(boolean basicAuth) {
this.basicAuth = basicAuth;
}
public boolean isDefault() {
return isDefault;
}
public void setDefault(boolean aDefault) {
isDefault = aDefault;
}
public Map<String, Object> getJsonData() {
return jsonData;
}
public void setJsonData(Map<String, Object> jsonData) {
this.jsonData = jsonData;
}
public boolean isReadOnly() {
return readOnly;
}
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
}

View File

@ -12,7 +12,7 @@ public class GPanelDef {
Map<String, Object> fieldConfig;
Map<String, String> options;
String pluginVersion;
List<Map<String, String>> targets;
List<GTarget> targets;
String title;
String type;
String datasource;
@ -82,11 +82,11 @@ public class GPanelDef {
this.pluginVersion = pluginVersion;
}
public List<Map<String, String>> getTargets() {
public List<GTarget> getTargets() {
return targets;
}
public void setTargets(List<Map<String, String>> targets) {
public void setTargets(List<GTarget> targets) {
this.targets = targets;
}
@ -117,4 +117,73 @@ public class GPanelDef {
public String toString() {
return id + ":'" + title + "'";
}
public static class GTarget {
String queryType;
String refId;
String expr;
String interval;
String legendFormat;
boolean hide;
public String getQueryType() {
return queryType;
}
public void setQueryType(String queryType) {
this.queryType = queryType;
}
public String getRefId() {
return refId;
}
public void setRefId(String refId) {
this.refId = refId;
}
public String getExpr() {
return expr;
}
public void setExpr(String expr) {
this.expr = expr;
}
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
public String getLegendFormat() {
return legendFormat;
}
public void setLegendFormat(String legendFormat) {
this.legendFormat = legendFormat;
}
public boolean isHide() {
return hide;
}
public void setHide(boolean hide) {
this.hide = hide;
}
@Override
public String toString() {
return "GTarget{" +
"queryType='" + queryType + '\'' +
", refId='" + refId + '\'' +
", expr='" + expr + '\'' +
", interval='" + interval + '\'' +
", legendFormat='" + legendFormat + '\'' +
", hide=" + hide +
'}';
}
}
}

View File

@ -0,0 +1,246 @@
package io.nosqlbench.engine.clients.grafana.transfer;
import java.util.List;
public class GTemplate {
String allValue;
String name;
GCurrentValue current;
String datasource;
String definition;
Object error;
long hide;
boolean includeAll;
String label;
boolean multi;
List<Object> options;
String query;
long refresh;
String regex;
boolean skipUrlSync;
long sort;
String tagValuesQuery;
List<String> tags;
String tagsQuery;
String type;
boolean useTags;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAllValue() {
return allValue;
}
public void setAllValue(String allValue) {
this.allValue = allValue;
}
public GCurrentValue getCurrent() {
return current;
}
public void setCurrent(GCurrentValue current) {
this.current = current;
}
public String getDatasource() {
return datasource;
}
public void setDatasource(String datasource) {
this.datasource = datasource;
}
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
public Object getError() {
return error;
}
public void setError(Object error) {
this.error = error;
}
public long getHide() {
return hide;
}
public void setHide(long hide) {
this.hide = hide;
}
public boolean isIncludeAll() {
return includeAll;
}
public void setIncludeAll(boolean includeAll) {
this.includeAll = includeAll;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public boolean isMulti() {
return multi;
}
public void setMulti(boolean multi) {
this.multi = multi;
}
public List<Object> getOptions() {
return options;
}
public void setOptions(List<Object> options) {
this.options = options;
}
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public long getRefresh() {
return refresh;
}
public void setRefresh(long refresh) {
this.refresh = refresh;
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public boolean isSkipUrlSync() {
return skipUrlSync;
}
public void setSkipUrlSync(boolean skipUrlSync) {
this.skipUrlSync = skipUrlSync;
}
public long getSort() {
return sort;
}
public void setSort(long sort) {
this.sort = sort;
}
public String getTagValuesQuery() {
return tagValuesQuery;
}
public void setTagValuesQuery(String tagValuesQuery) {
this.tagValuesQuery = tagValuesQuery;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public String getTagsQuery() {
return tagsQuery;
}
public void setTagsQuery(String tagsQuery) {
this.tagsQuery = tagsQuery;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isUseTags() {
return useTags;
}
public void setUseTags(boolean useTags) {
this.useTags = useTags;
}
public static class GCurrentValue {
boolean selected;
Object text;
Object value;
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public Object getText() {
return text;
}
public void setText(Object text) {
this.text = text;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public List<String> getValues() {
if (value instanceof String) {
return List.of((String) value);
} else if (value instanceof List) {
return (List<String>) value;
} else {
throw new RuntimeException("Unrecognized form of value:" + value.getClass().getSimpleName());
}
}
public List<String> getTexts() {
if (text instanceof String) {
return List.of((String) text);
} else if (text instanceof List) {
return (List<String>) text;
} else {
throw new RuntimeException("Unrecognized form of text:" + text.getClass().getSimpleName());
}
}
}
}

View File

@ -0,0 +1,15 @@
package io.nosqlbench.engine.clients.grafana.transfer;
import java.util.List;
public class GTemplating {
List<GTemplate> list;
public List<GTemplate> getList() {
return list;
}
public void setList(List<GTemplate> list) {
this.list = list;
}
}

View File

@ -0,0 +1,32 @@
package io.nosqlbench.engine.clients.prometheus;
import java.util.List;
public class PMatrixData {
String resultType;
List<PMatrixElem> result;
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public List<PMatrixElem> getResult() {
return result;
}
public void setResult(List<PMatrixElem> result) {
this.result = result;
}
@Override
public String toString() {
return "PMatrixData{" +
"resultType='" + resultType + '\'' +
", result=" + result +
'}';
}
}

View File

@ -0,0 +1,14 @@
package io.nosqlbench.engine.clients.prometheus;
public class PMatrixElem {
PMetric metric;
PValues values;
@Override
public String toString() {
return "PMatrixElem{" +
"metric=" + metric +
", values=" + values +
'}';
}
}

View File

@ -0,0 +1,17 @@
package io.nosqlbench.engine.clients.prometheus;
import java.util.LinkedHashMap;
public class PMetric extends LinkedHashMap<String, String> {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
forEach((k, v) -> {
sb.append(k).append("=");
sb.append("\"").append(v).append("\",");
});
sb.setLength(sb.length() - 1);
sb.append("}");
return sb.toString();
}
}

View File

@ -0,0 +1,13 @@
package io.nosqlbench.engine.clients.prometheus;
import java.util.ArrayList;
public class PValue extends ArrayList<Object> {
public double getInstant() {
return (double) get(0);
}
public String getValue() {
return (String) get(1);
}
}

View File

@ -0,0 +1,14 @@
package io.nosqlbench.engine.clients.prometheus;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
public class PValues extends ArrayList<PValue> {
private final static Gson gson = new GsonBuilder().create();
public String toString() {
return gson.toJson(this);
}
}

View File

@ -0,0 +1,30 @@
package io.nosqlbench.engine.clients.prometheus;
public class PromQueryResult<T> {
String status;
T data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "PromQueryResult{" +
"status='" + status + '\'' +
", data=" + data +
'}';
}
}

View File

@ -0,0 +1,88 @@
package io.nosqlbench.engine.clients.prometheus;
import java.util.List;
import java.util.Map;
public class PromSeriesDataResult {
String status;
Data data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public static class Data {
String resultType;
List<Result> result;
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public List<Result> getResult() {
return result;
}
public void setResult(List<Result> result) {
this.result = result;
}
private static class Result {
Map<String, String> metric;
Value[] values;
public Map<String, String> getMetric() {
return metric;
}
public void setMetric(Map<String, String> metric) {
this.metric = metric;
}
public Value[] getValues() {
return values;
}
public void setValues(Value[] values) {
this.values = values;
}
public static class Value {
long instant;
String value;
public long getInstant() {
return instant;
}
public void setInstant(long instant) {
this.instant = instant;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
}
}

View File

@ -0,0 +1,40 @@
package io.nosqlbench.engine.clients.prometheus;
import java.util.LinkedHashMap;
import java.util.List;
public class PromSeriesLookupResult {
String status;
List<Element> data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<Element> getData() {
return data;
}
public void setData(List<Element> data) {
this.data = data;
}
public static class Element extends LinkedHashMap<String, String> {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
forEach((k, v) -> {
sb.append(k).append("=");
sb.append("\"").append(v).append("\",");
});
sb.setLength(sb.length() - 1);
sb.append("}");
return sb.toString();
}
}
}

View File

@ -0,0 +1,21 @@
package io.nosqlbench.engine.clients.grafana;
import org.assertj.core.data.Offset;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class GTimeUnitTest {
@Test
public void testParseBasic() {
long result = GTimeUnit.epochSecondsFor("now");
}
@Test
public void testParseRelative() {
long result = GTimeUnit.epochSecondsFor("now-1w");
assertThat(result).isCloseTo((System.currentTimeMillis() / 1000) - (86400L * 7L), Offset.offset(60L));
}
}

View File

@ -9,9 +9,10 @@ public class GrafanaRegionAnalyzerTest {
public void testGetQueries() {
GrafanaRegionAnalyzer gra = new GrafanaRegionAnalyzer();
gra.setBaseUrl("http://44.242.139.57:3000/");
GDashboard db = GDashboard.fromFile("examples/db.json");
gra.getQueries(db);
GDashboard db = gra.getDashboard("aIIX1f6Wz");
//GDashboard db = GDashboard.fromFile("examples/db.json");
// gra.getQueries(db);
}

View File

@ -0,0 +1,56 @@
package io.nosqlbench.engine.clients.prometheus;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.junit.Test;
import java.lang.reflect.Type;
import static org.assertj.core.api.Assertions.assertThat;
public class PMatrixElemTest {
@Test
public void testMatrixElem() {
Gson gson = new GsonBuilder().create();
String json = """
{
"status" : "success",
"data" : {
"resultType" : "matrix",
"result" : [
{
"metric" : {
"__name__" : "up",
"job" : "prometheus",
"instance" : "localhost:9090"
},
"values" : [
[ 1435781430.781, "1" ],
[ 1435781445.781, "1" ],
[ 1435781460.781, "1" ]
]
},
{
"metric" : {
"__name__" : "up",
"job" : "node",
"instance" : "localhost:9091"
},
"values" : [
[ 1435781430.781, "0" ],
[ 1435781445.781, "0" ],
[ 1435781460.781, "1" ]
]
}
]
}
}""";
Type type = new TypeToken<PromQueryResult<PMatrixData>>() {
}.getType();
Object result = gson.fromJson(json, type);
assertThat(result).isOfAnyClassIn(PromQueryResult.class);
}
}