Skip to content

Commit

Permalink
[ML] Add ML result classes to protocol library (#32587)
Browse files Browse the repository at this point in the history
This commit adds the ML results classes to the X-Pack protocol
library used by the high level REST client.

(Other commits will add the config classes and stats classes.)

These classes:

- Are publically immutable
- Are privately mutable - this is perhaps not as nice as the
  config classes, but to do otherwise would require adding
  builders and the corresponding server-side classes that the
  old transport client used don't have builders
- Have little/no validation of field values beyond null checks
- Are convertible to and from X-Content, but NOT wire transportable
- Have lenient parsers to maximize compatibility across versions
- Have the same class names and getter names as the corresponding
  classes in X-Pack core to ease migration for transport client
  users
- Don't reproduce all the methods that do calculations or
  transformations that the the corresponding classes in X-Pack core
  have
  • Loading branch information
droberts195 committed Aug 3, 2018
1 parent 4ade361 commit eb44fe6
Show file tree
Hide file tree
Showing 17 changed files with 2,752 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.protocol.xpack.ml.job.results;

import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
* Anomaly Cause POJO.
* Used as a nested level inside population anomaly records.
*/
public class AnomalyCause implements ToXContentObject {

public static final ParseField ANOMALY_CAUSE = new ParseField("anomaly_cause");

/**
* Result fields
*/
public static final ParseField PROBABILITY = new ParseField("probability");
public static final ParseField OVER_FIELD_NAME = new ParseField("over_field_name");
public static final ParseField OVER_FIELD_VALUE = new ParseField("over_field_value");
public static final ParseField BY_FIELD_NAME = new ParseField("by_field_name");
public static final ParseField BY_FIELD_VALUE = new ParseField("by_field_value");
public static final ParseField CORRELATED_BY_FIELD_VALUE = new ParseField("correlated_by_field_value");
public static final ParseField PARTITION_FIELD_NAME = new ParseField("partition_field_name");
public static final ParseField PARTITION_FIELD_VALUE = new ParseField("partition_field_value");
public static final ParseField FUNCTION = new ParseField("function");
public static final ParseField FUNCTION_DESCRIPTION = new ParseField("function_description");
public static final ParseField TYPICAL = new ParseField("typical");
public static final ParseField ACTUAL = new ParseField("actual");
public static final ParseField INFLUENCERS = new ParseField("influencers");

/**
* Metric Results
*/
public static final ParseField FIELD_NAME = new ParseField("field_name");

public static final ObjectParser<AnomalyCause, Void> PARSER =
new ObjectParser<>(ANOMALY_CAUSE.getPreferredName(), true, AnomalyCause::new);

static {
PARSER.declareDouble(AnomalyCause::setProbability, PROBABILITY);
PARSER.declareString(AnomalyCause::setByFieldName, BY_FIELD_NAME);
PARSER.declareString(AnomalyCause::setByFieldValue, BY_FIELD_VALUE);
PARSER.declareString(AnomalyCause::setCorrelatedByFieldValue, CORRELATED_BY_FIELD_VALUE);
PARSER.declareString(AnomalyCause::setPartitionFieldName, PARTITION_FIELD_NAME);
PARSER.declareString(AnomalyCause::setPartitionFieldValue, PARTITION_FIELD_VALUE);
PARSER.declareString(AnomalyCause::setFunction, FUNCTION);
PARSER.declareString(AnomalyCause::setFunctionDescription, FUNCTION_DESCRIPTION);
PARSER.declareDoubleArray(AnomalyCause::setTypical, TYPICAL);
PARSER.declareDoubleArray(AnomalyCause::setActual, ACTUAL);
PARSER.declareString(AnomalyCause::setFieldName, FIELD_NAME);
PARSER.declareString(AnomalyCause::setOverFieldName, OVER_FIELD_NAME);
PARSER.declareString(AnomalyCause::setOverFieldValue, OVER_FIELD_VALUE);
PARSER.declareObjectArray(AnomalyCause::setInfluencers, Influence.PARSER, INFLUENCERS);
}

private double probability;
private String byFieldName;
private String byFieldValue;
private String correlatedByFieldValue;
private String partitionFieldName;
private String partitionFieldValue;
private String function;
private String functionDescription;
private List<Double> typical;
private List<Double> actual;
private String fieldName;
private String overFieldName;
private String overFieldValue;

private List<Influence> influencers;

AnomalyCause() {
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(PROBABILITY.getPreferredName(), probability);
if (byFieldName != null) {
builder.field(BY_FIELD_NAME.getPreferredName(), byFieldName);
}
if (byFieldValue != null) {
builder.field(BY_FIELD_VALUE.getPreferredName(), byFieldValue);
}
if (correlatedByFieldValue != null) {
builder.field(CORRELATED_BY_FIELD_VALUE.getPreferredName(), correlatedByFieldValue);
}
if (partitionFieldName != null) {
builder.field(PARTITION_FIELD_NAME.getPreferredName(), partitionFieldName);
}
if (partitionFieldValue != null) {
builder.field(PARTITION_FIELD_VALUE.getPreferredName(), partitionFieldValue);
}
if (function != null) {
builder.field(FUNCTION.getPreferredName(), function);
}
if (functionDescription != null) {
builder.field(FUNCTION_DESCRIPTION.getPreferredName(), functionDescription);
}
if (typical != null) {
builder.field(TYPICAL.getPreferredName(), typical);
}
if (actual != null) {
builder.field(ACTUAL.getPreferredName(), actual);
}
if (fieldName != null) {
builder.field(FIELD_NAME.getPreferredName(), fieldName);
}
if (overFieldName != null) {
builder.field(OVER_FIELD_NAME.getPreferredName(), overFieldName);
}
if (overFieldValue != null) {
builder.field(OVER_FIELD_VALUE.getPreferredName(), overFieldValue);
}
if (influencers != null) {
builder.field(INFLUENCERS.getPreferredName(), influencers);
}
builder.endObject();
return builder;
}

public double getProbability() {
return probability;
}

void setProbability(double value) {
probability = value;
}

public String getByFieldName() {
return byFieldName;
}

void setByFieldName(String value) {
byFieldName = value;
}

public String getByFieldValue() {
return byFieldValue;
}

void setByFieldValue(String value) {
byFieldValue = value;
}

public String getCorrelatedByFieldValue() {
return correlatedByFieldValue;
}

void setCorrelatedByFieldValue(String value) {
correlatedByFieldValue = value;
}

public String getPartitionFieldName() {
return partitionFieldName;
}

void setPartitionFieldName(String field) {
partitionFieldName = field;
}

public String getPartitionFieldValue() {
return partitionFieldValue;
}

void setPartitionFieldValue(String value) {
partitionFieldValue = value;
}

public String getFunction() {
return function;
}

void setFunction(String name) {
function = name;
}

public String getFunctionDescription() {
return functionDescription;
}

void setFunctionDescription(String functionDescription) {
this.functionDescription = functionDescription;
}

public List<Double> getTypical() {
return typical;
}

void setTypical(List<Double> typical) {
this.typical = Collections.unmodifiableList(typical);
}

public List<Double> getActual() {
return actual;
}

void setActual(List<Double> actual) {
this.actual = Collections.unmodifiableList(actual);
}

public String getFieldName() {
return fieldName;
}

void setFieldName(String field) {
fieldName = field;
}

public String getOverFieldName() {
return overFieldName;
}

void setOverFieldName(String name) {
overFieldName = name;
}

public String getOverFieldValue() {
return overFieldValue;
}

void setOverFieldValue(String value) {
overFieldValue = value;
}

public List<Influence> getInfluencers() {
return influencers;
}

void setInfluencers(List<Influence> influencers) {
this.influencers = Collections.unmodifiableList(influencers);
}

@Override
public int hashCode() {
return Objects.hash(probability, actual, typical, byFieldName, byFieldValue, correlatedByFieldValue, fieldName, function,
functionDescription, overFieldName, overFieldValue, partitionFieldName, partitionFieldValue, influencers);
}

@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}

if (other == null || getClass() != other.getClass()) {
return false;
}

AnomalyCause that = (AnomalyCause)other;

return this.probability == that.probability &&
Objects.equals(this.typical, that.typical) &&
Objects.equals(this.actual, that.actual) &&
Objects.equals(this.function, that.function) &&
Objects.equals(this.functionDescription, that.functionDescription) &&
Objects.equals(this.fieldName, that.fieldName) &&
Objects.equals(this.byFieldName, that.byFieldName) &&
Objects.equals(this.byFieldValue, that.byFieldValue) &&
Objects.equals(this.correlatedByFieldValue, that.correlatedByFieldValue) &&
Objects.equals(this.partitionFieldName, that.partitionFieldName) &&
Objects.equals(this.partitionFieldValue, that.partitionFieldValue) &&
Objects.equals(this.overFieldName, that.overFieldName) &&
Objects.equals(this.overFieldValue, that.overFieldValue) &&
Objects.equals(this.influencers, that.influencers);
}
}
Loading

0 comments on commit eb44fe6

Please sign in to comment.