aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/HorizonClient.java2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/MockHorizonClient.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriter.java10
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java4
-rw-r--r--controller-server/src/test/resources/horizon/filter-in-execution-graph.expected.json2
-rw-r--r--controller-server/src/test/resources/horizon/filters-complex.expected.json2
-rw-r--r--controller-server/src/test/resources/horizon/filters-meta-query.expected.json39
-rw-r--r--controller-server/src/test/resources/horizon/filters-meta-query.json29
-rw-r--r--controller-server/src/test/resources/horizon/no-filters.expected.json2
10 files changed, 92 insertions, 12 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/HorizonClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/HorizonClient.java
index c9f6f67df6c..77a36610dc7 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/HorizonClient.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/HorizonClient.java
@@ -22,4 +22,6 @@ public interface HorizonClient {
InputStream getClipboard(String dashboardId);
+ InputStream getMetaData(byte[] query);
+
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/MockHorizonClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/MockHorizonClient.java
index 7d7af046810..0ecad973cff 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/MockHorizonClient.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/horizon/MockHorizonClient.java
@@ -42,4 +42,9 @@ public class MockHorizonClient implements HorizonClient {
public InputStream getClipboard(String dashboardId) {
return null;
}
+
+ @Override
+ public InputStream getMetaData(byte[] query) {
+ return null;
+ }
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java
index 035d32e1837..a7875b0d1ae 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiHandler.java
@@ -16,7 +16,6 @@ import com.yahoo.yolean.Exceptions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UncheckedIOException;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.logging.Level;
@@ -68,8 +67,8 @@ public class HorizonApiHandler extends LoggingRequestHandler {
private HttpResponse post(HttpRequest request) {
Path path = new Path(request.getUri());
- if (path.matches("/horizon/v1/tsdb/api/query/graph")) return tsdbQuery(request);
- if (path.matches("/horizon/v1/meta/search/timeseries")) assert true; // TODO
+ if (path.matches("/horizon/v1/tsdb/api/query/graph")) return tsdbQuery(request, true);
+ if (path.matches("/horizon/v1/meta/search/timeseries")) return tsdbQuery(request, false);
return ErrorResponse.notFoundError("Nothing at " + path);
}
@@ -79,11 +78,11 @@ public class HorizonApiHandler extends LoggingRequestHandler {
return ErrorResponse.notFoundError("Nothing at " + path);
}
- private HttpResponse tsdbQuery(HttpRequest request) {
+ private HttpResponse tsdbQuery(HttpRequest request, boolean isMetricQuery) {
SecurityContext securityContext = getAttribute(request, SecurityContext.ATTRIBUTE_NAME, SecurityContext.class);
try {
byte[] data = TsdbQueryRewriter.rewrite(request.getData().readAllBytes(), securityContext.roles(), systemName);
- return new JsonInputStreamResponse(() -> client.getMetrics(data));
+ return new JsonInputStreamResponse(() -> isMetricQuery ? client.getMetrics(data) : client.getMetaData(data));
} catch (TsdbQueryRewriter.UnauthorizedException e) {
return ErrorResponse.forbidden("Access denied");
} catch (IOException e) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriter.java
index 0c20571032a..2060336487d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriter.java
@@ -39,14 +39,16 @@ public class TsdbQueryRewriter {
JsonNode root = mapper.readTree(data);
getField(root, "executionGraph", ArrayNode.class)
- .ifPresent(graph -> rewriteExecutionGraph(graph, authorizedTenants, operator, systemName));
+ .ifPresent(graph -> rewriteQueryGraph(graph, authorizedTenants, operator, systemName));
getField(root, "filters", ArrayNode.class)
.ifPresent(filters -> rewriteFilters(filters, authorizedTenants, operator, systemName));
+ getField(root, "queries", ArrayNode.class)
+ .ifPresent(graph -> rewriteQueryGraph(graph, authorizedTenants, operator, systemName));
return mapper.writeValueAsBytes(root);
}
- private static void rewriteExecutionGraph(ArrayNode executionGraph, Set<TenantName> tenantNames, boolean operator, SystemName systemName) {
+ private static void rewriteQueryGraph(ArrayNode executionGraph, Set<TenantName> tenantNames, boolean operator, SystemName systemName) {
for (int i = 0; i < executionGraph.size(); i++) {
JsonNode execution = executionGraph.get(i);
@@ -66,7 +68,7 @@ public class TsdbQueryRewriter {
ObjectNode prev = ((ObjectNode) parent.get("filter"));
ArrayNode filters;
// If we dont already have a filter object, or the object that we have is not an AND filter
- if (prev == null || !"Chain".equals(prev.get("type").asText()) || !"AND".equals(prev.get("op").asText())) {
+ if (prev == null || !"Chain".equals(prev.get("type").asText()) || prev.get("op") != null && !"AND".equals(prev.get("op").asText())) {
// Create new filter object
filters = parent.putObject("filter")
.put("type", "Chain")
@@ -88,7 +90,7 @@ public class TsdbQueryRewriter {
ObjectNode appFilter = filters.addObject();
appFilter.put("type", "TagValueRegex");
appFilter.put("filter",
- tenantNames.stream().map(TenantName::value).sorted().collect(Collectors.joining("|", "(", ")\\..*")));
+ tenantNames.stream().map(TenantName::value).sorted().collect(Collectors.joining("|", "^(", ")\\..*")));
appFilter.put("tagKey", "applicationId");
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java
index 937b0e95440..ab9d50f8eae 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java
@@ -35,6 +35,10 @@ public class TsdbQueryRewriterTest {
assertRewrite("no-filters.json",
"no-filters.expected.json",
Role.reader(TenantName.from("tenant2")), Role.athenzTenantAdmin(TenantName.from("tenant3")));
+
+ assertRewrite("filters-meta-query.json",
+ "filters-meta-query.expected.json",
+ Role.reader(TenantName.from("tenant2")), Role.athenzTenantAdmin(TenantName.from("tenant3")));
}
@Test(expected = TsdbQueryRewriter.UnauthorizedException.class)
diff --git a/controller-server/src/test/resources/horizon/filter-in-execution-graph.expected.json b/controller-server/src/test/resources/horizon/filter-in-execution-graph.expected.json
index 26497a0434a..a71fd812de9 100644
--- a/controller-server/src/test/resources/horizon/filter-in-execution-graph.expected.json
+++ b/controller-server/src/test/resources/horizon/filter-in-execution-graph.expected.json
@@ -27,7 +27,7 @@
},
{
"type": "TagValueRegex",
- "filter": "(tenant2|tenant3)\\..*",
+ "filter": "^(tenant2|tenant3)\\..*",
"tagKey": "applicationId"
}
]
diff --git a/controller-server/src/test/resources/horizon/filters-complex.expected.json b/controller-server/src/test/resources/horizon/filters-complex.expected.json
index 68ccb7895de..b3416f8a410 100644
--- a/controller-server/src/test/resources/horizon/filters-complex.expected.json
+++ b/controller-server/src/test/resources/horizon/filters-complex.expected.json
@@ -35,7 +35,7 @@
},
{
"type": "TagValueRegex",
- "filter": "(tenant2)\\..*",
+ "filter": "^(tenant2)\\..*",
"tagKey": "applicationId"
}
]
diff --git a/controller-server/src/test/resources/horizon/filters-meta-query.expected.json b/controller-server/src/test/resources/horizon/filters-meta-query.expected.json
new file mode 100644
index 00000000000..6c8cab217fa
--- /dev/null
+++ b/controller-server/src/test/resources/horizon/filters-meta-query.expected.json
@@ -0,0 +1,39 @@
+{
+ "from": 0,
+ "to": 1,
+ "order": "ASCENDING",
+ "type": "TAG_KEYS_AND_VALUES",
+ "source": "",
+ "aggregationSize": 1000,
+ "queries": [
+ {
+ "id": "id-0",
+ "namespace": "Vespa",
+ "filter": {
+ "type": "Chain",
+ "filters": [
+ {
+ "type": "TagValueRegex",
+ "filter": ".*",
+ "tagKey": "applicationId"
+ },
+ {
+ "type": "MetricLiteral",
+ "metric": "vespa.distributor.vds.distributor.docsstored.average|vespa.searchnode.content.proton.resource_usage.disk.average|vespa.searchnode.content.proton.resource_usage.memory.average|vespa.container.peak_qps.max"
+ },
+ {
+ "type": "TagValueLiteralOr",
+ "filter": "public",
+ "tagKey": "system"
+ },
+ {
+ "type": "TagValueRegex",
+ "filter": "^(tenant2|tenant3)\\..*",
+ "tagKey": "applicationId"
+ }
+ ]
+ }
+ }
+ ],
+ "aggregationField": "applicationId"
+}
diff --git a/controller-server/src/test/resources/horizon/filters-meta-query.json b/controller-server/src/test/resources/horizon/filters-meta-query.json
new file mode 100644
index 00000000000..ed59bef5eaa
--- /dev/null
+++ b/controller-server/src/test/resources/horizon/filters-meta-query.json
@@ -0,0 +1,29 @@
+{
+ "from": 0,
+ "to": 1,
+ "order": "ASCENDING",
+ "type": "TAG_KEYS_AND_VALUES",
+ "source": "",
+ "aggregationSize": 1000,
+ "queries": [
+ {
+ "id": "id-0",
+ "namespace": "Vespa",
+ "filter": {
+ "type": "Chain",
+ "filters": [
+ {
+ "type": "TagValueRegex",
+ "filter": ".*",
+ "tagKey": "applicationId"
+ },
+ {
+ "type": "MetricLiteral",
+ "metric": "vespa.distributor.vds.distributor.docsstored.average|vespa.searchnode.content.proton.resource_usage.disk.average|vespa.searchnode.content.proton.resource_usage.memory.average|vespa.container.peak_qps.max"
+ }
+ ]
+ }
+ }
+ ],
+ "aggregationField": "applicationId"
+} \ No newline at end of file
diff --git a/controller-server/src/test/resources/horizon/no-filters.expected.json b/controller-server/src/test/resources/horizon/no-filters.expected.json
index ab26885b839..35decea21db 100644
--- a/controller-server/src/test/resources/horizon/no-filters.expected.json
+++ b/controller-server/src/test/resources/horizon/no-filters.expected.json
@@ -22,7 +22,7 @@
},
{
"type": "TagValueRegex",
- "filter": "(tenant2|tenant3)\\..*",
+ "filter": "^(tenant2|tenant3)\\..*",
"tagKey": "applicationId"
}
]