Skip to content

Commit

Permalink
Add total rule type counts to list calls and xpack usage
Browse files Browse the repository at this point in the history
  • Loading branch information
kderusso committed Nov 6, 2024
1 parent 8db9181 commit 4e6cedd
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 59 deletions.
237 changes: 200 additions & 37 deletions docs/reference/search/retriever.asciidoc

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ static TransportVersion def(int id) {
public static final TransportVersion ESQL_CCS_EXEC_INFO_WITH_FAILURES = def(8_783_00_0);
public static final TransportVersion LOGSDB_TELEMETRY = def(8_784_00_0);
public static final TransportVersion LOGSDB_TELEMETRY_STATS = def(8_785_00_0);
public static final TransportVersion QUERY_RULES_LIST_INCLUDES_TYPES = def(8_786_00_0);

/*
* STOP! READ THIS FIRST! No, really,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class EnterpriseSearchFeatureSetUsage extends XPackFeatureUsage {
public static final String MIN_RULE_COUNT = "min_rule_count";
public static final String MAX_RULE_COUNT = "max_rule_count";
public static final String RULE_CRITERIA_TOTAL_COUNTS = "rule_criteria_total_counts";
public static final String RULE_TYPE_TOTAL_COUNTS = "rule_type_total_counts";

private final Map<String, Object> searchApplicationsUsage;
private final Map<String, Object> analyticsCollectionsUsage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ teardown:
- 'id1'
- 'id2'
- rule_id: query-rule-id2
type: pinned
type: exclude
criteria:
- type: exact
metadata: query_string
Expand Down Expand Up @@ -199,7 +199,7 @@ teardown:
available: true,
search_applications: { count: 1 },
analytics_collections: { count: 0 },
query_rulesets: { total_count: 2, total_rule_count: 5, min_rule_count: 2, max_rule_count: 3, rule_criteria_total_counts: { exact: 5 } }
query_rulesets: { total_count: 2, total_rule_count: 5, min_rule_count: 2, max_rule_count: 3, rule_criteria_total_counts: { exact: 5 }, rule_type_total_counts: { pinned: 4, exclude: 1 } }
}
}

Expand All @@ -216,7 +216,7 @@ teardown:
available: true,
search_applications: { count: 1 },
analytics_collections: { count: 0 },
query_rulesets: { total_count: 1, total_rule_count: 2, min_rule_count: 2, max_rule_count: 2, rule_criteria_total_counts: { exact: 2 } }
query_rulesets: { total_count: 1, total_rule_count: 2, min_rule_count: 2, max_rule_count: 2, rule_criteria_total_counts: { exact: 2 }, rule_type_total_counts: { pinned: 1, exclude: 1 } }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,17 @@ teardown:
- match: { results.0.ruleset_id: "test-query-ruleset-1" }
- match: { results.0.rule_total_count: 3 }
- match: { results.0.rule_criteria_types_counts: { exact: 3 } }
- match: { results.0.rule_type_counts: { pinned: 3, } }

- match: { results.1.ruleset_id: "test-query-ruleset-2" }
- match: { results.1.rule_total_count: 5 }
- match: { results.1.rule_criteria_types_counts: { exact: 4, fuzzy: 1 } }
- match: { results.1.rule_type_counts: { pinned: 4, exclude: 1 } }

- match: { results.2.ruleset_id: "test-query-ruleset-3" }
- match: { results.2.rule_total_count: 2 }
- match: { results.2.rule_criteria_types_counts: { exact: 2 } }
- match: { results.2.rule_type_counts: { pinned: 2 } }

---
"List Query Rulesets - with from":
Expand All @@ -173,10 +176,12 @@ teardown:
- match: { results.0.ruleset_id: "test-query-ruleset-2" }
- match: { results.0.rule_total_count: 5 }
- match: { results.0.rule_criteria_types_counts: { exact: 4, fuzzy: 1 } }
- match: { results.0.rule_type_counts: { pinned: 4, exclude: 1 } }

- match: { results.1.ruleset_id: "test-query-ruleset-3" }
- match: { results.1.rule_total_count: 2 }
- match: { results.1.rule_criteria_types_counts: { exact: 2 } }
- match: { results.1.rule_type_counts: { pinned: 2 } }

---
"List Query Rulesets - with size":
Expand All @@ -190,10 +195,12 @@ teardown:
- match: { results.0.ruleset_id: "test-query-ruleset-1" }
- match: { results.0.rule_total_count: 3 }
- match: { results.0.rule_criteria_types_counts: { exact: 3 } }
- match: { results.0.rule_type_counts: { pinned: 3 } }

- match: { results.1.ruleset_id: "test-query-ruleset-2" }
- match: { results.1.rule_total_count: 5 }
- match: { results.1.rule_criteria_types_counts: { exact: 4, fuzzy: 1 } }
- match: { results.1.rule_type_counts: { pinned: 4, exclude: 1 } }

---
"List Query Rulesets - empty":
Expand Down Expand Up @@ -222,7 +229,7 @@ teardown:
body:
rules:
- rule_id: query-rule-id1
type: pinned
type: exclude
criteria:
- type: exact
metadata: query_string
Expand Down Expand Up @@ -294,6 +301,7 @@ teardown:
prefix: 1
suffix: 1
always: 1
- match: { results.0.rule_type_counts: { pinned: 4, exclude: 1 } }

---
'List Query Rulesets - Insufficient privilege':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.application.analytics.action.GetAnalyticsCollectionAction;
import org.elasticsearch.xpack.application.rules.QueryRuleCriteriaType;
import org.elasticsearch.xpack.application.rules.QueryRulesIndexService;
import org.elasticsearch.xpack.application.rules.QueryRulesetListItem;
import org.elasticsearch.xpack.application.rules.action.ListQueryRulesetsAction;
Expand All @@ -41,7 +40,6 @@
import org.elasticsearch.xpack.core.application.EnterpriseSearchFeatureSetUsage;

import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
Expand Down Expand Up @@ -226,20 +224,29 @@ private void addQueryRulesetUsage(ListQueryRulesetsAction.Response response, Map
List<QueryRulesetListItem> results = response.queryPage().results();
IntSummaryStatistics ruleStats = results.stream().mapToInt(QueryRulesetListItem::ruleTotalCount).summaryStatistics();

Map<QueryRuleCriteriaType, Integer> criteriaTypeCountMap = new EnumMap<>(QueryRuleCriteriaType.class);
results.stream()
.flatMap(result -> result.criteriaTypeToCountMap().entrySet().stream())
.forEach(entry -> criteriaTypeCountMap.merge(entry.getKey(), entry.getValue(), Integer::sum));
Map<String, Object> ruleCriteriaTypeCountMap = new HashMap<>();
Map<String, Object> ruleTypeCountMap = new HashMap<>();

Map<String, Object> rulesTypeCountMap = new HashMap<>();
criteriaTypeCountMap.forEach((criteriaType, count) -> rulesTypeCountMap.put(criteriaType.name().toLowerCase(Locale.ROOT), count));
results.forEach(result -> {
populateCounts(ruleCriteriaTypeCountMap, result.criteriaTypeToCountMap());
populateCounts(ruleTypeCountMap, result.ruleTypeToCountMap());
});

queryRulesUsage.put(TOTAL_COUNT, response.queryPage().count());
queryRulesUsage.put(TOTAL_RULE_COUNT, ruleStats.getSum());
queryRulesUsage.put(MIN_RULE_COUNT, results.isEmpty() ? 0 : ruleStats.getMin());
queryRulesUsage.put(MAX_RULE_COUNT, results.isEmpty() ? 0 : ruleStats.getMax());
if (rulesTypeCountMap.isEmpty() == false) {
queryRulesUsage.put(RULE_CRITERIA_TOTAL_COUNTS, rulesTypeCountMap);
if (ruleCriteriaTypeCountMap.isEmpty() == false) {
queryRulesUsage.put(RULE_CRITERIA_TOTAL_COUNTS, ruleCriteriaTypeCountMap);
}
if (ruleTypeCountMap.isEmpty() == false) {
queryRulesUsage.put(EnterpriseSearchFeatureSetUsage.RULE_TYPE_TOTAL_COUNTS, ruleTypeCountMap);
}
}

private void populateCounts(Map<String, Object> targetMap, Map<? extends Enum<?>, Integer> sourceMap) {
sourceMap.forEach(
(key, value) -> targetMap.merge(key.name().toLowerCase(Locale.ROOT), value, (v1, v2) -> (Integer) v1 + (Integer) v2)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ private static QueryRulesetListItem hitToQueryRulesetListItem(SearchHit searchHi
final List<LinkedHashMap<?, ?>> rules = ((List<LinkedHashMap<?, ?>>) sourceMap.get(QueryRuleset.RULES_FIELD.getPreferredName()));
final int numRules = rules.size();
final Map<QueryRuleCriteriaType, Integer> queryRuleCriteriaTypeToCountMap = new EnumMap<>(QueryRuleCriteriaType.class);
final Map<QueryRule.QueryRuleType, Integer> ruleTypeToCountMap = new EnumMap<>(QueryRule.QueryRuleType.class);
for (LinkedHashMap<?, ?> rule : rules) {
@SuppressWarnings("unchecked")
List<LinkedHashMap<?, ?>> criteriaList = ((List<LinkedHashMap<?, ?>>) rule.get(QueryRule.CRITERIA_FIELD.getPreferredName()));
Expand All @@ -453,9 +454,12 @@ private static QueryRulesetListItem hitToQueryRulesetListItem(SearchHit searchHi
final QueryRuleCriteriaType queryRuleCriteriaType = QueryRuleCriteriaType.type(criteriaType);
queryRuleCriteriaTypeToCountMap.compute(queryRuleCriteriaType, (k, v) -> v == null ? 1 : v + 1);
}
final String ruleType = ((String) rule.get(QueryRule.TYPE_FIELD.getPreferredName()));
final QueryRule.QueryRuleType queryRuleType = QueryRule.QueryRuleType.queryRuleType(ruleType);
ruleTypeToCountMap.compute(queryRuleType, (k, v) -> v == null ? 1 : v + 1);
}

return new QueryRulesetListItem(rulesetId, numRules, queryRuleCriteriaTypeToCountMap);
return new QueryRulesetListItem(rulesetId, numRules, queryRuleCriteriaTypeToCountMap, ruleTypeToCountMap);
}

public record QueryRulesetResult(List<QueryRulesetListItem> rulesets, long totalResults) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ public class QueryRulesetListItem implements Writeable, ToXContentObject {
public static final ParseField RULESET_ID_FIELD = new ParseField("ruleset_id");
public static final ParseField RULE_TOTAL_COUNT_FIELD = new ParseField("rule_total_count");
public static final ParseField RULE_CRITERIA_TYPE_COUNTS_FIELD = new ParseField("rule_criteria_types_counts");
public static final ParseField RULE_TYPE_COUNTS_FIELD = new ParseField("rule_type_counts");

private final String rulesetId;
private final int ruleTotalCount;
private final Map<QueryRuleCriteriaType, Integer> criteriaTypeToCountMap;
private final Map<QueryRule.QueryRuleType, Integer> ruleTypeToCountMap;

/**
* Constructs a QueryRulesetListItem.
Expand All @@ -44,11 +46,17 @@ public class QueryRulesetListItem implements Writeable, ToXContentObject {
* @param ruleTotalCount The number of rules contained within the ruleset.
* @param criteriaTypeToCountMap A map of criteria type to the number of rules of that type.
*/
public QueryRulesetListItem(String rulesetId, int ruleTotalCount, Map<QueryRuleCriteriaType, Integer> criteriaTypeToCountMap) {
public QueryRulesetListItem(
String rulesetId,
int ruleTotalCount,
Map<QueryRuleCriteriaType, Integer> criteriaTypeToCountMap,
Map<QueryRule.QueryRuleType, Integer> ruleTypeToCountMap
) {
Objects.requireNonNull(rulesetId, "rulesetId cannot be null on a QueryRuleListItem");
this.rulesetId = rulesetId;
this.ruleTotalCount = ruleTotalCount;
this.criteriaTypeToCountMap = criteriaTypeToCountMap;
this.ruleTypeToCountMap = ruleTypeToCountMap;
}

public QueryRulesetListItem(StreamInput in) throws IOException {
Expand All @@ -59,6 +67,11 @@ public QueryRulesetListItem(StreamInput in) throws IOException {
} else {
this.criteriaTypeToCountMap = Map.of();
}
if (in.getTransportVersion().onOrAfter(TransportVersions.QUERY_RULES_LIST_INCLUDES_TYPES)) {
this.ruleTypeToCountMap = in.readMap(m -> in.readEnum(QueryRule.QueryRuleType.class), StreamInput::readInt);
} else {
this.ruleTypeToCountMap = Map.of();
}
}

@Override
Expand All @@ -71,6 +84,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
builder.field(criteriaType.name().toLowerCase(Locale.ROOT), criteriaTypeToCountMap.get(criteriaType));
}
builder.endObject();
builder.startObject(RULE_TYPE_COUNTS_FIELD.getPreferredName());
for (QueryRule.QueryRuleType ruleType : ruleTypeToCountMap.keySet()) {
builder.field(ruleType.name().toLowerCase(Locale.ROOT), ruleTypeToCountMap.get(ruleType));
}
builder.endObject();
builder.endObject();
return builder;
}
Expand All @@ -82,6 +100,9 @@ public void writeTo(StreamOutput out) throws IOException {
if (out.getTransportVersion().onOrAfter(EXPANDED_RULESET_COUNT_TRANSPORT_VERSION)) {
out.writeMap(criteriaTypeToCountMap, StreamOutput::writeEnum, StreamOutput::writeInt);
}
if (out.getTransportVersion().onOrAfter(TransportVersions.QUERY_RULES_LIST_INCLUDES_TYPES)) {
out.writeMap(ruleTypeToCountMap, StreamOutput::writeEnum, StreamOutput::writeInt);
}
}

