From ed1ccf8884c6bd42e468d697f552e29258318fcf Mon Sep 17 00:00:00 2001 From: Siddhant Deshmukh Date: Wed, 17 Jul 2024 19:11:27 -0700 Subject: [PATCH] Increment latency, cpu and memory histograms for query/aggregation/sort query types (#30) * Increment latency, cpu and memory histograms for query/aggregation/sort types Signed-off-by: Siddhant Deshmukh --- .../SearchQueryAggregationCategorizer.java | 16 ++- .../categorizer/SearchQueryCategorizer.java | 39 +++--- .../SearchQueryCategorizingVisitor.java | 15 ++- .../categorizer/SearchQueryCounters.java | 48 +++++++- .../insights/QueryInsightsTestUtils.java | 19 +++ .../SearchQueryCategorizerTests.java | 111 +++++++++++++++--- 6 files changed, 202 insertions(+), 46 deletions(-) diff --git a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryAggregationCategorizer.java b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryAggregationCategorizer.java index f252795..e72e5de 100644 --- a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryAggregationCategorizer.java +++ b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryAggregationCategorizer.java @@ -8,11 +8,13 @@ package org.opensearch.plugin.insights.core.service.categorizer; +import org.opensearch.plugin.insights.rules.model.MetricType; import org.opensearch.search.aggregations.AggregationBuilder; import org.opensearch.search.aggregations.PipelineAggregationBuilder; import org.opensearch.telemetry.metrics.tags.Tags; import java.util.Collection; +import java.util.Map; /** * Increments the counters related to Aggregation Search Queries. @@ -32,24 +34,26 @@ public SearchQueryAggregationCategorizer(SearchQueryCounters searchQueryCounters /** * Increment aggregation related counters + * * @param aggregatorFactories input aggregations + * @param measurements latency, cpu, memory measurements */ - public void incrementSearchQueryAggregationCounters(Collection aggregatorFactories) { + public void incrementSearchQueryAggregationCounters(Collection aggregatorFactories, Map measurements) { for (AggregationBuilder aggregationBuilder : aggregatorFactories) { - incrementCountersRecursively(aggregationBuilder); + incrementCountersRecursively(aggregationBuilder, measurements); } } - private void incrementCountersRecursively(AggregationBuilder aggregationBuilder) { + private void incrementCountersRecursively(AggregationBuilder aggregationBuilder, Map measurements) { // Increment counters for the current aggregation String aggregationType = aggregationBuilder.getType(); - searchQueryCounters.incrementAggCounter(1, Tags.create().addTag(TYPE_TAG, aggregationType)); + searchQueryCounters.incrementAggCounter(1, Tags.create().addTag(TYPE_TAG, aggregationType), measurements); // Recursively process sub-aggregations if any Collection subAggregations = aggregationBuilder.getSubAggregations(); if (subAggregations != null && !subAggregations.isEmpty()) { for (AggregationBuilder subAggregation : subAggregations) { - incrementCountersRecursively(subAggregation); + incrementCountersRecursively(subAggregation, measurements); } } @@ -57,7 +61,7 @@ private void incrementCountersRecursively(AggregationBuilder aggregationBuilder) Collection pipelineAggregations = aggregationBuilder.getPipelineAggregations(); for (PipelineAggregationBuilder pipelineAggregation : pipelineAggregations) { String pipelineAggregationType = pipelineAggregation.getType(); - searchQueryCounters.incrementAggCounter(1, Tags.create().addTag(TYPE_TAG, pipelineAggregationType)); + searchQueryCounters.incrementAggCounter(1, Tags.create().addTag(TYPE_TAG, pipelineAggregationType), measurements); } } } diff --git a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizer.java b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizer.java index b941ed7..32a444e 100644 --- a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizer.java +++ b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizer.java @@ -13,6 +13,7 @@ import org.opensearch.index.query.QueryBuilder; import org.opensearch.index.query.QueryBuilderVisitor; import org.opensearch.plugin.insights.rules.model.Attribute; +import org.opensearch.plugin.insights.rules.model.MetricType; import org.opensearch.plugin.insights.rules.model.SearchQueryRecord; import org.opensearch.search.aggregations.AggregatorFactories; import org.opensearch.search.builder.SearchSourceBuilder; @@ -21,6 +22,7 @@ import org.opensearch.telemetry.metrics.tags.Tags; import java.util.List; +import java.util.Map; /** * Class to categorize the search queries based on the type and increment the relevant counters. @@ -64,50 +66,53 @@ public static SearchQueryCategorizer getInstance(MetricsRegistry metricsRegistry } /** - * Consume records and increment counters for the records + * Consume records and increment categorization counters and histograms for the records including latency, cpu and memory. * @param records records to consume */ public void consumeRecords(List records) { for (SearchQueryRecord record : records) { - SearchSourceBuilder source = (SearchSourceBuilder) record.getAttributes().get(Attribute.SOURCE); - categorize(source); + categorize(record); } } /** - * Increment categorizations counters for the given source search query - * @param source search query source + * Increment categorizations counters for the given search query record and + * also increment latency, cpu and memory related histograms. + * @param record search query record */ - public void categorize(SearchSourceBuilder source) { + public void categorize(SearchQueryRecord record) { + SearchSourceBuilder source = (SearchSourceBuilder) record.getAttributes().get(Attribute.SOURCE); + Map measurements = record.getMeasurements(); + QueryBuilder topLevelQueryBuilder = source.query(); logQueryShape(topLevelQueryBuilder); - incrementQueryTypeCounters(topLevelQueryBuilder); - incrementQueryAggregationCounters(source.aggregations()); - incrementQuerySortCounters(source.sorts()); + incrementQueryTypeCounters(topLevelQueryBuilder, measurements); + incrementQueryAggregationCounters(source.aggregations(), measurements); + incrementQuerySortCounters(source.sorts(), measurements); } - private void incrementQuerySortCounters(List> sorts) { + private void incrementQuerySortCounters(List> sorts, Map measurements) { if (sorts != null && sorts.size() > 0) { for (SortBuilder sortBuilder : sorts) { String sortOrder = sortBuilder.order().toString(); - searchQueryCounters.incrementSortCounter(1, Tags.create().addTag("sort_order", sortOrder)); + searchQueryCounters.incrementSortCounter(1, Tags.create().addTag("sort_order", sortOrder), measurements); } } } - private void incrementQueryAggregationCounters(AggregatorFactories.Builder aggregations) { + private void incrementQueryAggregationCounters(AggregatorFactories.Builder aggregations, Map measurements) { if (aggregations == null) { return; } - searchQueryAggregationCategorizer.incrementSearchQueryAggregationCounters(aggregations.getAggregatorFactories()); + searchQueryAggregationCategorizer.incrementSearchQueryAggregationCounters(aggregations.getAggregatorFactories(), measurements); } - private void incrementQueryTypeCounters(QueryBuilder topLevelQueryBuilder) { + private void incrementQueryTypeCounters(QueryBuilder topLevelQueryBuilder, Map measurements) { if (topLevelQueryBuilder == null) { return; } - QueryBuilderVisitor searchQueryVisitor = new SearchQueryCategorizingVisitor(searchQueryCounters); + QueryBuilderVisitor searchQueryVisitor = new SearchQueryCategorizingVisitor(searchQueryCounters, measurements); topLevelQueryBuilder.visit(searchQueryVisitor); } @@ -134,6 +139,8 @@ public SearchQueryCounters getSearchQueryCounters() { * Reset the search query categorizer and its counters */ public void reset() { - instance = null; + synchronized (SearchQueryCategorizer.class) { + instance = null; + } } } diff --git a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizingVisitor.java b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizingVisitor.java index d4762e6..fcccb4b 100644 --- a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizingVisitor.java +++ b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCategorizingVisitor.java @@ -11,6 +11,9 @@ import org.apache.lucene.search.BooleanClause; import org.opensearch.index.query.QueryBuilder; import org.opensearch.index.query.QueryBuilderVisitor; +import org.opensearch.plugin.insights.rules.model.MetricType; + +import java.util.Map; /** * Class to visit the query builder tree and also track the level information. @@ -19,21 +22,23 @@ final class SearchQueryCategorizingVisitor implements QueryBuilderVisitor { private final int level; private final SearchQueryCounters searchQueryCounters; + private final Map measurements; - public SearchQueryCategorizingVisitor(SearchQueryCounters searchQueryCounters) { - this(searchQueryCounters, 0); + public SearchQueryCategorizingVisitor(SearchQueryCounters searchQueryCounters, Map measurements) { + this(searchQueryCounters, 0, measurements); } - private SearchQueryCategorizingVisitor(SearchQueryCounters counters, int level) { + private SearchQueryCategorizingVisitor(SearchQueryCounters counters, int level, Map measurements) { this.searchQueryCounters = counters; this.level = level; + this.measurements = measurements; } public void accept(QueryBuilder qb) { - searchQueryCounters.incrementCounter(qb, level); + searchQueryCounters.incrementCounter(qb, level, measurements); } public QueryBuilderVisitor getChildVisitor(BooleanClause.Occur occur) { - return new SearchQueryCategorizingVisitor(searchQueryCounters, level + 1); + return new SearchQueryCategorizingVisitor(searchQueryCounters, level + 1, measurements); } } diff --git a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCounters.java b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCounters.java index 7a272b6..ccf0e0f 100644 --- a/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCounters.java +++ b/src/main/java/org/opensearch/plugin/insights/core/service/categorizer/SearchQueryCounters.java @@ -9,7 +9,9 @@ package org.opensearch.plugin.insights.core.service.categorizer; import org.opensearch.index.query.QueryBuilder; +import org.opensearch.plugin.insights.rules.model.MetricType; import org.opensearch.telemetry.metrics.Counter; +import org.opensearch.telemetry.metrics.Histogram; import org.opensearch.telemetry.metrics.MetricsRegistry; import org.opensearch.telemetry.metrics.tags.Tags; @@ -22,6 +24,7 @@ */ public final class SearchQueryCounters { private static final String LEVEL_TAG = "level"; + private static final String TYPE_TAG = "type"; private static final String UNIT = "1"; private final MetricsRegistry metricsRegistry; /** @@ -36,6 +39,20 @@ public final class SearchQueryCounters { * Counter for sort */ private final Counter sortCounter; + + /** + * Histogram for latency per query type + */ + private final Histogram queryTypeLatencyHistogram; + /** + * Histogram for cpu per query type + */ + private final Histogram queryTypeCpuHistogram; + /** + * Histogram for memory per query type + */ + private final Histogram queryTypeMemoryHistogram; + private final Map, Counter> queryHandlers; /** * Counter name to Counter object map @@ -64,8 +81,22 @@ public SearchQueryCounters(MetricsRegistry metricsRegistry) { "Counter for the number of top level sort search queries", UNIT ); + this.queryTypeLatencyHistogram = metricsRegistry.createHistogram( + "search.query.type.latency.histogram", + "Histogram for the latency per query type", + UNIT + ); + this.queryTypeCpuHistogram = metricsRegistry.createHistogram( + "search.query.type.cpu.histogram", + "Histogram for the cpu per query type", + UNIT + ); + this.queryTypeMemoryHistogram = metricsRegistry.createHistogram( + "search.query.type.memory.histogram", + "Histogram for the memory per query type", + UNIT + ); this.queryHandlers = new HashMap<>(); - } /** @@ -73,11 +104,12 @@ public SearchQueryCounters(MetricsRegistry metricsRegistry) { * @param queryBuilder query builder * @param level level of query builder, 0 being highest level */ - public void incrementCounter(QueryBuilder queryBuilder, int level) { + public void incrementCounter(QueryBuilder queryBuilder, int level, Map measurements) { String uniqueQueryCounterName = queryBuilder.getName(); Counter counter = nameToQueryTypeCounters.computeIfAbsent(uniqueQueryCounterName, k -> createQueryCounter(k)); counter.add(1, Tags.create().addTag(LEVEL_TAG, level)); + incrementAllHistograms(Tags.create().addTag(LEVEL_TAG, level).addTag(TYPE_TAG, uniqueQueryCounterName), measurements); } /** @@ -85,8 +117,9 @@ public void incrementCounter(QueryBuilder queryBuilder, int level) { * @param value value to increment * @param tags tags */ - public void incrementAggCounter(double value, Tags tags) { + public void incrementAggCounter(double value, Tags tags, Map measurements) { aggCounter.add(value, tags); + incrementAllHistograms(tags, measurements); } /** @@ -94,8 +127,15 @@ public void incrementAggCounter(double value, Tags tags) { * @param value value to increment * @param tags tags */ - public void incrementSortCounter(double value, Tags tags) { + public void incrementSortCounter(double value, Tags tags, Map measurements) { sortCounter.add(value, tags); + incrementAllHistograms(tags, measurements); + } + + private void incrementAllHistograms(Tags tags, Map measurements) { + queryTypeLatencyHistogram.record(measurements.get(MetricType.LATENCY).doubleValue(), tags); + queryTypeCpuHistogram.record(measurements.get(MetricType.CPU).doubleValue(), tags); + queryTypeMemoryHistogram.record(measurements.get(MetricType.MEMORY).doubleValue(), tags); } /** diff --git a/src/test/java/org/opensearch/plugin/insights/QueryInsightsTestUtils.java b/src/test/java/org/opensearch/plugin/insights/QueryInsightsTestUtils.java index c1b4e54..a96533d 100644 --- a/src/test/java/org/opensearch/plugin/insights/QueryInsightsTestUtils.java +++ b/src/test/java/org/opensearch/plugin/insights/QueryInsightsTestUtils.java @@ -52,10 +52,29 @@ final public class QueryInsightsTestUtils { public QueryInsightsTestUtils() {} + /** + * Returns list of randomly generated search query records. + * @param count number of records + * @return List of records + */ public static List generateQueryInsightRecords(int count) { return generateQueryInsightRecords(count, count, System.currentTimeMillis(), 0); } + /** + * Returns list of randomly generated search query records. + * @param count number of records + * @param searchSourceBuilder source + * @return List of records + */ + public static List generateQueryInsightRecords(int count, SearchSourceBuilder searchSourceBuilder) { + List records = generateQueryInsightRecords(count, count, System.currentTimeMillis(), 0); + for (SearchQueryRecord record : records) { + record.getAttributes().put(Attribute.SOURCE, searchSourceBuilder); + } + return records; + } + /** * Creates a List of random Query Insight Records for testing purpose */ diff --git a/src/test/java/org/opensearch/plugin/insights/core/service/categorizor/SearchQueryCategorizerTests.java b/src/test/java/org/opensearch/plugin/insights/core/service/categorizor/SearchQueryCategorizerTests.java index 643b514..7ce2499 100644 --- a/src/test/java/org/opensearch/plugin/insights/core/service/categorizor/SearchQueryCategorizerTests.java +++ b/src/test/java/org/opensearch/plugin/insights/core/service/categorizor/SearchQueryCategorizerTests.java @@ -9,7 +9,8 @@ package org.opensearch.plugin.insights.core.service.categorizor; import org.junit.After; -import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.opensearch.index.query.BoolQueryBuilder; import org.opensearch.index.query.BoostingQueryBuilder; import org.opensearch.index.query.MatchNoneQueryBuilder; @@ -23,6 +24,8 @@ import org.opensearch.index.query.WildcardQueryBuilder; import org.opensearch.index.query.functionscore.FunctionScoreQueryBuilder; import org.opensearch.plugin.insights.core.service.categorizer.SearchQueryCategorizer; +import org.opensearch.plugin.insights.rules.model.MetricType; +import org.opensearch.plugin.insights.rules.model.SearchQueryRecord; import org.opensearch.search.aggregations.bucket.range.RangeAggregationBuilder; import org.opensearch.search.aggregations.bucket.terms.MultiTermsAggregationBuilder; import org.opensearch.search.aggregations.support.MultiTermsValuesSourceConfig; @@ -30,12 +33,15 @@ import org.opensearch.search.sort.ScoreSortBuilder; import org.opensearch.search.sort.SortOrder; import org.opensearch.telemetry.metrics.Counter; +import org.opensearch.telemetry.metrics.Histogram; import org.opensearch.telemetry.metrics.MetricsRegistry; import org.opensearch.telemetry.metrics.tags.Tags; import org.opensearch.test.OpenSearchTestCase; import org.junit.Before; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.mockito.ArgumentCaptor; @@ -45,6 +51,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.opensearch.plugin.insights.QueryInsightsTestUtils.generateQueryInsightRecords; public final class SearchQueryCategorizerTests extends OpenSearchTestCase { @@ -54,12 +61,29 @@ public final class SearchQueryCategorizerTests extends OpenSearchTestCase { private SearchQueryCategorizer searchQueryCategorizer; + private Map histogramMap = new HashMap<>(); + @Before public void setup() { + SearchQueryCategorizer.getInstance(mock(MetricsRegistry.class)).reset(); metricsRegistry = mock(MetricsRegistry.class); when(metricsRegistry.createCounter(any(String.class), any(String.class), any(String.class))).thenAnswer( invocation -> mock(Counter.class) ); + + when(metricsRegistry.createHistogram(any(String.class), any(String.class), any(String.class))) + .thenAnswer(new Answer() { + @Override + public Histogram answer(InvocationOnMock invocation) throws Throwable { + // Extract arguments to identify which histogram is being created + String name = invocation.getArgument(0); + // Create a mock histogram + Histogram histogram = mock(Histogram.class); + // Store histogram in map for lookup + histogramMap.put(name, histogram); + return histogram; + } + }); searchQueryCategorizer = SearchQueryCategorizer.getInstance(metricsRegistry); } @@ -80,7 +104,10 @@ public void testAggregationsQuery() { ); sourceBuilder.size(0); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getAggCounter()).add(eq(1.0d), any(Tags.class)); @@ -101,7 +128,10 @@ public void testBoolQuery() { sourceBuilder.size(50); sourceBuilder.query(new BoolQueryBuilder().must(new MatchQueryBuilder("searchText", "fox"))); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 2); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("bool")).add(eq(1.0d), any(Tags.class)); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match")).add(eq(1.0d), any(Tags.class)); @@ -112,7 +142,10 @@ public void testFunctionScoreQuery() { sourceBuilder.size(50); sourceBuilder.query(new FunctionScoreQueryBuilder(QueryBuilders.prefixQuery("text", "bro"))); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("function_score")).add( eq(1.0d), @@ -125,7 +158,10 @@ public void testMatchQuery() { sourceBuilder.size(50); sourceBuilder.query(QueryBuilders.matchQuery("tags", "php")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match")).add(eq(1.0d), any(Tags.class)); } @@ -135,7 +171,10 @@ public void testMatchPhraseQuery() { sourceBuilder.size(50); sourceBuilder.query(QueryBuilders.matchPhraseQuery("tags", "php")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match_phrase")).add(eq(1.0d), any(Tags.class)); } @@ -145,7 +184,10 @@ public void testMultiMatchQuery() { sourceBuilder.size(50); sourceBuilder.query(new MultiMatchQueryBuilder("foo bar", "myField")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("multi_match")).add(eq(1.0d), any(Tags.class)); } @@ -159,7 +201,10 @@ public void testOtherQuery() { ); sourceBuilder.query(queryBuilder); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 3); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("boosting")).add(eq(1.0d), any(Tags.class)); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match_none")).add(eq(1.0d), any(Tags.class)); @@ -172,7 +217,10 @@ public void testQueryStringQuery() { QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder("foo:*"); sourceBuilder.query(queryBuilder); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("query_string")).add(eq(1.0d), any(Tags.class)); } @@ -184,7 +232,10 @@ public void testRangeQuery() { rangeQuery.lt("1982-01-01"); sourceBuilder.query(rangeQuery); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("range")).add(eq(1.0d), any(Tags.class)); } @@ -193,7 +244,10 @@ public void testRegexQuery() { SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(new RegexpQueryBuilder("field", "text")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("regexp")).add(eq(1.0d), any(Tags.class)); } @@ -204,7 +258,10 @@ public void testSortQuery() { sourceBuilder.sort("creationDate", SortOrder.DESC); sourceBuilder.sort(new ScoreSortBuilder()); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 3); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match")).add(eq(1.0d), any(Tags.class)); verify(searchQueryCategorizer.getSearchQueryCounters().getSortCounter(), times(2)).add(eq(1.0d), any(Tags.class)); @@ -215,7 +272,10 @@ public void testTermQuery() { sourceBuilder.size(50); sourceBuilder.query(QueryBuilders.termQuery("field", "value2")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("term")).add(eq(1.0d), any(Tags.class)); } @@ -225,7 +285,10 @@ public void testWildcardQuery() { sourceBuilder.size(50); sourceBuilder.query(new WildcardQueryBuilder("field", "text")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 1); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("wildcard")).add(eq(1.0d), any(Tags.class)); } @@ -243,7 +306,10 @@ public void testComplexQuery() { sourceBuilder.query(boolQueryBuilder); sourceBuilder.aggregation(new RangeAggregationBuilder("agg1").field("num")); - searchQueryCategorizer.categorize(sourceBuilder); + SearchQueryRecord record = generateQueryInsightRecords(1, sourceBuilder).get(0); + searchQueryCategorizer.categorize(record); + + verifyMeasurementHistogramsIncremented(record, 5); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("term")).add(eq(1.0d), any(Tags.class)); verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("match")).add(eq(1.0d), any(Tags.class)); @@ -251,4 +317,19 @@ public void testComplexQuery() { verify(searchQueryCategorizer.getSearchQueryCounters().getCounterByQueryBuilderName("bool")).add(eq(1.0d), any(Tags.class)); verify(searchQueryCategorizer.getSearchQueryCounters().getAggCounter()).add(eq(1.0d), any(Tags.class)); } + + private void verifyMeasurementHistogramsIncremented(SearchQueryRecord record, int times) { + Double expectedLatency = record.getMeasurement(MetricType.LATENCY).doubleValue(); + Double expectedCpu = record.getMeasurement(MetricType.CPU).doubleValue(); + Double expectedMemory = record.getMeasurement(MetricType.MEMORY).doubleValue(); + + Histogram queryTypeLatencyHistogram = histogramMap.get("search.query.type.latency.histogram"); + Histogram queryTypeCpuHistogram = histogramMap.get("search.query.type.cpu.histogram"); + Histogram queryTypeMemoryHistogram = histogramMap.get("search.query.type.memory.histogram"); + + + verify(queryTypeLatencyHistogram, times(times)).record(eq(expectedLatency), any(Tags.class)); + verify(queryTypeCpuHistogram, times(times)).record(eq(expectedCpu), any(Tags.class)); + verify(queryTypeMemoryHistogram, times(times)).record(eq(expectedMemory), any(Tags.class)); + } }