Extend SymptomArray to Diagnosis and Action

This commit is contained in:
Ashvin Agrawal 2018-02-09 09:23:08 -08:00
Родитель 18057d4369
Коммит 76468bcc3b
11 изменённых файлов: 654 добавлений и 269 удалений

Просмотреть файл

@ -9,47 +9,27 @@ package com.microsoft.dhalion.core;
import com.microsoft.dhalion.api.IResolver;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/**
* {@link Action} is a representation of a action taken by {@link IResolver} to improve system health.
*/
public class Action {
// action type
private final String type;
// instant when this action was created
private final Instant instant;
// Diagnosis relevant to this action
private final Collection<Diagnosis> diagnosis;
public Action(String type, Instant instant, Collection<Diagnosis> diagnosis) {
this.type = type;
this.instant = instant;
this.diagnosis = new ArrayList<>(diagnosis);
public class Action extends Outcome {
public Action(String type, Instant instant, Collection<String> assignments) {
super(type, instant, assignments);
}
public String getType() {
return type;
}
public Instant getInstant() {
return instant;
}
public Collection<Diagnosis> getDiagnosis() {
return Collections.unmodifiableCollection(diagnosis);
public Action(int id, String symptomType, Instant instant, Collection<String> assignments) {
super(id, symptomType, instant, assignments);
}
@Override
public String toString() {
return "Action{" +
"type='" + type + '\'' +
", instant=" + instant +
", diagnosis=" + diagnosis +
"id=" + id() +
", type=" + type() +
", instant=" + instant() +
", assignments=" + assignments() +
'}';
}
}

Просмотреть файл

@ -0,0 +1,158 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This program is made available under the terms of the MIT License.
* See the LICENSE file in the project root for more information.
*/
package com.microsoft.dhalion.core;
import tech.tablesaw.api.Table;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
//TODO thread safety
/**
* An ordered collection of {@link Action}s. It provides methods to filter, query and aggregate the
* {@link Action}s.
*/
public class ActionArray extends OutcomeArray<Action> {
private ActionArray() {
super("Actions");
}
private ActionArray(Table table) {
super(table);
}
/**
* @param actions collections of actions
* @return a {@link ActionArray} holding the input
*/
public ActionArray of(Collection<Action> actions) {
ActionArray array = new ActionArray();
array.addAll(actions);
return array;
}
private void addAll(Collection<Action> actions) {
actions.forEach(action -> {
action.assignments().forEach(assignment -> {
id.append(action.id());
this.assignment.append(assignment);
type.append(action.type());
timeStamp.append(action.instant().toEpochMilli());
});
});
}
/**
* @param id unique action id
* @return {@link Action}s with the given id
*/
public ActionArray id(int id) {
Table result = filterId(id);
return new ActionArray(result);
}
/**
* Retains all {@link Action}s with given action type
*
* @param types names of the action types, not null
* @return {@link ActionArray} containing filtered {@link Action}s
*/
public ActionArray type(Collection<String> types) {
return new ActionArray(filterType(types));
}
/**
* @param type a action type
* @return {@link ActionArray} containing filtered {@link Action}s
* @see #type(Collection)
*/
public ActionArray type(String type) {
return type(Collections.singletonList(type));
}
/**
* Retains all {@link Action}s with given assignment ids.
*
* @param assignments assignment ids, not null
* @return {@link ActionArray} containing filtered {@link Action}s
*/
public ActionArray assignment(Collection<String> assignments) {
return new ActionArray(filterAssignment(assignments));
}
/**
* @param assignment assignment id
* @return {@link ActionArray} containing filtered {@link Action}s
* @see #assignment(Collection)
*/
public ActionArray assignment(String assignment) {
return assignment(Collections.singletonList(assignment));
}
/**
* Retains all {@link Action}s with timestamp in the given range.
*
* @param oldest the oldest timestamp, null to ignore this condition
* @param newest the newest timestamp, null to ignore this condition
* @return {@link ActionArray} containing filtered {@link Action}s
*/
public ActionArray between(Instant oldest, Instant newest) {
return new ActionArray(filterTime(oldest, newest));
}
/**
* Sorts the {@link Action}s in this collection in the order of the specified keys
*
* @param descending false for ascending order, true for descending
* @param sortKeys one or more sort keys, e.g. {@link SortKey#ID}
* @return ordered {@link Action}s
*/
public ActionArray sort(boolean descending, SortKey... sortKeys) {
return new ActionArray(sortTable(descending, sortKeys));
}
/**
* Retains the {@link Action} positioned between <code>first</code> and <code>last</code>, both inclusive,
* positions in this collection
*
* @param first the lowest index {@link Action} to be retained
* @param last the highest index {@link Action} to be retained
* @return {@link ActionArray} containing specific {@link Action}s
*/
public ActionArray slice(int first, int last) {
return new ActionArray(sliceTable(first, last));
}
Action row2Obj(int index) {
return new Action(id.get(index),
type.get(index),
Instant.ofEpochMilli(timeStamp.get(index)),
Collections.singletonList(assignment.get(index)));
}
/**
* Builds {@link ActionArray} instance and provides ability to update it.
*/
public static class Builder {
private final ActionArray actionsArray = new ActionArray();
public ActionArray get() {
return actionsArray;
}
public void addAll(Collection<Action> actions) {
if (actions == null) {
return;
}
this.actionsArray.addAll(actions);
}
}
}

Просмотреть файл

@ -7,48 +7,28 @@
package com.microsoft.dhalion.core;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/**
* A {@link Diagnosis} is a representation of a possible causes of one or more {@link Symptom}s. For e.g. resource
* under-provisioning
*/
public class Diagnosis {
// diagnosis identifier
private final String type;
// instant when this diagnosis was created
private final Instant instant;
// symptoms corresponding to this symptom
private final Collection<Symptom> symptoms;
public Diagnosis(String type, Instant instant, Collection<Symptom> symptoms) {
this.type = type;
this.instant = instant;
this.symptoms = new ArrayList<>(symptoms);
public class Diagnosis extends Outcome {
public Diagnosis(String type, Instant instant, Collection<String> assignments) {
super(type, instant, assignments);
}
public String getType() {
return type;
}
public Instant getInstant() {
return instant;
}
public Collection<Symptom> getSymptoms() {
return Collections.unmodifiableCollection(symptoms);
public Diagnosis(int id, String symptomType, Instant instant, Collection<String> assignments) {
super(id, symptomType, instant, assignments);
}
@Override
public String toString() {
return "Diagnosis{" +
"type='" + type + '\'' +
", instant=" + instant +
", symptoms=" + symptoms +
"id=" + id() +
", type=" + type() +
", instant=" + instant() +
", assignments=" + assignments() +
'}';
}
}

Просмотреть файл

@ -0,0 +1,158 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This program is made available under the terms of the MIT License.
* See the LICENSE file in the project root for more information.
*/
package com.microsoft.dhalion.core;
import tech.tablesaw.api.Table;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
//TODO thread safety
/**
* An ordered collection of {@link Diagnosis}. It provides methods to filter, query and aggregate the
* {@link Diagnosis} .
*/
public class DiagnosisArray extends OutcomeArray<Diagnosis> {
private DiagnosisArray() {
super("Symptoms");
}
private DiagnosisArray(Table table) {
super(table);
}
/**
* @param diagnosis collections of diagnosis
* @return a {@link DiagnosisArray} holding the input
*/
public DiagnosisArray of(Collection<Diagnosis> diagnosis) {
DiagnosisArray array = new DiagnosisArray();
array.addAll(diagnosis);
return array;
}
private void addAll(Collection<Diagnosis> diagnosis) {
diagnosis.forEach(diagnoses -> {
diagnoses.assignments().forEach(assignment -> {
id.append(diagnoses.id());
this.assignment.append(assignment);
type.append(diagnoses.type());
timeStamp.append(diagnoses.instant().toEpochMilli());
});
});
}
/**
* @param id unique diagnosis id
* @return {@link Diagnosis} with the given id
*/
public DiagnosisArray id(int id) {
Table result = filterId(id);
return new DiagnosisArray(result);
}
/**
* Retains all {@link Diagnosis} with given diagnosis type
*
* @param types names of the diagnosis types, not null
* @return {@link DiagnosisArray} containing filtered {@link Diagnosis}
*/
public DiagnosisArray type(Collection<String> types) {
return new DiagnosisArray(filterType(types));
}
/**
* @param type a diagnosis type
* @return {@link DiagnosisArray} containing filtered {@link Diagnosis}
* @see #type(Collection)
*/
public DiagnosisArray type(String type) {
return type(Collections.singletonList(type));
}
/**
* Retains all {@link Diagnosis} with given assignment ids.
*
* @param assignments assignment ids, not null
* @return {@link DiagnosisArray} containing filtered {@link Diagnosis}
*/
public DiagnosisArray assignment(Collection<String> assignments) {
return new DiagnosisArray(filterAssignment(assignments));
}
/**
* @param assignment assignment id
* @return {@link DiagnosisArray} containing filtered {@link Diagnosis}
* @see #assignment(Collection)
*/
public DiagnosisArray assignment(String assignment) {
return assignment(Collections.singletonList(assignment));
}
/**
* Retains all {@link Diagnosis} with timestamp in the given range.
*
* @param oldest the oldest timestamp, null to ignore this condition
* @param newest the newest timestamp, null to ignore this condition
* @return {@link DiagnosisArray} containing filtered {@link Diagnosis}
*/
public DiagnosisArray between(Instant oldest, Instant newest) {
return new DiagnosisArray(filterTime(oldest, newest));
}
/**
* Sorts the {@link Diagnosis} in this collection in the order of the specified keys
*
* @param descending false for ascending order, true for descending
* @param sortKeys one or more sort keys, e.g. {@link SortKey#ID}
* @return ordered {@link Diagnosis}
*/
public DiagnosisArray sort(boolean descending, SortKey... sortKeys) {
return new DiagnosisArray(sortTable(descending, sortKeys));
}
/**
* Retains the {@link Diagnosis} positioned between <code>first</code> and <code>last</code>, both inclusive,
* positions in this collection
*
* @param first the lowest index {@link Diagnosis} to be retained
* @param last the highest index {@link Diagnosis} to be retained
* @return {@link DiagnosisArray} containing specific {@link Diagnosis}s
*/
public DiagnosisArray slice(int first, int last) {
return new DiagnosisArray(sliceTable(first, last));
}
Diagnosis row2Obj(int index) {
return new Diagnosis(id.get(index),
type.get(index),
Instant.ofEpochMilli(timeStamp.get(index)),
Collections.singletonList(assignment.get(index)));
}
/**
* Builds {@link DiagnosisArray} instance and provides ability to update it.
*/
public static class Builder {
private final DiagnosisArray diagnosisArray = new DiagnosisArray();
public DiagnosisArray get() {
return diagnosisArray;
}
public void addAll(Collection<Diagnosis> diagnosis) {
if (diagnosis == null) {
return;
}
this.diagnosisArray.addAll(diagnosis);
}
}
}

Просмотреть файл

@ -84,6 +84,10 @@ public class MeasurementsArray {
});
}
/**
* @param measurements collections of measurements
* @return a {@link MeasurementsArray} holding the input
*/
public MeasurementsArray of(Collection<Measurement> measurements) {
MeasurementsArray array = new MeasurementsArray();
array.addAll(measurements);

Просмотреть файл

@ -0,0 +1,62 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This program is made available under the terms of the MIT License.
* See the LICENSE file in the project root for more information.
*/
package com.microsoft.dhalion.core;
import com.microsoft.dhalion.api.IDetector;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A {@link Outcome} represent result of execution of a Dhalion phase. For e.g. {@link IDetector} phase's results in
* {@link Symptom}s
*/
abstract class Outcome {
private static final AtomicInteger idGenerator = new AtomicInteger(1);
// unique identifier of this instance
private final int id;
// outcome category identifier
private final String type;
// instant when this outcome was created
private final Instant instant;
// ids of objects to which this outcome can be attributed to, for e.g. slow instance's id
private final Collection<String> assignments;
Outcome(String type, Instant instant, Collection<String> assignments) {
this(idGenerator.incrementAndGet(), type, instant, assignments);
}
Outcome(int id, String type, Instant instant, Collection<String> assignments) {
this.id = id;
this.type = type;
this.instant = instant;
this.assignments = Collections.unmodifiableCollection(assignments);
}
public int id() {
return id;
}
public String type() {
return type;
}
public Instant instant() {
return instant;
}
public Collection<String> assignments() {
return assignments;
}
}

Просмотреть файл

@ -0,0 +1,205 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This program is made available under the terms of the MIT License.
* See the LICENSE file in the project root for more information.
*/
package com.microsoft.dhalion.core;
import tech.tablesaw.api.CategoryColumn;
import tech.tablesaw.api.IntColumn;
import tech.tablesaw.api.LongColumn;
import tech.tablesaw.api.Table;
import tech.tablesaw.columns.ColumnReference;
import tech.tablesaw.filtering.Filter;
import tech.tablesaw.filtering.LongGreaterThanOrEqualTo;
import tech.tablesaw.filtering.LongLessThanOrEqualTo;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static tech.tablesaw.api.QueryHelper.both;
import static tech.tablesaw.api.QueryHelper.column;
import static tech.tablesaw.api.QueryHelper.or;
//TODO thread safety
/**
* An ordered collection of {@link Outcome} instances. This class provides methods to filter, query and aggregate the
* {@link Outcome} instances.
*/
public abstract class OutcomeArray<T extends Outcome> {
final Table table;
final CategoryColumn type;
final IntColumn id;
final CategoryColumn assignment;
final LongColumn timeStamp;
private static final String ID = SortKey.ID.name();
private static final String ASSIGNMENT = SortKey.ASSIGNMENT.name();
private static final String TIME_STAMP = SortKey.TIME_STAMP.name();
private static final String TYPE = SortKey.TYPE.name();
public enum SortKey {
ID, ASSIGNMENT, TIME_STAMP, TYPE
}
OutcomeArray(String name) {
id = new IntColumn(ID);
assignment = new CategoryColumn(ASSIGNMENT);
type = new CategoryColumn(TYPE);
timeStamp = new LongColumn(TIME_STAMP);
table = Table.create(name);
table.addColumn(id);
table.addColumn(assignment);
table.addColumn(type);
table.addColumn(timeStamp);
}
OutcomeArray(Table table) {
this.table = table;
id = this.table.intColumn(ID);
assignment = this.table.categoryColumn(ASSIGNMENT);
type = this.table.categoryColumn(TYPE);
timeStamp = this.table.longColumn(TIME_STAMP);
}
Table filterId(int id) {
return table.selectWhere(column(ID).isEqualTo(id));
}
Table filterType(Collection<String> types) {
return applyCategoryFilter(types, TYPE);
}
Table filterType(String type) {
return filterType(Collections.singletonList(type));
}
Table filterAssignment(Collection<String> assignments) {
return applyCategoryFilter(assignments, ASSIGNMENT);
}
Table filterAssignment(String assignment) {
return filterAssignment(Collections.singletonList(assignment));
}
private Table applyCategoryFilter(Collection<String> names, String column) {
List<Filter> filters = names.stream().map(name -> column(column).isEqualTo(name)).collect(Collectors.toList());
return table.selectWhere(or(filters));
}
Table filterTime(Instant oldest, Instant newest) {
return table.selectWhere(
both(new LongGreaterThanOrEqualTo(new ColumnReference(TIME_STAMP), oldest.toEpochMilli()),
new LongLessThanOrEqualTo(new ColumnReference(TIME_STAMP), newest.toEpochMilli())));
}
/**
* @return count of {@link Outcome} rows in this collection
*/
public int size() {
return table.rowCount();
}
/**
* @return unique ids in this collection
*/
public Collection<Integer> uniqueIds() {
ArrayList<Integer> result = new ArrayList<>();
IntColumn uniqueColumn = id.unique();
for (int id : uniqueColumn) {
result.add(id);
}
return result;
}
/**
* @return unique {@link Outcome} types in this collection
*/
public Collection<String> uniqueTypes() {
ArrayList<String> result = new ArrayList<>();
CategoryColumn uniqueColumn = type.unique();
uniqueColumn.forEach(result::add);
return result;
}
/**
* @return unique {@link Instant}s at which {@link Outcome} objects were created
*/
public Collection<Instant> uniqueInstants() {
ArrayList<Instant> result = new ArrayList<>();
LongColumn uniqueColumn = timeStamp.unique();
for (Long ts : uniqueColumn) {
result.add(Instant.ofEpochMilli(ts));
}
return result;
}
Table sortTable(boolean descending, SortKey... sortKeys) {
String[] columns = new String[sortKeys.length];
for (int i = 0; i < sortKeys.length; i++) {
columns[i] = sortKeys[i].name();
}
Table result;
if (descending) {
result = table.sortDescendingOn(columns);
} else {
result = table.sortAscendingOn(columns);
}
return result;
}
Table sliceTable(int first, int last) {
return table.selectRows(first, last);
}
/**
* @return the first {@link Outcome} in this collection, if present
*/
public T first() {
return get(0);
}
/**
* @return the last {@link Outcome} in this collection, if present
*/
public T last() {
return get(table.rowCount() - 1);
}
/**
* @return all {@link Outcome} objects in this collection
*/
public Collection<T> get() {
ArrayList<T> result = new ArrayList<>();
for (int i = 0; i < table.rowCount(); i++) {
result.add(row2Obj(i));
}
return result;
}
/**
* @param index position in the table
* @return {@link Outcome} at the requested position
*/
public T get(int index) {
if (index < 0 || index >= table.rowCount() || table.isEmpty()) {
return null;
}
return row2Obj(index);
}
abstract T row2Obj(int index);
public String toStringForDebugging() {
return table.print(table.rowCount());
}
}

Просмотреть файл

@ -7,63 +7,28 @@
package com.microsoft.dhalion.core;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A {@link Symptom} identifies an anomaly or a potential health issue in a specific component of a
* distributed application. For e.g. identification of irregular processing latency.
*/
public class Symptom {
private static final AtomicInteger idGenerator = new AtomicInteger(1);
// symptom identifier
private final String type;
// unique identifier of this instance
private final int id;
// instant when this symptom was created
private final Instant instant;
// ids to which the symptom is assigned, for e.g. instances
private final Collection<String> assignments;
public class Symptom extends Outcome {
public Symptom(String symptomType, Instant instant, Collection<String> assignments) {
this(idGenerator.incrementAndGet(), symptomType, instant, assignments);
super(symptomType, instant, assignments);
}
public Symptom(int id, String symptomType, Instant instant, Collection<String> assignments) {
this.id = id;
this.type = symptomType;
this.instant = instant;
this.assignments = new ArrayList<>(assignments);
}
public int id() {
return id;
}
public String type() {
return type;
}
public Instant instant() {
return instant;
}
public Collection<String> assignments() {
return assignments;
super(id, symptomType, instant, assignments);
}
@Override
public String toString() {
return "Symptom{" +
"type=" + type +
", id=" + id +
", instant=" + instant +
", assignments=" + assignments +
"type=" + type() +
", id=" + id() +
", instant=" + instant() +
", assignments=" + assignments() +
'}';
}
}

Просмотреть файл

@ -6,25 +6,11 @@
*/
package com.microsoft.dhalion.core;
import tech.tablesaw.api.CategoryColumn;
import tech.tablesaw.api.IntColumn;
import tech.tablesaw.api.LongColumn;
import tech.tablesaw.api.Table;
import tech.tablesaw.columns.ColumnReference;
import tech.tablesaw.filtering.Filter;
import tech.tablesaw.filtering.LongGreaterThanOrEqualTo;
import tech.tablesaw.filtering.LongLessThanOrEqualTo;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static tech.tablesaw.api.QueryHelper.both;
import static tech.tablesaw.api.QueryHelper.column;
import static tech.tablesaw.api.QueryHelper.or;
//TODO thread safety
@ -32,41 +18,23 @@ import static tech.tablesaw.api.QueryHelper.or;
* An ordered collection of {@link Symptom}s. It provides methods to filter, query and aggregate the
* {@link Symptom}s.
*/
public class SymptomsArray {
private final Table symptoms;
private CategoryColumn type;
private IntColumn id;
private CategoryColumn assignment;
private LongColumn timeStamp;
public enum SortKey {
ID, ASSIGNMENT, TIME_STAMP, TYPE
}
private static final String ID = SortKey.ID.name();
private static final String ASSIGNMENT = SortKey.ASSIGNMENT.name();
private static final String TIME_STAMP = SortKey.TIME_STAMP.name();
private static final String TYPE = SortKey.TYPE.name();
public class SymptomsArray extends OutcomeArray<Symptom> {
private SymptomsArray() {
id = new IntColumn(ID);
assignment = new CategoryColumn(ASSIGNMENT);
type = new CategoryColumn(TYPE);
timeStamp = new LongColumn(TIME_STAMP);
symptoms = Table.create("Symptoms");
symptoms.addColumn(id);
symptoms.addColumn(assignment);
symptoms.addColumn(type);
symptoms.addColumn(timeStamp);
super("Symptoms");
}
private SymptomsArray(Table table) {
this.symptoms = table;
id = symptoms.intColumn(ID);
assignment = symptoms.categoryColumn(ASSIGNMENT);
type = symptoms.categoryColumn(TYPE);
timeStamp = symptoms.longColumn(TIME_STAMP);
super(table);
}
/**
* @param symptoms collections of symptoms
* @return a {@link SymptomsArray} holding the input
*/
public SymptomsArray of(Collection<Symptom> symptoms) {
SymptomsArray array = new SymptomsArray();
array.addAll(symptoms);
return array;
}
private void addAll(Collection<Symptom> symptoms) {
@ -85,7 +53,7 @@ public class SymptomsArray {
* @return {@link Symptom}s with the given id
*/
public SymptomsArray id(int id) {
Table result = symptoms.selectWhere(column(ID).isEqualTo(id));
Table result = filterId(id);
return new SymptomsArray(result);
}
@ -96,7 +64,7 @@ public class SymptomsArray {
* @return {@link SymptomsArray} containing filtered {@link Symptom}s
*/
public SymptomsArray type(Collection<String> types) {
return applyCategoryFilter(types, TYPE);
return new SymptomsArray(filterType(types));
}
/**
@ -115,7 +83,7 @@ public class SymptomsArray {
* @return {@link SymptomsArray} containing filtered {@link Symptom}s
*/
public SymptomsArray assignment(Collection<String> assignments) {
return applyCategoryFilter(assignments, ASSIGNMENT);
return new SymptomsArray(filterAssignment(assignments));
}
/**
@ -127,12 +95,6 @@ public class SymptomsArray {
return assignment(Collections.singletonList(assignment));
}
private SymptomsArray applyCategoryFilter(Collection<String> names, String column) {
List<Filter> filters = names.stream().map(name -> column(column).isEqualTo(name)).collect(Collectors.toList());
Table result = symptoms.selectWhere(or(filters));
return new SymptomsArray(result);
}
/**
* Retains all {@link Symptom}s with timestamp in the given range.
*
@ -141,52 +103,7 @@ public class SymptomsArray {
* @return {@link SymptomsArray} containing filtered {@link Symptom}s
*/
public SymptomsArray between(Instant oldest, Instant newest) {
Table result = symptoms.selectWhere(
both(new LongGreaterThanOrEqualTo(new ColumnReference(TIME_STAMP), oldest.toEpochMilli()),
new LongLessThanOrEqualTo(new ColumnReference(TIME_STAMP), newest.toEpochMilli())));
return new SymptomsArray(result);
}
/**
* @return count of {@link Symptom}s in this collection
*/
public int size() {
return symptoms.rowCount();
}
/**
* @return unique symptom ids in this collection of {@link Symptom}s
*/
public Collection<Integer> uniqueIds() {
ArrayList<Integer> result = new ArrayList<>();
IntColumn uniqueColumn = id.unique();
for (int id : uniqueColumn) {
result.add(id);
}
return result;
}
/**
* @return unique symptom types in this collection of {@link Symptom}s
*/
public Collection<String> uniqueTypes() {
ArrayList<String> result = new ArrayList<>();
CategoryColumn uniqueColumn = type.unique();
uniqueColumn.forEach(result::add);
return result;
}
/**
* @return unique {@link Instant}s in this collection of {@link Symptom}s
*/
public Collection<Instant> uniqueInstants() {
ArrayList<Instant> result = new ArrayList<>();
LongColumn uniqueColumn = timeStamp.unique();
for (Long ts : uniqueColumn) {
result.add(Instant.ofEpochMilli(ts));
}
return result;
return new SymptomsArray(filterTime(oldest, newest));
}
/**
@ -197,18 +114,7 @@ public class SymptomsArray {
* @return ordered {@link Symptom}s
*/
public SymptomsArray sort(boolean descending, SortKey... sortKeys) {
String[] columns = new String[sortKeys.length];
for (int i = 0; i < sortKeys.length; i++) {
columns[i] = sortKeys[i].name();
}
Table result;
if (descending) {
result = symptoms.sortDescendingOn(columns);
} else {
result = symptoms.sortAscendingOn(columns);
}
return new SymptomsArray(result);
return new SymptomsArray(sortTable(descending, sortKeys));
}
/**
@ -220,60 +126,10 @@ public class SymptomsArray {
* @return {@link SymptomsArray} containing specific {@link Symptom}s
*/
public SymptomsArray slice(int first, int last) {
Table result = symptoms.selectRows(first, last);
return new SymptomsArray(result);
return new SymptomsArray(sliceTable(first, last));
}
/**
* @return the first {@link Symptom}, if present
*/
public Symptom first() {
if (symptoms.isEmpty()) {
return null;
}
Table result = symptoms.first(1);
Collection<Symptom> measurementCollection = new SymptomsArray(result).get();
return measurementCollection.iterator().next();
}
/**
* @return the last {@link Symptom}, if present
*/
public Symptom last() {
if (symptoms.isEmpty()) {
return null;
}
Table result = symptoms.last(1);
Collection<Symptom> measurementCollection = new SymptomsArray(result).get();
return measurementCollection.iterator().next();
}
/**
* @return all {@link Symptom}s in this collection
*/
public Collection<Symptom> get() {
ArrayList<Symptom> result = new ArrayList<>();
for (int i = 0; i < symptoms.rowCount(); i++) {
result.add(row2Obj(i));
}
return result;
}
/**
* @param index position in the table
* @return {@link Symptom} at the requested position
*/
public Symptom get(int index) {
if (index < 0 || index >= symptoms.rowCount() || symptoms.isEmpty()) {
return null;
}
return row2Obj(index);
}
private Symptom row2Obj(int index) {
Symptom row2Obj(int index) {
return new Symptom(id.get(index),
type.get(index),
Instant.ofEpochMilli(timeStamp.get(index)),
@ -281,10 +137,6 @@ public class SymptomsArray {
}
public String toStringForDebugging() {
return symptoms.print(symptoms.rowCount());
}
/**
* Builds {@link SymptomsArray} instance and provides ability to update it.
*/

Просмотреть файл

@ -9,7 +9,9 @@ package com.microsoft.dhalion.policy;
import com.microsoft.dhalion.api.IHealthPolicy;
import com.microsoft.dhalion.core.Action;
import com.microsoft.dhalion.core.ActionArray;
import com.microsoft.dhalion.core.Diagnosis;
import com.microsoft.dhalion.core.DiagnosisArray;
import com.microsoft.dhalion.core.Measurement;
import com.microsoft.dhalion.core.MeasurementsArray;
import com.microsoft.dhalion.core.Symptom;
@ -70,8 +72,14 @@ public class PoliciesExecutor {
policyContextMap.get(policy).measurementsArrayBuilder.addAll(measurements);
Collection<Symptom> symptoms = policy.executeDetectors(measurements);
policyContextMap.get(policy).symptomsArrayBuilder.addAll(symptoms);
Collection<Diagnosis> diagnosis = policy.executeDiagnosers(symptoms);
policyContextMap.get(policy).diagnsisArrayBuilder.addAll(diagnosis);
Collection<Action> actions = policy.executeResolvers(diagnosis);
policyContextMap.get(policy).actionArrayBuilder.addAll(actions);
// TODO pretty print
LOG.info(actions.toString());
@ -91,17 +99,30 @@ public class PoliciesExecutor {
public static class ExecutionContext {
private final MeasurementsArray.Builder measurementsArrayBuilder;
private final SymptomsArray.Builder symptomsArrayBuilder;
private final DiagnosisArray.Builder diagnsisArrayBuilder;
private final ActionArray.Builder actionArrayBuilder;
private ExecutionContext() {
measurementsArrayBuilder = new MeasurementsArray.Builder();
symptomsArrayBuilder = new SymptomsArray.Builder();
diagnsisArrayBuilder = new DiagnosisArray.Builder();
actionArrayBuilder = new ActionArray.Builder();
}
public MeasurementsArray measurements() {
return measurementsArrayBuilder.get();
}
public SymptomsArray symptoms() {
return symptomsArrayBuilder.get();
}
public DiagnosisArray diagnosis() {
return diagnsisArrayBuilder.get();
}
public ActionArray actions() {
return actionArrayBuilder.get();
}
}
}

Просмотреть файл

@ -7,8 +7,8 @@
package com.microsoft.dhalion.core;
import com.microsoft.dhalion.core.OutcomeArray.SortKey;
import com.microsoft.dhalion.core.SymptomsArray.Builder;
import com.microsoft.dhalion.core.SymptomsArray.SortKey;
import org.junit.Before;
import org.junit.Test;