/**
Expand All @@ -106,18 +127,23 @@ public Map<QueryRuleCriteriaType, Integer> criteriaTypeToCountMap() {
return criteriaTypeToCountMap;
}

public Map<QueryRule.QueryRuleType, Integer> ruleTypeToCountMap() {
return ruleTypeToCountMap;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueryRulesetListItem that = (QueryRulesetListItem) o;
return ruleTotalCount == that.ruleTotalCount
&& Objects.equals(rulesetId, that.rulesetId)
&& Objects.equals(criteriaTypeToCountMap, that.criteriaTypeToCountMap);
&& Objects.equals(criteriaTypeToCountMap, that.criteriaTypeToCountMap)
&& Objects.equals(ruleTypeToCountMap, that.ruleTypeToCountMap);
}

@Override
public int hashCode() {
return Objects.hash(rulesetId, ruleTotalCount, criteriaTypeToCountMap);
return Objects.hash(rulesetId, ruleTotalCount, criteriaTypeToCountMap, ruleTypeToCountMap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
package org.elasticsearch.xpack.application.rules.action;

import org.elasticsearch.TransportVersion;
import org.elasticsearch.TransportVersions;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.xpack.application.EnterpriseSearchModuleTestUtils;
import org.elasticsearch.xpack.application.rules.QueryRule;
import org.elasticsearch.xpack.application.rules.QueryRuleCriteriaType;
import org.elasticsearch.xpack.application.rules.QueryRuleset;
import org.elasticsearch.xpack.application.rules.QueryRulesetListItem;
Expand All @@ -32,9 +34,13 @@ private static ListQueryRulesetsAction.Response randomQueryRulesetListItem() {
QueryRuleset queryRuleset = EnterpriseSearchModuleTestUtils.randomQueryRuleset();
Map<QueryRuleCriteriaType, Integer> criteriaTypeToCountMap = Map.of(
randomFrom(QueryRuleCriteriaType.values()),
randomIntBetween(0, 10)
randomIntBetween(1, 10)
);
return new QueryRulesetListItem(queryRuleset.id(), queryRuleset.rules().size(), criteriaTypeToCountMap);
Map<QueryRule.QueryRuleType, Integer> ruleTypeToCountMap = Map.of(
randomFrom(QueryRule.QueryRuleType.values()),
randomIntBetween(1, 10)
);
return new QueryRulesetListItem(queryRuleset.id(), queryRuleset.rules().size(), criteriaTypeToCountMap, ruleTypeToCountMap);
}), randomLongBetween(0, 1000));
}

Expand All @@ -53,12 +59,20 @@ protected ListQueryRulesetsAction.Response mutateInstanceForVersion(
ListQueryRulesetsAction.Response instance,
TransportVersion version
) {
if (version.onOrAfter(QueryRulesetListItem.EXPANDED_RULESET_COUNT_TRANSPORT_VERSION)) {
if (version.onOrAfter(TransportVersions.QUERY_RULES_LIST_INCLUDES_TYPES)) {
return instance;
} else if (version.onOrAfter(QueryRulesetListItem.EXPANDED_RULESET_COUNT_TRANSPORT_VERSION)) {
List<QueryRulesetListItem> updatedResults = new ArrayList<>();
for (QueryRulesetListItem listItem : instance.queryPage.results()) {
updatedResults.add(
new QueryRulesetListItem(listItem.rulesetId(), listItem.ruleTotalCount(), listItem.criteriaTypeToCountMap(), Map.of())
);
}
return new ListQueryRulesetsAction.Response(updatedResults, instance.queryPage.count());
} else {
List<QueryRulesetListItem> updatedResults = new ArrayList<>();
for (QueryRulesetListItem listItem : instance.queryPage.results()) {
updatedResults.add(new QueryRulesetListItem(listItem.rulesetId(), listItem.ruleTotalCount(), Map.of()));
updatedResults.add(new QueryRulesetListItem(listItem.rulesetId(), listItem.ruleTotalCount(), Map.of(), Map.of()));
}
return new ListQueryRulesetsAction.Response(updatedResults, instance.queryPage.count());
}
Expand Down

0 comments on commit 4e6cedd

Please sign in to comment.