[ML] Support multiple rule actions and renames (elastic/x-pack-elasticsearch#3356)

Relates elastic/x-pack-elasticsearch#3325

Original commit: elastic/x-pack-elasticsearch@a7f400aeeb
This commit is contained in:
Dimitris Athanasiou 2017-12-19 16:28:36 +00:00 committed by GitHub
parent f1f1be3927
commit 08a35d44c6
20 changed files with 211 additions and 200 deletions

View File

@ -150,7 +150,7 @@ public class SpecialEvent implements ToXContentObject, Writeable {
conditions.add(RuleCondition.createTime(Operator.LT, bucketEndTime));
DetectionRule.Builder builder = new DetectionRule.Builder(conditions);
builder.setRuleAction(RuleAction.SKIP_SAMPLING_AND_FILTER_RESULTS);
builder.setActions(RuleAction.FILTER_RESULTS, RuleAction.SKIP_SAMPLING);
builder.setConditionsConnective(Connective.AND);
return builder.build();
}

View File

@ -21,8 +21,10 @@ import org.elasticsearch.xpack.ml.utils.ExceptionsHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -32,11 +34,11 @@ import java.util.stream.Collectors;
public class DetectionRule implements ToXContentObject, Writeable {
public static final ParseField DETECTION_RULE_FIELD = new ParseField("detection_rule");
public static final ParseField RULE_ACTION_FIELD = new ParseField("rule_action");
public static final ParseField ACTIONS_FIELD = new ParseField("actions");
public static final ParseField TARGET_FIELD_NAME_FIELD = new ParseField("target_field_name");
public static final ParseField TARGET_FIELD_VALUE_FIELD = new ParseField("target_field_value");
public static final ParseField CONDITIONS_CONNECTIVE_FIELD = new ParseField("conditions_connective");
public static final ParseField RULE_CONDITIONS_FIELD = new ParseField("rule_conditions");
public static final ParseField CONDITIONS_FIELD = new ParseField("conditions");
// These parsers follow the pattern that metadata is parsed leniently (to allow for enhancements), whilst config is parsed strictly
public static final ObjectParser<Builder, Void> METADATA_PARSER =
@ -51,12 +53,7 @@ public class DetectionRule implements ToXContentObject, Writeable {
for (MlParserType parserType : MlParserType.values()) {
ObjectParser<Builder, Void> parser = PARSERS.get(parserType);
assert parser != null;
parser.declareField(Builder::setRuleAction, p -> {
if (p.currentToken() == XContentParser.Token.VALUE_STRING) {
return RuleAction.fromString(p.text());
}
throw new IllegalArgumentException("Unsupported token [" + p.currentToken() + "]");
}, RULE_ACTION_FIELD, ValueType.STRING);
parser.declareStringArray(Builder::setActions, ACTIONS_FIELD);
parser.declareString(Builder::setTargetFieldName, TARGET_FIELD_NAME_FIELD);
parser.declareString(Builder::setTargetFieldValue, TARGET_FIELD_VALUE_FIELD);
parser.declareField(Builder::setConditionsConnective, p -> {
@ -65,33 +62,38 @@ public class DetectionRule implements ToXContentObject, Writeable {
}
throw new IllegalArgumentException("Unsupported token [" + p.currentToken() + "]");
}, CONDITIONS_CONNECTIVE_FIELD, ValueType.STRING);
parser.declareObjectArray(Builder::setRuleConditions, (p, c) ->
RuleCondition.PARSERS.get(parserType).apply(p, c), RULE_CONDITIONS_FIELD);
parser.declareObjectArray(Builder::setConditions, (p, c) ->
RuleCondition.PARSERS.get(parserType).apply(p, c), CONDITIONS_FIELD);
}
}
private final RuleAction ruleAction;
private final EnumSet<RuleAction> actions;
private final String targetFieldName;
private final String targetFieldValue;
private final Connective conditionsConnective;
private final List<RuleCondition> ruleConditions;
private final List<RuleCondition> conditions;
private DetectionRule(RuleAction ruleAction, @Nullable String targetFieldName, @Nullable String targetFieldValue,
Connective conditionsConnective, List<RuleCondition> ruleConditions) {
this.ruleAction = Objects.requireNonNull(ruleAction);
private DetectionRule(EnumSet<RuleAction> actions, @Nullable String targetFieldName, @Nullable String targetFieldValue,
Connective conditionsConnective, List<RuleCondition> conditions) {
this.actions = Objects.requireNonNull(actions);
this.targetFieldName = targetFieldName;
this.targetFieldValue = targetFieldValue;
this.conditionsConnective = Objects.requireNonNull(conditionsConnective);
this.ruleConditions = Collections.unmodifiableList(ruleConditions);
this.conditions = Collections.unmodifiableList(conditions);
}
public DetectionRule(StreamInput in) throws IOException {
ruleAction = RuleAction.readFromStream(in);
int actionsCount = in.readVInt();
actions = EnumSet.noneOf(RuleAction.class);
for (int i = 0; i < actionsCount; ++i) {
actions.add(RuleAction.readFromStream(in));
}
conditionsConnective = Connective.readFromStream(in);
int size = in.readVInt();
ruleConditions = new ArrayList<>(size);
conditions = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
ruleConditions.add(new RuleCondition(in));
conditions.add(new RuleCondition(in));
}
targetFieldName = in.readOptionalString();
targetFieldValue = in.readOptionalString();
@ -99,10 +101,14 @@ public class DetectionRule implements ToXContentObject, Writeable {
@Override
public void writeTo(StreamOutput out) throws IOException {
ruleAction.writeTo(out);
out.writeVInt(actions.size());
for (RuleAction action : actions) {
action.writeTo(out);
}
conditionsConnective.writeTo(out);
out.writeVInt(ruleConditions.size());
for (RuleCondition condition : ruleConditions) {
out.writeVInt(conditions.size());
for (RuleCondition condition : conditions) {
condition.writeTo(out);
}
out.writeOptionalString(targetFieldName);
@ -112,9 +118,9 @@ public class DetectionRule implements ToXContentObject, Writeable {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(RULE_ACTION_FIELD.getPreferredName(), ruleAction);
builder.field(ACTIONS_FIELD.getPreferredName(), actions);
builder.field(CONDITIONS_CONNECTIVE_FIELD.getPreferredName(), conditionsConnective);
builder.field(RULE_CONDITIONS_FIELD.getPreferredName(), ruleConditions);
builder.field(CONDITIONS_FIELD.getPreferredName(), conditions);
if (targetFieldName != null) {
builder.field(TARGET_FIELD_NAME_FIELD.getPreferredName(), targetFieldName);
}
@ -125,8 +131,8 @@ public class DetectionRule implements ToXContentObject, Writeable {
return builder;
}
public RuleAction getRuleAction() {
return ruleAction;
public EnumSet<RuleAction> getActions() {
return actions;
}
@Nullable
@ -143,12 +149,12 @@ public class DetectionRule implements ToXContentObject, Writeable {
return conditionsConnective;
}
public List<RuleCondition> getRuleConditions() {
return ruleConditions;
public List<RuleCondition> getConditions() {
return conditions;
}
public Set<String> extractReferencedFilters() {
return ruleConditions.stream().map(RuleCondition::getValueFilter).filter(Objects::nonNull).collect(Collectors.toSet());
return conditions.stream().map(RuleCondition::getFilterId).filter(Objects::nonNull).collect(Collectors.toSet());
}
@Override
@ -162,34 +168,46 @@ public class DetectionRule implements ToXContentObject, Writeable {
}
DetectionRule other = (DetectionRule) obj;
return Objects.equals(ruleAction, other.ruleAction)
return Objects.equals(actions, other.actions)
&& Objects.equals(targetFieldName, other.targetFieldName)
&& Objects.equals(targetFieldValue, other.targetFieldValue)
&& Objects.equals(conditionsConnective, other.conditionsConnective)
&& Objects.equals(ruleConditions, other.ruleConditions);
&& Objects.equals(conditions, other.conditions);
}
@Override
public int hashCode() {
return Objects.hash(ruleAction, targetFieldName, targetFieldValue, conditionsConnective, ruleConditions);
return Objects.hash(actions, targetFieldName, targetFieldValue, conditionsConnective, conditions);
}
public static class Builder {
private RuleAction ruleAction = RuleAction.FILTER_RESULTS;
private EnumSet<RuleAction> actions = EnumSet.of(RuleAction.FILTER_RESULTS);
private String targetFieldName;
private String targetFieldValue;
private Connective conditionsConnective = Connective.OR;
private List<RuleCondition> ruleConditions = Collections.emptyList();
private List<RuleCondition> conditions = Collections.emptyList();
public Builder(List<RuleCondition> ruleConditions) {
this.ruleConditions = ExceptionsHelper.requireNonNull(ruleConditions, RULE_CONDITIONS_FIELD.getPreferredName());
public Builder(List<RuleCondition> conditions) {
this.conditions = ExceptionsHelper.requireNonNull(conditions, CONDITIONS_FIELD.getPreferredName());
}
private Builder() {
}
public Builder setRuleAction(RuleAction ruleAction) {
this.ruleAction = ExceptionsHelper.requireNonNull(ruleAction, RULE_ACTION_FIELD.getPreferredName());
public Builder setActions(List<String> actions) {
this.actions.clear();
actions.stream().map(RuleAction::fromString).forEach(this.actions::add);
return this;
}
public Builder setActions(EnumSet<RuleAction> actions) {
this.actions = Objects.requireNonNull(actions, ACTIONS_FIELD.getPreferredName());
return this;
}
public Builder setActions(RuleAction... actions) {
this.actions.clear();
Arrays.stream(actions).forEach(this.actions::add);
return this;
}
@ -208,8 +226,8 @@ public class DetectionRule implements ToXContentObject, Writeable {
return this;
}
public Builder setRuleConditions(List<RuleCondition> ruleConditions) {
this.ruleConditions = ExceptionsHelper.requireNonNull(ruleConditions, RULE_ACTION_FIELD.getPreferredName());
public Builder setConditions(List<RuleCondition> conditions) {
this.conditions = ExceptionsHelper.requireNonNull(conditions, CONDITIONS_FIELD.getPreferredName());
return this;
}
@ -218,18 +236,18 @@ public class DetectionRule implements ToXContentObject, Writeable {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_MISSING_TARGET_FIELD_NAME, targetFieldValue);
throw ExceptionsHelper.badRequestException(msg);
}
if (ruleConditions == null || ruleConditions.isEmpty()) {
if (conditions == null || conditions.isEmpty()) {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_REQUIRES_AT_LEAST_ONE_CONDITION);
throw ExceptionsHelper.badRequestException(msg);
}
for (RuleCondition condition : ruleConditions) {
if (condition.getConditionType() == RuleConditionType.CATEGORICAL && targetFieldName != null) {
for (RuleCondition condition : conditions) {
if (condition.getType() == RuleConditionType.CATEGORICAL && targetFieldName != null) {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_CONDITION_CATEGORICAL_INVALID_OPTION,
DetectionRule.TARGET_FIELD_NAME_FIELD.getPreferredName());
throw ExceptionsHelper.badRequestException(msg);
}
}
return new DetectionRule(ruleAction, targetFieldName, targetFieldValue, conditionsConnective, ruleConditions);
return new DetectionRule(actions, targetFieldName, targetFieldValue, conditionsConnective, conditions);
}
}
}

View File

@ -83,7 +83,7 @@ public class Detector implements ToXContentObject, Writeable {
public static final ParseField PARTITION_FIELD_NAME_FIELD = new ParseField("partition_field_name");
public static final ParseField USE_NULL_FIELD = new ParseField("use_null");
public static final ParseField EXCLUDE_FREQUENT_FIELD = new ParseField("exclude_frequent");
public static final ParseField DETECTOR_RULES_FIELD = new ParseField("detector_rules");
public static final ParseField RULES_FIELD = new ParseField("rules");
public static final ParseField DETECTOR_INDEX = new ParseField("detector_index");
// These parsers follow the pattern that metadata is parsed leniently (to allow for enhancements), whilst config is parsed strictly
@ -110,8 +110,8 @@ public class Detector implements ToXContentObject, Writeable {
}
throw new IllegalArgumentException("Unsupported token [" + p.currentToken() + "]");
}, EXCLUDE_FREQUENT_FIELD, ObjectParser.ValueType.STRING);
parser.declareObjectArray(Builder::setDetectorRules, (p, c) ->
DetectionRule.PARSERS.get(parserType).apply(p, c).build(), DETECTOR_RULES_FIELD);
parser.declareObjectArray(Builder::setRules, (p, c) ->
DetectionRule.PARSERS.get(parserType).apply(p, c).build(), RULES_FIELD);
parser.declareInt(Builder::setDetectorIndex, DETECTOR_INDEX);
}
}
@ -329,7 +329,7 @@ public class Detector implements ToXContentObject, Writeable {
private final String partitionFieldName;
private final boolean useNull;
private final ExcludeFrequent excludeFrequent;
private final List<DetectionRule> detectorRules;
private final List<DetectionRule> rules;
private final int detectorIndex;
public Detector(StreamInput in) throws IOException {
@ -341,7 +341,7 @@ public class Detector implements ToXContentObject, Writeable {
partitionFieldName = in.readOptionalString();
useNull = in.readBoolean();
excludeFrequent = in.readBoolean() ? ExcludeFrequent.readFromStream(in) : null;
detectorRules = in.readList(DetectionRule::new);
rules = in.readList(DetectionRule::new);
if (in.getVersion().onOrAfter(Version.V_5_5_0)) {
detectorIndex = in.readInt();
} else {
@ -365,7 +365,7 @@ public class Detector implements ToXContentObject, Writeable {
} else {
out.writeBoolean(false);
}
out.writeList(detectorRules);
out.writeList(rules);
if (out.getVersion().onOrAfter(Version.V_5_5_0)) {
out.writeInt(detectorIndex);
}
@ -394,7 +394,7 @@ public class Detector implements ToXContentObject, Writeable {
if (excludeFrequent != null) {
builder.field(EXCLUDE_FREQUENT_FIELD.getPreferredName(), excludeFrequent);
}
builder.field(DETECTOR_RULES_FIELD.getPreferredName(), detectorRules);
builder.field(RULES_FIELD.getPreferredName(), rules);
// negative means "unknown", which should only happen for a 5.4 job
if (detectorIndex >= 0
// no point writing this to cluster state, as the indexes will get reassigned on reload anyway
@ -406,7 +406,7 @@ public class Detector implements ToXContentObject, Writeable {
}
private Detector(String detectorDescription, String function, String fieldName, String byFieldName, String overFieldName,
String partitionFieldName, boolean useNull, ExcludeFrequent excludeFrequent, List<DetectionRule> detectorRules,
String partitionFieldName, boolean useNull, ExcludeFrequent excludeFrequent, List<DetectionRule> rules,
int detectorIndex) {
this.function = function;
this.fieldName = fieldName;
@ -415,7 +415,7 @@ public class Detector implements ToXContentObject, Writeable {
this.partitionFieldName = partitionFieldName;
this.useNull = useNull;
this.excludeFrequent = excludeFrequent;
this.detectorRules = Collections.unmodifiableList(detectorRules);
this.rules = Collections.unmodifiableList(rules);
this.detectorDescription = detectorDescription != null ? detectorDescription : DefaultDetectorDescription.of(this);
this.detectorIndex = detectorIndex;
}
@ -491,8 +491,8 @@ public class Detector implements ToXContentObject, Writeable {
return excludeFrequent;
}
public List<DetectionRule> getDetectorRules() {
return detectorRules;
public List<DetectionRule> getRules() {
return rules;
}
/**
@ -514,8 +514,8 @@ public class Detector implements ToXContentObject, Writeable {
}
public Set<String> extractReferencedFilters() {
return detectorRules == null ? Collections.emptySet()
: detectorRules.stream().map(DetectionRule::extractReferencedFilters)
return rules == null ? Collections.emptySet()
: rules.stream().map(DetectionRule::extractReferencedFilters)
.flatMap(Set::stream).collect(Collectors.toSet());
}
@ -556,15 +556,14 @@ public class Detector implements ToXContentObject, Writeable {
Objects.equals(this.partitionFieldName, that.partitionFieldName) &&
Objects.equals(this.useNull, that.useNull) &&
Objects.equals(this.excludeFrequent, that.excludeFrequent) &&
Objects.equals(this.detectorRules, that.detectorRules) &&
Objects.equals(this.rules, that.rules) &&
this.detectorIndex == that.detectorIndex;
}
@Override
public int hashCode() {
return Objects.hash(detectorDescription, function, fieldName, byFieldName,
overFieldName, partitionFieldName, useNull, excludeFrequent,
detectorRules, detectorIndex);
return Objects.hash(detectorDescription, function, fieldName, byFieldName, overFieldName, partitionFieldName, useNull,
excludeFrequent, rules, detectorIndex);
}
public static class Builder {
@ -587,7 +586,7 @@ public class Detector implements ToXContentObject, Writeable {
private String partitionFieldName;
private boolean useNull = false;
private ExcludeFrequent excludeFrequent;
private List<DetectionRule> detectorRules = Collections.emptyList();
private List<DetectionRule> rules = Collections.emptyList();
// negative means unknown, and is expected for v5.4 jobs
private int detectorIndex = -1;
@ -603,8 +602,7 @@ public class Detector implements ToXContentObject, Writeable {
partitionFieldName = detector.partitionFieldName;
useNull = detector.useNull;
excludeFrequent = detector.excludeFrequent;
detectorRules = new ArrayList<>(detector.detectorRules.size());
detectorRules.addAll(detector.getDetectorRules());
rules = new ArrayList<>(detector.getRules());
detectorIndex = detector.detectorIndex;
}
@ -645,8 +643,8 @@ public class Detector implements ToXContentObject, Writeable {
this.excludeFrequent = excludeFrequent;
}
public void setDetectorRules(List<DetectionRule> detectorRules) {
this.detectorRules = detectorRules;
public void setRules(List<DetectionRule> rules) {
this.rules = rules;
}
public void setDetectorIndex(int detectorIndex) {
@ -704,12 +702,12 @@ public class Detector implements ToXContentObject, Writeable {
}
String function = this.function == null ? Detector.METRIC : this.function;
if (detectorRules.isEmpty() == false) {
if (rules.isEmpty() == false) {
if (FUNCTIONS_WITHOUT_RULE_SUPPORT.contains(function)) {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_NOT_SUPPORTED_BY_FUNCTION, function);
throw ExceptionsHelper.badRequestException(msg);
}
for (DetectionRule rule : detectorRules) {
for (DetectionRule rule : rules) {
checkScoping(rule);
}
}
@ -764,7 +762,7 @@ public class Detector implements ToXContentObject, Writeable {
}
return new Detector(detectorDescription, function, fieldName, byFieldName, overFieldName, partitionFieldName,
useNull, excludeFrequent, detectorRules, detectorIndex);
useNull, excludeFrequent, rules, detectorIndex);
}
public List<String> extractAnalysisFields() {
@ -802,7 +800,7 @@ public class Detector implements ToXContentObject, Writeable {
String targetFieldName = rule.getTargetFieldName();
checkTargetFieldNameIsValid(extractAnalysisFields(), targetFieldName);
List<String> validOptions = getValidFieldNameOptions(rule);
for (RuleCondition condition : rule.getRuleConditions()) {
for (RuleCondition condition : rule.getConditions()) {
if (!validOptions.contains(condition.getFieldName())) {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_CONDITION_INVALID_FIELD_NAME, validOptions,
condition.getFieldName());

View File

@ -315,7 +315,7 @@ public class JobUpdate implements Writeable, ToXContentObject {
detectorbuilder.setDetectorDescription(dd.getDescription());
}
if (dd.getRules() != null) {
detectorbuilder.setDetectorRules(dd.getRules());
detectorbuilder.setRules(dd.getRules());
}
ac.getDetectors().set(dd.getDetectorIndex(), detectorbuilder.build());
}
@ -435,13 +435,11 @@ public class JobUpdate implements Writeable, ToXContentObject {
new ConstructingObjectParser<>("detector_update", a -> new DetectorUpdate((int) a[0], (String) a[1],
(List<DetectionRule>) a[2]));
public static final ParseField RULES = new ParseField("rules");
static {
PARSER.declareInt(ConstructingObjectParser.optionalConstructorArg(), Detector.DETECTOR_INDEX);
PARSER.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), Job.DESCRIPTION);
PARSER.declareObjectArray(ConstructingObjectParser.optionalConstructorArg(),
(parser, parseFieldMatcher) -> DetectionRule.CONFIG_PARSER.apply(parser, parseFieldMatcher).build(), RULES);
PARSER.declareObjectArray(ConstructingObjectParser.optionalConstructorArg(), (parser, parseFieldMatcher) ->
DetectionRule.CONFIG_PARSER.apply(parser, parseFieldMatcher).build(), Detector.RULES_FIELD);
}
private int detectorIndex;
@ -495,7 +493,7 @@ public class JobUpdate implements Writeable, ToXContentObject {
builder.field(Job.DESCRIPTION.getPreferredName(), description);
}
if (rules != null) {
builder.field(RULES.getPreferredName(), rules);
builder.field(Detector.RULES_FIELD.getPreferredName(), rules);
}
builder.endObject();

View File

@ -14,8 +14,7 @@ import java.util.Locale;
public enum RuleAction implements Writeable {
FILTER_RESULTS,
SKIP_SAMPLING,
SKIP_SAMPLING_AND_FILTER_RESULTS;
SKIP_SAMPLING;
/**
* Case-insensitive from string method.

View File

@ -26,11 +26,10 @@ import java.util.Map;
import java.util.Objects;
public class RuleCondition implements ToXContentObject, Writeable {
public static final ParseField CONDITION_TYPE_FIELD = new ParseField("condition_type");
public static final ParseField TYPE_FIELD = new ParseField("type");
public static final ParseField RULE_CONDITION_FIELD = new ParseField("rule_condition");
public static final ParseField FIELD_NAME_FIELD = new ParseField("field_name");
public static final ParseField FIELD_VALUE_FIELD = new ParseField("field_value");
public static final ParseField VALUE_FILTER_FIELD = new ParseField("value_filter");
// These parsers follow the pattern that metadata is parsed leniently (to allow for enhancements), whilst config is parsed strictly
public static final ConstructingObjectParser<RuleCondition, Void> METADATA_PARSER =
@ -53,60 +52,60 @@ public class RuleCondition implements ToXContentObject, Writeable {
return RuleConditionType.fromString(p.text());
}
throw new IllegalArgumentException("Unsupported token [" + p.currentToken() + "]");
}, CONDITION_TYPE_FIELD, ValueType.STRING);
}, TYPE_FIELD, ValueType.STRING);
parser.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), FIELD_NAME_FIELD);
parser.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), FIELD_VALUE_FIELD);
parser.declareObject(ConstructingObjectParser.optionalConstructorArg(), Condition.PARSER, Condition.CONDITION_FIELD);
parser.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), VALUE_FILTER_FIELD);
parser.declareStringOrNull(ConstructingObjectParser.optionalConstructorArg(), MlFilter.ID);
}
}
private final RuleConditionType conditionType;
private final RuleConditionType type;
private final String fieldName;
private final String fieldValue;
private final Condition condition;
private final String valueFilter;
private final String filterId;
public RuleCondition(StreamInput in) throws IOException {
conditionType = RuleConditionType.readFromStream(in);
type = RuleConditionType.readFromStream(in);
condition = in.readOptionalWriteable(Condition::new);
fieldName = in.readOptionalString();
fieldValue = in.readOptionalString();
valueFilter = in.readOptionalString();
filterId = in.readOptionalString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
conditionType.writeTo(out);
type.writeTo(out);
out.writeOptionalWriteable(condition);
out.writeOptionalString(fieldName);
out.writeOptionalString(fieldValue);
out.writeOptionalString(valueFilter);
out.writeOptionalString(filterId);
}
RuleCondition(RuleConditionType conditionType, String fieldName, String fieldValue, Condition condition, String valueFilter) {
this.conditionType = conditionType;
RuleCondition(RuleConditionType type, String fieldName, String fieldValue, Condition condition, String filterId) {
this.type = type;
this.fieldName = fieldName;
this.fieldValue = fieldValue;
this.condition = condition;
this.valueFilter = valueFilter;
this.filterId = filterId;
verifyFieldsBoundToType(this);
verifyFieldValueRequiresFieldName(this);
}
public RuleCondition(RuleCondition ruleCondition) {
this.conditionType = ruleCondition.conditionType;
this.type = ruleCondition.type;
this.fieldName = ruleCondition.fieldName;
this.fieldValue = ruleCondition.fieldValue;
this.condition = ruleCondition.condition;
this.valueFilter = ruleCondition.valueFilter;
this.filterId = ruleCondition.filterId;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(CONDITION_TYPE_FIELD.getPreferredName(), conditionType);
builder.field(TYPE_FIELD.getPreferredName(), type);
if (condition != null) {
builder.field(Condition.CONDITION_FIELD.getPreferredName(), condition);
}
@ -116,15 +115,15 @@ public class RuleCondition implements ToXContentObject, Writeable {
if (fieldValue != null) {
builder.field(FIELD_VALUE_FIELD.getPreferredName(), fieldValue);
}
if (valueFilter != null) {
builder.field(VALUE_FILTER_FIELD.getPreferredName(), valueFilter);
if (filterId != null) {
builder.field(MlFilter.ID.getPreferredName(), filterId);
}
builder.endObject();
return builder;
}
public RuleConditionType getConditionType() {
return conditionType;
public RuleConditionType getType() {
return type;
}
/**
@ -153,8 +152,8 @@ public class RuleCondition implements ToXContentObject, Writeable {
* The unique identifier of a filter. Required when the rule type is
* categorical. Should be null for all other types.
*/
public String getValueFilter() {
return valueFilter;
public String getFilterId() {
return filterId;
}
@Override
@ -168,14 +167,14 @@ public class RuleCondition implements ToXContentObject, Writeable {
}
RuleCondition other = (RuleCondition) obj;
return Objects.equals(conditionType, other.conditionType) && Objects.equals(fieldName, other.fieldName)
return Objects.equals(type, other.type) && Objects.equals(fieldName, other.fieldName)
&& Objects.equals(fieldValue, other.fieldValue) && Objects.equals(condition, other.condition)
&& Objects.equals(valueFilter, other.valueFilter);
&& Objects.equals(filterId, other.filterId);
}
@Override
public int hashCode() {
return Objects.hash(conditionType, fieldName, fieldValue, condition, valueFilter);
return Objects.hash(type, fieldName, fieldValue, condition, filterId);
}
public static RuleCondition createCategorical(String fieldName, String valueFilter) {
@ -195,7 +194,7 @@ public class RuleCondition implements ToXContentObject, Writeable {
}
private static void verifyFieldsBoundToType(RuleCondition ruleCondition) throws ElasticsearchParseException {
switch (ruleCondition.getConditionType()) {
switch (ruleCondition.getType()) {
case CATEGORICAL:
verifyCategorical(ruleCondition);
break;
@ -215,7 +214,7 @@ public class RuleCondition implements ToXContentObject, Writeable {
private static void verifyCategorical(RuleCondition ruleCondition) throws ElasticsearchParseException {
checkCategoricalHasNoField(Condition.CONDITION_FIELD.getPreferredName(), ruleCondition.getCondition());
checkCategoricalHasNoField(RuleCondition.FIELD_VALUE_FIELD.getPreferredName(), ruleCondition.getFieldValue());
checkCategoricalHasField(RuleCondition.VALUE_FILTER_FIELD.getPreferredName(), ruleCondition.getValueFilter());
checkCategoricalHasField(MlFilter.ID.getPreferredName(), ruleCondition.getFilterId());
}
private static void checkCategoricalHasNoField(String fieldName, Object fieldValue) throws ElasticsearchParseException {
@ -233,7 +232,7 @@ public class RuleCondition implements ToXContentObject, Writeable {
}
private static void verifyNumerical(RuleCondition ruleCondition) throws ElasticsearchParseException {
checkNumericalHasNoField(RuleCondition.VALUE_FILTER_FIELD.getPreferredName(), ruleCondition.getValueFilter());
checkNumericalHasNoField(MlFilter.ID.getPreferredName(), ruleCondition.getFilterId());
checkNumericalHasField(Condition.CONDITION_FIELD.getPreferredName(), ruleCondition.getCondition());
if (ruleCondition.getFieldName() != null && ruleCondition.getFieldValue() == null) {
String msg = Messages.getMessage(Messages.JOB_CONFIG_DETECTION_RULE_CONDITION_NUMERICAL_WITH_FIELD_NAME_REQUIRES_FIELD_VALUE);

View File

@ -107,8 +107,8 @@ public class FieldConfigWriter {
StringBuilder contents) throws IOException {
List<DetectionRule> rules = new ArrayList<>();
if (detector.getDetectorRules() != null) {
rules.addAll(detector.getDetectorRules());
if (detector.getRules() != null) {
rules.addAll(detector.getRules());
}
rules.addAll(specialEvents);

View File

@ -22,6 +22,7 @@ import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
public class SpecialEventTests extends AbstractSerializingTestCase<SpecialEvent> {
@ -60,14 +61,14 @@ public class SpecialEventTests extends AbstractSerializingTestCase<SpecialEvent>
DetectionRule rule = event.toDetectionRule(TimeValue.timeValueSeconds(bucketSpanSecs));
assertEquals(Connective.AND, rule.getConditionsConnective());
assertEquals(RuleAction.SKIP_SAMPLING_AND_FILTER_RESULTS, rule.getRuleAction());
assertEquals(rule.getActions(), EnumSet.of(RuleAction.FILTER_RESULTS, RuleAction.SKIP_SAMPLING));
assertNull(rule.getTargetFieldName());
assertNull(rule.getTargetFieldValue());
List<RuleCondition> conditions = rule.getRuleConditions();
List<RuleCondition> conditions = rule.getConditions();
assertEquals(2, conditions.size());
assertEquals(RuleConditionType.TIME, conditions.get(0).getConditionType());
assertEquals(RuleConditionType.TIME, conditions.get(1).getConditionType());
assertEquals(RuleConditionType.TIME, conditions.get(0).getType());
assertEquals(RuleConditionType.TIME, conditions.get(1).getType());
assertEquals(Operator.GTE, conditions.get(0).getCondition().getOperator());
assertEquals(Operator.LT, conditions.get(1).getCondition().getOperator());

View File

@ -61,7 +61,7 @@ public class DetectionRulesIT extends MlNativeAutodetectIntegTestCase {
DetectionRule rule = new DetectionRule.Builder(Arrays.asList(condition1, condition2, condition3)).build();
Detector.Builder detector = new Detector.Builder("max", "value");
detector.setDetectorRules(Arrays.asList(rule));
detector.setRules(Arrays.asList(rule));
detector.setByFieldName("by_field");
AnalysisConfig.Builder analysisConfig = new AnalysisConfig.Builder(

View File

@ -431,10 +431,10 @@ public class JobProviderIT extends XPackSingleNodeTestCase {
}
DetectionRule.Builder rule = new DetectionRule.Builder(conditions)
.setRuleAction(RuleAction.FILTER_RESULTS)
.setActions(RuleAction.FILTER_RESULTS)
.setConditionsConnective(Connective.OR);
detector.setDetectorRules(Collections.singletonList(rule.build()));
detector.setRules(Collections.singletonList(rule.build()));
}
return new AnalysisConfig.Builder(Collections.singletonList(detector.build()));

View File

@ -461,9 +461,9 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
"filter2"))).build();
Detector.Builder detector1 = new Detector.Builder("count", null);
detector1.setByFieldName("foo");
detector1.setDetectorRules(Collections.singletonList(rule1));
detector1.setRules(Collections.singletonList(rule1));
Detector.Builder detector2 = new Detector.Builder("count", null);
detector2.setDetectorRules(Collections.singletonList(rule2));
detector2.setRules(Collections.singletonList(rule2));
detector2.setByFieldName("foo");
AnalysisConfig config = new AnalysisConfig.Builder(
Arrays.asList(detector1.build(), detector2.build(), new Detector.Builder("count", null).build())).build();

View File

@ -13,6 +13,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
@ -63,7 +64,7 @@ public class DetectionRuleTests extends AbstractSerializingTestCase<DetectionRul
public void testEqualsGivenRules() {
DetectionRule rule1 = createFullyPopulated().build();
DetectionRule rule2 = createFullyPopulated().setRuleConditions(createRule("10")).build();
DetectionRule rule2 = createFullyPopulated().setConditions(createRule("10")).build();
assertFalse(rule1.equals(rule2));
assertFalse(rule2.equals(rule1));
}
@ -78,7 +79,7 @@ public class DetectionRuleTests extends AbstractSerializingTestCase<DetectionRul
private static DetectionRule.Builder createFullyPopulated() {
return new DetectionRule.Builder(createRule("5"))
.setRuleAction(RuleAction.FILTER_RESULTS)
.setActions(EnumSet.of(RuleAction.FILTER_RESULTS, RuleAction.SKIP_SAMPLING))
.setTargetFieldName("targetField")
.setTargetFieldValue("targetValue")
.setConditionsConnective(Connective.AND);
@ -91,26 +92,33 @@ public class DetectionRuleTests extends AbstractSerializingTestCase<DetectionRul
@Override
protected DetectionRule createTestInstance() {
RuleAction ruleAction = randomFrom(RuleAction.values());
String targetFieldName = null;
String targetFieldValue = null;
Connective connective = randomFrom(Connective.values());
if (randomBoolean()) {
targetFieldName = randomAlphaOfLengthBetween(1, 20);
targetFieldValue = randomAlphaOfLengthBetween(1, 20);
}
int size = 1 + randomInt(20);
List<RuleCondition> ruleConditions = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
// no need for random condition (it is already tested)
ruleConditions.addAll(createRule(Double.toString(randomDouble())));
}
return new DetectionRule.Builder(ruleConditions)
.setRuleAction(ruleAction)
.setTargetFieldName(targetFieldName)
.setTargetFieldValue(targetFieldValue)
.setConditionsConnective(connective)
.build();
DetectionRule.Builder builder = new DetectionRule.Builder(ruleConditions);
if (randomBoolean()) {
EnumSet<RuleAction> actions = EnumSet.noneOf(RuleAction.class);
int actionsCount = randomIntBetween(1, RuleAction.values().length);
for (int i = 0; i < actionsCount; ++i) {
actions.add(randomFrom(RuleAction.values()));
}
builder.setActions(actions);
}
if (randomBoolean()) {
builder.setConditionsConnective(randomFrom(Connective.values()));
}
if (randomBoolean()) {
builder.setTargetFieldName(randomAlphaOfLengthBetween(1, 20));
builder.setTargetFieldValue(randomAlphaOfLengthBetween(1, 20));
}
return builder.build();
}
@Override
@ -125,16 +133,16 @@ public class DetectionRuleTests extends AbstractSerializingTestCase<DetectionRul
@Override
protected DetectionRule mutateInstance(DetectionRule instance) throws IOException {
List<RuleCondition> ruleConditions = instance.getRuleConditions();
RuleAction ruleAction = instance.getRuleAction();
List<RuleCondition> conditions = instance.getConditions();
EnumSet<RuleAction> actions = instance.getActions();
String targetFieldName = instance.getTargetFieldName();
String targetFieldValue = instance.getTargetFieldValue();
Connective connective = instance.getConditionsConnective();
switch (between(0, 3)) {
case 0:
ruleConditions = new ArrayList<>(ruleConditions);
ruleConditions.addAll(createRule(Double.toString(randomDouble())));
conditions = new ArrayList<>(conditions);
conditions.addAll(createRule(Double.toString(randomDouble())));
break;
case 1:
targetFieldName = randomAlphaOfLengthBetween(5, 10);
@ -156,7 +164,7 @@ public class DetectionRuleTests extends AbstractSerializingTestCase<DetectionRul
throw new AssertionError("Illegal randomisation branch");
}
return new DetectionRule.Builder(ruleConditions).setRuleAction(ruleAction).setTargetFieldName(targetFieldName)
return new DetectionRule.Builder(conditions).setActions(actions).setTargetFieldName(targetFieldName)
.setTargetFieldValue(targetFieldValue).setConditionsConnective(connective).build();
}
}

View File

@ -64,11 +64,11 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
Condition condition = new Condition(Operator.GT, "5");
DetectionRule rule = new DetectionRule.Builder(
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "by2", "val", condition, null)))
.setRuleAction(RuleAction.FILTER_RESULTS).setTargetFieldName("over_field")
.setActions(RuleAction.FILTER_RESULTS).setTargetFieldName("over_field")
.setTargetFieldValue("targetValue")
.setConditionsConnective(Connective.AND)
.build();
builder.setDetectorRules(Collections.singletonList(rule));
builder.setRules(Collections.singletonList(rule));
detector2 = builder.build();
assertFalse(detector1.equals(detector2));
}
@ -84,22 +84,22 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
Condition condition = new Condition(Operator.GT, "5");
DetectionRule rule = new DetectionRule.Builder(
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, condition, null)))
.setRuleAction(RuleAction.FILTER_RESULTS)
.setActions(RuleAction.FILTER_RESULTS)
.setTargetFieldName("over_field")
.setTargetFieldValue("targetValue")
.setConditionsConnective(Connective.AND)
.build();
builder.setDetectorRules(Collections.singletonList(rule));
builder.setRules(Collections.singletonList(rule));
builder.setByFieldName(null);
detector = builder.build();
assertEquals(Collections.singletonList("over_field"), detector.extractAnalysisFields());
builder = new Detector.Builder(detector);
rule = new DetectionRule.Builder(
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, condition, null)))
.setRuleAction(RuleAction.FILTER_RESULTS)
.setActions(RuleAction.FILTER_RESULTS)
.setConditionsConnective(Connective.AND)
.build();
builder.setDetectorRules(Collections.singletonList(rule));
builder.setRules(Collections.singletonList(rule));
builder.setOverFieldName(null);
detector = builder.build();
assertTrue(detector.extractAnalysisFields().isEmpty());
@ -107,7 +107,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
public void testExtractReferencedLists() {
Detector.Builder builder = createDetector();
builder.setDetectorRules(Arrays.asList(
builder.setRules(Arrays.asList(
new DetectionRule.Builder(Collections.singletonList(RuleCondition.createCategorical("by_field", "list1"))).build(),
new DetectionRule.Builder(Collections.singletonList(RuleCondition.createCategorical("by_field", "list2"))).build()));
@ -140,12 +140,12 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
Condition condition = new Condition(Operator.GT, "5");
DetectionRule rule = new DetectionRule.Builder(
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "by_field", "val", condition, null)))
.setRuleAction(RuleAction.FILTER_RESULTS)
.setActions(RuleAction.FILTER_RESULTS)
.setTargetFieldName("over_field")
.setTargetFieldValue("targetValue")
.setConditionsConnective(Connective.AND)
.build();
detector.setDetectorRules(Collections.singletonList(rule));
detector.setRules(Collections.singletonList(rule));
return detector;
}
@ -176,15 +176,15 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
}
if (randomBoolean()) {
int size = randomInt(10);
List<DetectionRule> detectorRules = new ArrayList<>(size);
List<DetectionRule> rules = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
// no need for random DetectionRule (it is already tested)
Condition condition = new Condition(Operator.GT, "5");
detectorRules.add(new DetectionRule.Builder(
rules.add(new DetectionRule.Builder(
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, condition, null)))
.setTargetFieldName(fieldName).build());
}
detector.setDetectorRules(detectorRules);
detector.setRules(rules);
}
if (randomBoolean()) {
detector.setUseNull(randomBoolean());
@ -508,14 +508,14 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
}
}
public void testVerify_GivenInvalidDetectionRuleTargetFieldName() {
public void testVerify_GivenInvalidRuleTargetFieldName() {
Detector.Builder detector = new Detector.Builder("mean", "metricVale");
detector.setByFieldName("metricName");
detector.setPartitionFieldName("instance");
RuleCondition ruleCondition =
new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "metricName", "metricVale", new Condition(Operator.LT, "5"), null);
DetectionRule rule = new DetectionRule.Builder(Collections.singletonList(ruleCondition)).setTargetFieldName("instancE").build();
detector.setDetectorRules(Collections.singletonList(rule));
detector.setRules(Collections.singletonList(rule));
ElasticsearchException e = ESTestCase.expectThrows(ElasticsearchException.class, detector::build);
@ -524,14 +524,14 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
e.getMessage());
}
public void testVerify_GivenValidDetectionRule() {
public void testVerify_GivenValidRule() {
Detector.Builder detector = new Detector.Builder("mean", "metricVale");
detector.setByFieldName("metricName");
detector.setPartitionFieldName("instance");
RuleCondition ruleCondition =
new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "metricName", "CPU", new Condition(Operator.LT, "5"), null);
DetectionRule rule = new DetectionRule.Builder(Collections.singletonList(ruleCondition)).setTargetFieldName("instance").build();
detector.setDetectorRules(Collections.singletonList(rule));
detector.setRules(Collections.singletonList(rule));
detector.build();
}

View File

@ -165,7 +165,7 @@ public class JobUpdateTests extends AbstractSerializingTestCase<JobUpdate> {
updatedJob.getAnalysisConfig().getDetectors().get(detectorUpdate.getDetectorIndex()).getDetectorDescription());
assertNotNull(updatedJob.getAnalysisConfig().getDetectors().get(detectorUpdate.getDetectorIndex()).getDetectorDescription());
assertEquals(detectorUpdate.getRules(),
updatedJob.getAnalysisConfig().getDetectors().get(detectorUpdate.getDetectorIndex()).getDetectorRules());
updatedJob.getAnalysisConfig().getDetectors().get(detectorUpdate.getDetectorIndex()).getRules());
}
}

View File

@ -11,14 +11,12 @@ import org.elasticsearch.test.ESTestCase;
import static org.hamcrest.Matchers.equalTo;
public class
RuleActionTests extends ESTestCase {
public class RuleActionTests extends ESTestCase {
public void testForString() {
assertEquals(RuleAction.FILTER_RESULTS, RuleAction.fromString("filter_results"));
assertEquals(RuleAction.FILTER_RESULTS, RuleAction.fromString("FILTER_RESULTS"));
assertEquals(RuleAction.SKIP_SAMPLING, RuleAction.fromString("SKip_sampLing"));
assertEquals(RuleAction.SKIP_SAMPLING_AND_FILTER_RESULTS, RuleAction.fromString("skip_sampling_and_filter_results"));
}
public void testToString() {
@ -34,9 +32,9 @@ RuleActionTests extends ESTestCase {
}
try (BytesStreamOutput out = new BytesStreamOutput()) {
out.writeVInt(2);
out.writeVInt(1);
try (StreamInput in = out.bytes().streamInput()) {
assertThat(RuleAction.readFromStream(in), equalTo(RuleAction.SKIP_SAMPLING_AND_FILTER_RESULTS));
assertThat(RuleAction.readFromStream(in), equalTo(RuleAction.SKIP_SAMPLING));
}
}
}

View File

@ -52,7 +52,7 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
public void testConstructor() {
RuleCondition condition = new RuleCondition(RuleConditionType.CATEGORICAL, null, null, null, "valueFilter");
assertEquals(RuleConditionType.CATEGORICAL, condition.getConditionType());
assertEquals(RuleConditionType.CATEGORICAL, condition.getType());
assertNull(condition.getFieldName());
assertNull(condition.getFieldValue());
assertNull(condition.getCondition());
@ -122,16 +122,16 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
assertEquals("Invalid detector rule: a categorical rule_condition does not support field_value", e.getMessage());
}
public void testVerify_GivenCategoricalWithoutValueFilter() {
public void testVerify_GivenCategoricalWithoutFilterId() {
ElasticsearchException e = expectThrows(ElasticsearchException.class,
() -> new RuleCondition(RuleConditionType.CATEGORICAL, null, null, null, null));
assertEquals("Invalid detector rule: a categorical rule_condition requires value_filter to be set", e.getMessage());
assertEquals("Invalid detector rule: a categorical rule_condition requires filter_id to be set", e.getMessage());
}
public void testVerify_GivenNumericalActualWithValueFilter() {
public void testVerify_GivenNumericalActualWithFilterId() {
ElasticsearchException e = expectThrows(ElasticsearchException.class,
() -> new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, null, "myFilter"));
assertEquals("Invalid detector rule: a numerical rule_condition does not support value_filter", e.getMessage());
assertEquals("Invalid detector rule: a numerical rule_condition does not support filter_id", e.getMessage());
}
public void testVerify_GivenNumericalActualWithoutCondition() {
@ -146,10 +146,10 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
assertEquals("Invalid detector rule: a numerical rule_condition with field_name requires that field_value is set", e.getMessage());
}
public void testVerify_GivenNumericalTypicalWithValueFilter() {
public void testVerify_GivenNumericalTypicalWithFilterId() {
ElasticsearchException e = expectThrows(ElasticsearchException.class,
() -> new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, null, "myFilter"));
assertEquals("Invalid detector rule: a numerical rule_condition does not support value_filter", e.getMessage());
assertEquals("Invalid detector rule: a numerical rule_condition does not support filter_id", e.getMessage());
}
public void testVerify_GivenNumericalTypicalWithoutCondition() {
@ -158,10 +158,10 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
assertEquals("Invalid detector rule: a numerical rule_condition requires condition to be set", e.getMessage());
}
public void testVerify_GivenNumericalDiffAbsWithValueFilter() {
public void testVerify_GivenNumericalDiffAbsWithFilterId() {
ElasticsearchException e = expectThrows(ElasticsearchException.class,
() -> new RuleCondition(RuleConditionType.NUMERICAL_DIFF_ABS, null, null, null, "myFilter"));
assertEquals("Invalid detector rule: a numerical rule_condition does not support value_filter", e.getMessage());
assertEquals("Invalid detector rule: a numerical rule_condition does not support filter_id", e.getMessage());
}
public void testVerify_GivenNumericalDiffAbsWithoutCondition() {
@ -220,12 +220,12 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
public void testCreateTimeBased() {
RuleCondition timeBased = RuleCondition.createTime(Operator.GTE, 100L);
assertEquals(RuleConditionType.TIME, timeBased.getConditionType());
assertEquals(RuleConditionType.TIME, timeBased.getType());
assertEquals(Operator.GTE, timeBased.getCondition().getOperator());
assertEquals("100", timeBased.getCondition().getValue());
assertNull(timeBased.getFieldName());
assertNull(timeBased.getFieldValue());
assertNull(timeBased.getValueFilter());
assertNull(timeBased.getFilterId());
}
public void testCreateTimeBased_GivenOperatorMatch() {
@ -237,11 +237,11 @@ public class RuleConditionTests extends AbstractSerializingTestCase<RuleConditio
public void testCreateNumerical() {
RuleCondition ruleCondition = RuleCondition.createNumerical(RuleConditionType.NUMERICAL_ACTUAL, "foo", "bar",
new Condition(Operator.GTE, "100"));
assertEquals(RuleConditionType.NUMERICAL_ACTUAL, ruleCondition.getConditionType());
assertEquals(RuleConditionType.NUMERICAL_ACTUAL, ruleCondition.getType());
assertEquals(Operator.GTE, ruleCondition.getCondition().getOperator());
assertEquals("100", ruleCondition.getCondition().getValue());
assertEquals("foo", ruleCondition.getFieldName());
assertEquals("bar", ruleCondition.getFieldValue());
assertNull(ruleCondition.getValueFilter());
assertNull(ruleCondition.getFilterId());
}
}

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.ml.job.process.autodetect.writer;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.ml.calendars.SpecialEvent;
import org.elasticsearch.xpack.ml.job.config.Condition;
import org.elasticsearch.xpack.ml.job.config.Connective;
import org.elasticsearch.xpack.ml.job.config.DetectionRule;
@ -22,13 +21,8 @@ import org.mockito.InOrder;
import org.mockito.Mockito;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
@ -202,11 +196,11 @@ public class ControlMsgToProcessWriterTests extends ESTestCase {
inOrder.verify(lengthEncodedWriter).writeNumFields(4);
inOrder.verify(lengthEncodedWriter, times(3)).writeField("");
inOrder.verify(lengthEncodedWriter).writeField("u[detectorRules]\ndetectorIndex=2\n" +
"rulesJson=[{\"rule_action\":\"filter_results\",\"conditions_connective\":\"and\",\"rule_conditions\":" +
"[{\"condition_type\":\"numerical_actual\",\"condition\":{\"operator\":\"gt\",\"value\":\"5\"}}]," +
"rulesJson=[{\"actions\":[\"filter_results\"],\"conditions_connective\":\"and\",\"conditions\":" +
"[{\"type\":\"numerical_actual\",\"condition\":{\"operator\":\"gt\",\"value\":\"5\"}}]," +
"\"target_field_name\":\"targetField1\",\"target_field_value\":\"targetValue\"}," +
"{\"rule_action\":\"filter_results\",\"conditions_connective\":\"and\",\"rule_conditions\":[" +
"{\"condition_type\":\"numerical_actual\",\"condition\":{\"operator\":\"gt\",\"value\":\"5\"}}]," +
"{\"actions\":[\"filter_results\"],\"conditions_connective\":\"and\",\"conditions\":[" +
"{\"type\":\"numerical_actual\",\"condition\":{\"operator\":\"gt\",\"value\":\"5\"}}]," +
"\"target_field_name\":\"targetField2\",\"target_field_value\":\"targetValue\"}]");
verifyNoMoreInteractions(lengthEncodedWriter);
}

View File

@ -26,7 +26,6 @@ import org.mockito.ArgumentCaptor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
@ -36,7 +35,6 @@ import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@ -195,7 +193,7 @@ public class FieldConfigWriterTests extends ESTestCase {
RuleCondition ruleCondition = RuleCondition.createNumerical
(RuleConditionType.NUMERICAL_ACTUAL, "metricName", "metricValue", new Condition(Operator.LT, "5"));
DetectionRule rule = new DetectionRule.Builder(Arrays.asList(ruleCondition)).setTargetFieldName("instance").build();
detector.setDetectorRules(Arrays.asList(rule));
detector.setRules(Arrays.asList(rule));
AnalysisConfig.Builder builder = new AnalysisConfig.Builder(Arrays.asList(detector.build()));
analysisConfig = builder.build();
@ -251,12 +249,12 @@ public class FieldConfigWriterTests extends ESTestCase {
createFieldConfigWriter().write();
verify(writer).write("detector.0.clause = count\n" +
"detector.0.rules = [{\"rule_action\":\"skip_sampling_and_filter_results\",\"conditions_connective\":\"and\"," +
"\"rule_conditions\":[{\"condition_type\":\"time\",\"condition\":{\"operator\":\"gte\",\"value\":\"1511395200\"}}," +
"{\"condition_type\":\"time\",\"condition\":{\"operator\":\"lt\",\"value\":\"1515369600\"}}]}," +
"{\"rule_action\":\"skip_sampling_and_filter_results\",\"conditions_connective\":\"and\"," +
"\"rule_conditions\":[{\"condition_type\":\"time\",\"condition\":{\"operator\":\"gte\",\"value\":\"1519603200\"}}," +
"{\"condition_type\":\"time\",\"condition\":{\"operator\":\"lt\",\"value\":\"1519862400\"}}]}]" +
"detector.0.rules = [{\"actions\":[\"filter_results\",\"skip_sampling\"],\"conditions_connective\":\"and\"," +
"\"conditions\":[{\"type\":\"time\",\"condition\":{\"operator\":\"gte\",\"value\":\"1511395200\"}}," +
"{\"type\":\"time\",\"condition\":{\"operator\":\"lt\",\"value\":\"1515369600\"}}]}," +
"{\"actions\":[\"filter_results\",\"skip_sampling\"],\"conditions_connective\":\"and\"," +
"\"conditions\":[{\"type\":\"time\",\"condition\":{\"operator\":\"gte\",\"value\":\"1519603200\"}}," +
"{\"type\":\"time\",\"condition\":{\"operator\":\"lt\",\"value\":\"1519862400\"}}]}]" +
"\n");
verifyNoMoreInteractions(writer);

View File

@ -152,12 +152,12 @@ setup:
"analysis_config" : {
"bucket_span": "3600s",
"detectors" :[{"function":"mean","field_name":"airline",
"detector_rules": [
"rules": [
{
"rule_conditions": [
"conditions": [
{
"condition_type": "categorical",
"value_filter": "filter-foo"
"type": "categorical",
"filter_id": "filter-foo"
}
]
}

View File

@ -301,7 +301,7 @@
"groups": ["group-1", "group-2"],
"description":"Post update description",
"detectors": [{"detector_index": 0, "rules": {"target_field_name": "airline",
"rule_conditions": [ { "condition_type": "numerical_actual",
"conditions": [ { "type": "numerical_actual",
"condition": {"operator": "gt", "value": "10" } } ] } },
{"detector_index": 1, "description": "updated description"}],
"model_plot_config": {
@ -327,7 +327,7 @@
- match: { model_plot_config.terms: "foobar" }
- match: { analysis_limits.model_memory_limit: "20mb" }
- match: { analysis_config.categorization_filters: ["cat3.*"] }
- match: { analysis_config.detectors.0.detector_rules.0.target_field_name: "airline" }
- match: { analysis_config.detectors.0.rules.0.target_field_name: "airline" }
- match: { analysis_config.detectors.0.detector_index: 0 }
- match: { analysis_config.detectors.1.detector_description: "updated description" }
- match: { analysis_config.detectors.1.detector_index: 1 }