Skip to content

Commit

Permalink
[HWKMETRICS-523] Add more tests for the core service along with integ…
Browse files Browse the repository at this point in the history
…ration tests for the REST API. All these tests cover a good portion of the matching capabilities for JSON Path.
  • Loading branch information
Stefan Negrea committed Dec 9, 2016
1 parent 4bfed72 commit 140d7e9
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
import rx.Observable;

/**
* Very simple query optimizer and parser for the tags query language
* JSON Path based tag query parser
*
* @author Michael Burman
* @author Stefan Negrea
*/
public class JsonTagQueryParser {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ public <T> Observable<Metric<T>> findMetricsWithFilters(String tenantId, MetricT
}

if (simpleTagMetrics != null && jsonTagMetrics != null) {
return simpleTagMetrics.concatWith(jsonTagMetrics).distinct();
return simpleTagMetrics.mergeWith(jsonTagMetrics).distinct();
} else if (simpleTagMetrics != null) {
return simpleTagMetrics;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
import static java.util.Arrays.asList;

import static org.hawkular.metrics.model.MetricType.AVAILABILITY;
import static org.hawkular.metrics.model.MetricType.COUNTER;
import static org.hawkular.metrics.model.MetricType.GAUGE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hawkular.metrics.model.AvailabilityType;
import org.hawkular.metrics.model.DataPoint;
Expand All @@ -37,43 +40,128 @@

import rx.Observable;

/**
*
* @author Stefan Negrea
*/
public class JsonTagsITest extends BaseMetricsITest {

@Test
public void tagValueSearch() throws Exception {
String tenantId = "t1tag";
String tenantId = "jsonT1Tag";

createTagMetrics(tenantId);

//JSON PATH queries
List<Metric<Double>> gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.foo"))
.toList()
.toSortedList((a, b) -> {
return a.getId().compareTo(b.getId());
})
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 3);
assertMetricListById(gauges, "m1", "m2", "m3");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$..foo"))
.toSortedList((a, b) -> {
return a.getId().compareTo(b.getId());
})
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 3, "Metrics m1, m2, m3 should have been returned");
assertEquals(gauges.size(), 3);
assertMetricListById(gauges, "m1", "m2", "m3");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$[?(@.foo == \"2\")]"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 1, "Metric m2 should have been returned");
assertEquals(gauges.size(), 1);
assertEquals(gauges.get(0).getId(), "m2");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$[?(@.foo == 1)]"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 1);
assertEquals(gauges.get(0).getId(), "m1");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.foo.bar"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 1, "Metric m3 should have been returned");
assertEquals(gauges.size(), 1);
assertEquals(gauges.get(0).getId(), "m3");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.foo.bar.foo"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 0);

// Request both regex and JSON Path matches
gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.foo", "a2", "3"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 4);
assertMetricListById(gauges, "m1", "m2", "m3", "m4");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a2", "3", "a1", "json:$.foo"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 4);
assertMetricListById(gauges, "m1", "m2", "m3", "m4");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.bar.foo", "a2", "3"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 1);
assertMetricListById(gauges, "m4");

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$.bar"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 0);

gauges = metricsService
.findMetricsWithFilters(tenantId, GAUGE, ImmutableMap.of("a1", "json:$..bar"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(gauges.size(), 1);
assertMetricListById(gauges, "m3");

List<Metric<AvailabilityType>> availability = metricsService
.findMetricsWithFilters(tenantId, AVAILABILITY, ImmutableMap.of("a1", "json:$.foo"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(availability.size(), 1, "Metric a1 should have been returned");
assertEquals(availability.size(), 1);
assertEquals(availability.get(0).getId(), "a1");

List<Metric<Long>> counters = metricsService
.findMetricsWithFilters(tenantId, COUNTER, ImmutableMap.of("a1", "json:$..foo"))
.toList()
.toBlocking().lastOrDefault(null);
assertEquals(counters.size(), 1);
assertEquals(counters.get(0).getId(), "c1");
}

private <T> void assertMetricListById(List<Metric<T>> actualMetrics, String... expectedMetricIds) {
for (String expectedMetricId : expectedMetricIds) {
boolean found = false;
for (Metric<T> actualMetric : actualMetrics) {
if (actualMetric.getId().equals(expectedMetricId)) {
found = true;
break;
}
}
assertTrue(found, "Metric " + expectedMetricId + " was not found in the list of returned metrics.");
}
}

protected List<Metric<?>> createTagMetrics(String tenantId) throws Exception {
protected Map<String, Metric<?>> createTagMetrics(String tenantId) throws Exception {
ImmutableList<MetricId<?>> ids = ImmutableList.of(
new MetricId<>(tenantId, GAUGE, "m1"),
new MetricId<>(tenantId, GAUGE, "m2"),
Expand All @@ -88,11 +176,12 @@ protected List<Metric<?>> createTagMetrics(String tenantId) throws Exception {
new MetricId<>(tenantId, GAUGE, "mE"),
new MetricId<>(tenantId, GAUGE, "mF"),
new MetricId<>(tenantId, GAUGE, "mG"),
new MetricId<>(tenantId, AVAILABILITY, "a1"));
new MetricId<>(tenantId, AVAILABILITY, "a1"),
new MetricId<>(tenantId, COUNTER, "c1"));

@SuppressWarnings("unchecked")
ImmutableList<ImmutableMap<String, String>> maps = ImmutableList.of(
ImmutableMap.of("a1", "{\"foo\":1}"),
ImmutableMap.of("a1", "{\"foo\":1}", "a2", "1"),
ImmutableMap.of("a1", "{\"foo\":2}"),
ImmutableMap.of("a1", "{\"foo\": {\"bar\":3}}"),
ImmutableMap.of("a1", "2", "a2", "3"),
Expand All @@ -105,7 +194,8 @@ protected List<Metric<?>> createTagMetrics(String tenantId) throws Exception {
ImmutableMap.of("owner", "hede"),
ImmutableMap.of("owner", "hades"),
ImmutableMap.of("owner", "had"),
ImmutableMap.of("a1", "{\"foo\": 3}"));
ImmutableMap.of("a1", "{\"foo\": 3}"),
ImmutableMap.of("a1", "{\"foo\": 5}"));
assertEquals(ids.size(), maps.size(), "ids' size should equal to maps' size");

// Create the metrics
Expand All @@ -123,6 +213,6 @@ protected List<Metric<?>> createTagMetrics(String tenantId) throws Exception {
Observable.from(metricsToAdd)
.subscribe(m -> metricsService.createMetric(m, false).toBlocking().lastOrDefault(null));

return metricsToAdd;
return Observable.from(metricsToAdd).toMap(e -> e.getId()).toBlocking().lastOrDefault(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright 2014-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hawkular.metrics.rest

import static org.joda.time.DateTime.now
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNotNull
import static org.junit.Assert.assertTrue

import org.joda.time.DateTime
import org.junit.Test

import groovy.json.JsonOutput


/**
* @author Stefan Negrea
*/
class JsonTagsITest extends RESTTest {

static metrics = [
['id': 'm1', 'tags': ['a1': JsonOutput.toJson(['foo': 'd']), 'b1': 'B']],
['id': 'm2', 'tags': ['a1': JsonOutput.toJson(['foo':['bar': 3]]), 'b1': 'B']],
['id': 'm3', 'tags': ['a1': JsonOutput.toJson(['foo':['bar': 4]]), 'b1': 'B']],
['id': 'm4', 'tags': ['a1': JsonOutput.toJson(['bar': 'ab']), 'b1': 'B']],
['id': 'm5', 'tags': ['a1': JsonOutput.toJson(['fizz': ['foo': ['bar': 3]]]), 'b1': 'B']],
['id': 'm6', 'tags': ['c1': 'C']]
];

@Test
void createMetricsAndUpdateTags() {
metricTypes.each {
String tenantId = nextTenantId()

def metricType = it

metrics.each {
def response = hawkularMetrics.post(path: metricType.path, body: [
id : it.id,
tags: it.tags
], headers: [(tenantHeaderName): tenantId])
assertEquals(201, response.status)

response = hawkularMetrics.get(path: metricType.path + '/' +it.id, headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertEquals([
tenantId: tenantId,
id : it.id,
tags: it.tags,
dataRetention: 7,
type: metricType.type
], response.data)
}

//match 'a1' tags with original regex tag query
def response = hawkularMetrics.get(path: "metrics",
query: [tags: "a1:*"],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm1', 'm2', 'm3', 'm4', 'm5')

//match 'a1' JSON tags that have a top property named "foo"
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$.foo'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm1', 'm2', 'm3')

//match 'a1' JSON tags that have a property named 'bar' at any level of the JSON tree
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$..bar'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm2', 'm3', 'm4', 'm5')

//match 'a1' JSON tags that have a property named 'foo'.'bar' at any level of the JSON tree
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$..foo.bar'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm2', 'm3', 'm5')

//match 'a1' JSON tags that have a property 'foo'.'bar' != 3 at any level of the JSON tree
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$..foo[?(@.bar != 3)]'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm3')

//match 'a1' JSON tags that have a property 'foo'.'bar' == 3 at any level of the JSON tree
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$..foo[?(@.bar == 3)]'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm2', 'm5')

//match 'a1' JSON tags that have a property 'bar' == 'ab' or 'bar' == 3 at any level of the JSON tree
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$..[?(@.bar == \'ab\' || @.bar == 3)]'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm2', 'm4', 'm5')

//match 'a1' JSON tags that have a property named 'bar' as a child of 'fizz', 'fizz' being a top level property
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$.fizz..bar'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm5')

//match 'a1' JSON tags that have a property 'bar' == 3 as a child of 'fizz', 'fizz' being a top level property
response = hawkularMetrics.get(path: "metrics",
query: [tags: 'a1:json:$.fizz..[?(@.bar == 3)]'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm5')

//match 'a1' JSON tags that have a property 'bar' == 3 as a child of 'fizz', 'fizz' being a top level property
// and also have a regex filter for c1 tag
response = hawkularMetrics.get(path: "metrics",
//query: [tags: 'c1:*, a1:json:$.fizz..[?(@.bar == 3)]'],
query: [tags: 'a1:json:$.fizz..[?(@.bar == 3)],c1:*'],
headers: [(tenantHeaderName): tenantId])
assertEquals(200, response.status)
assertMetricListById(response.data, 'm5', 'm6')
}
}

void assertMetricListById(actualMetrics, String... expectedMetricIds) {
assertEquals(expectedMetricIds.length, actualMetrics.size)

expectedMetricIds.each {
def expectedMetricId = it
def found = false

actualMetrics.each {
if (it['id'].equals(expectedMetricId)) {
found = true
}
}

if (!found) {
System.out.println("Metric ${expectedMetricId} was not found in the list of retrieved metrics.");
}

assertTrue(found)
}
}
}

0 comments on commit 140d7e9

Please sign in to comment.