зеркало из https://github.com/microsoft/Dhalion.git
Extend SymptomArray to Diagnosis and Action
This commit is contained in:
Родитель
18057d4369
Коммит
76468bcc3b
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче