-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
187 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,15 @@ | ||
package com.microsoft.dhalion; | ||
|
||
import java.util.ArrayList; | ||
/* | ||
* 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. | ||
*/ | ||
|
||
import static java.awt.SystemColor.text; | ||
package com.microsoft.dhalion; | ||
|
||
public class Utils { | ||
|
||
public static String getCompositeName(String... names) { | ||
if (names.length > 0) { | ||
String text = names[0]; | ||
for (int i = 1; i < names.length; i++) { | ||
text = text + "_" + names[i]; | ||
} | ||
return text; | ||
} | ||
return ""; | ||
return names.length > 0 ? String.join("_", names) : ""; | ||
} | ||
|
||
} |
76 changes: 41 additions & 35 deletions
76
src/main/java/com/microsoft/dhalion/detectors/AboveThresholdDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,78 @@ | ||
/* | ||
* 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.detectors; | ||
|
||
import com.microsoft.dhalion.Utils; | ||
import com.microsoft.dhalion.conf.PolicyConfig; | ||
import com.microsoft.dhalion.core.Measurement; | ||
import com.microsoft.dhalion.core.MeasurementsTable; | ||
import com.microsoft.dhalion.core.MeasurementsTable.SortKey; | ||
import com.microsoft.dhalion.core.Symptom; | ||
|
||
import javax.inject.Inject; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* The AboveThreshold Detector evaluates whether the values of a certain metric are above a user-defined | ||
* threshold during a time window and in this case returns a symptom. The detector takes as input the metric name, | ||
* the threshold and the time window specified as the number of latest checkpoints. It generates a | ||
* SYMPTOM_HIGH_metricName symptom that is parameterized by the metric name. | ||
* | ||
* {@link AboveThresholdDetector}_metricName symptom that is parameterized by the metric name. | ||
* <p> | ||
* For example, if the threshold is set to 90, the number of latest checkpoints is set to 2 and the metric is set to | ||
* CPU_UTILIZATION, then the detector will return a symptom SYMPTOM_HIGH_CPU_UTILIZATION only when the CPU_UTILIZATION | ||
* is above 90 consistently during the last 2 invocations of the policy. By default the number of checkpoints is set | ||
* to 1 which means that the detector considers only the current value when determining whether to return a symptom. | ||
* CPU_UTILIZATION, then the detector will return a symptom AboveThresholdDetector_CPU_UTILIZATION only when the | ||
* CPU_UTILIZATION is above 90 consistently during the last 2 invocations of the policy. By default the number of | ||
* checkpoints is set to 1 which means that the detector considers only the current value when determining whether to | ||
* return a symptom. | ||
*/ | ||
public class AboveThresholdDetector extends Detector { | ||
public static String SYMPTOM_HIGH = AboveThresholdDetector.class.getSimpleName(); | ||
|
||
public static final String HIGH_THRESHOLD_CONF = "AboveThresholdDetector.threshold"; | ||
public static final String ABOVE_THRESHOLD_NO_CHECKPOINTS = "AboveThresholdDetector.noCheckpoints"; | ||
public static final String SYMPTOM_HIGH = AboveThresholdDetector.class.getSimpleName(); | ||
static final String HIGH_THRESHOLD_CONF = "AboveThresholdDetector.threshold"; | ||
static final String ABOVE_THRESHOLD_NO_CHECKPOINTS = "AboveThresholdDetector.noCheckpoints"; | ||
|
||
private final double highThreshold; | ||
private String metricName; | ||
private double noCheckpoints; | ||
|
||
private static final Logger LOG = Logger.getLogger(AboveThresholdDetector.class.getSimpleName()); | ||
|
||
|
||
@Inject | ||
public AboveThresholdDetector(PolicyConfig policyConfig, String metricName) { | ||
this.highThreshold = (Double) policyConfig.getConfig(Utils.getCompositeName(HIGH_THRESHOLD_CONF, metricName)); | ||
this.noCheckpoints = (Double) policyConfig.getConfig(Utils.getCompositeName(ABOVE_THRESHOLD_NO_CHECKPOINTS, | ||
metricName), 1); | ||
this.highThreshold = (Double) policyConfig.getConfig(String.join("_", HIGH_THRESHOLD_CONF, metricName)); | ||
this.noCheckpoints | ||
= (Double) policyConfig.getConfig(String.join("_", ABOVE_THRESHOLD_NO_CHECKPOINTS, metricName), 1); | ||
this.metricName = metricName; | ||
} | ||
|
||
@Override | ||
public Collection<Symptom> detect(Collection<Measurement> measurements) { | ||
ArrayList<Symptom> result = new ArrayList<>(); | ||
if (measurements.size() > 0) { | ||
MeasurementsTable measurementsTable = context.measurements().type(metricName).sort(false, SortKey.TIME_STAMP); | ||
Collection<String> aboveThresholdAssignments = new ArrayList(); | ||
for (String component : measurementsTable.uniqueComponents()) { | ||
MeasurementsTable componentData = measurementsTable.component(component); | ||
for (String instance : componentData.uniqueInstances()) { | ||
MeasurementsTable instanceData = measurementsTable.instance(instance).last((int) noCheckpoints); | ||
if (instanceData.valueBetween(highThreshold, Double.MAX_VALUE).size() == noCheckpoints) { | ||
LOG.fine(String.format("Instance %s has values above the limit for the last %s checkpoints", instance, | ||
noCheckpoints)); | ||
aboveThresholdAssignments.add(instance); | ||
} | ||
if (measurements.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
Collection<String> assignments = new ArrayList<>(); | ||
MeasurementsTable measurementsTable = context.measurements().type(metricName).sort(false, SortKey.TIME_STAMP); | ||
for (String component : measurementsTable.uniqueComponents()) { | ||
MeasurementsTable componentData = measurementsTable.component(component); | ||
for (String instance : componentData.uniqueInstances()) { | ||
MeasurementsTable instanceData = componentData.instance(instance).last((int) noCheckpoints); | ||
if (instanceData.valueBetween(highThreshold, Double.MAX_VALUE).size() == noCheckpoints) { | ||
LOG.fine(String.format("Instance %s has values above the limit (%s) for the last %s checkpoints", | ||
instance, highThreshold, noCheckpoints)); | ||
assignments.add(instance); | ||
} | ||
} | ||
if (aboveThresholdAssignments.size() > 0) { | ||
Symptom s = new Symptom(Utils.getCompositeName(SYMPTOM_HIGH, metricName), context.checkpoint(), | ||
aboveThresholdAssignments); | ||
result.add(s); | ||
} | ||
} | ||
return result; | ||
|
||
if (assignments.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
Symptom s = new Symptom(String.join("_", SYMPTOM_HIGH, metricName), context.checkpoint(), assignments); | ||
return Collections.singletonList(s); | ||
} | ||
} |
72 changes: 40 additions & 32 deletions
72
src/main/java/com/microsoft/dhalion/detectors/BelowThresholdDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,79 @@ | ||
/* | ||
* 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.detectors; | ||
|
||
import com.microsoft.dhalion.Utils; | ||
import com.microsoft.dhalion.conf.PolicyConfig; | ||
import com.microsoft.dhalion.core.Measurement; | ||
import com.microsoft.dhalion.core.MeasurementsTable; | ||
import com.microsoft.dhalion.core.MeasurementsTable.SortKey; | ||
import com.microsoft.dhalion.core.Symptom; | ||
|
||
import javax.inject.Inject; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* The BelowThreshold Detector evaluates whether the values of a certain metric are below a user-defined | ||
* threshold during a time window and in this case returns a symptom. The detector takes as input the metric name, | ||
* the threshold and the time window specified as the number of latest checkpoints. It generates a | ||
* SYMPTOM_LOW_metricName symptom that is parameterized by the metric name. | ||
* {@link BelowThresholdDetector}_metricName symptom that is parameterized by the metric name. | ||
* <p> | ||
* For example, if the threshold is set to 10, the number of latest checkpoints is set to 2 and the metric is set to | ||
* CPU_UTILIZATION, then the detector will return a symptom SYMPTOM_LOW_CPU_UTILIZATION only when the CPU_UTILIZATION | ||
* is below 10 consistently during the last 2 invocations of the policy. By default the number of checkpoints is set | ||
* to 1 which means that the detector considers only the current value when determining whether to return a symptom. | ||
* CPU_UTILIZATION, then the detector will return a symptom {@link BelowThresholdDetector}_CPU_UTILIZATION only when | ||
* the CPU_UTILIZATION is below 10 consistently during the last 2 invocations of the policy. By default the number of | ||
* checkpoints is set to 1 which means that the detector considers only the current value when determining whether to | ||
* return a symptom. | ||
*/ | ||
public class BelowThresholdDetector extends Detector { | ||
public static String SYMPTOM_LOW = BelowThresholdDetector.class.getSimpleName(); | ||
public static final String SYMPTOM_LOW = BelowThresholdDetector.class.getSimpleName(); | ||
|
||
public static final String LOW_THRESHOLD_CONF = "BelowThresholdDetector.threshold"; | ||
public static final String BELOW_THRESHOLD_NO_CHECKPOINTS = "BelowThresholdDetector.noCheckpoints"; | ||
static final String LOW_THRESHOLD_CONF = "BelowThresholdDetector.threshold"; | ||
static final String BELOW_THRESHOLD_NO_CHECKPOINTS = "BelowThresholdDetector.noCheckpoints"; | ||
|
||
private final double lowThreshold; | ||
private String metricName; | ||
private double noCheckpoints; | ||
|
||
private static final Logger LOG = Logger.getLogger(BelowThresholdDetector.class.getSimpleName()); | ||
|
||
@Inject | ||
public BelowThresholdDetector(PolicyConfig policyConfig, String metricName) { | ||
this.lowThreshold = (Double) policyConfig.getConfig(Utils.getCompositeName(LOW_THRESHOLD_CONF, metricName)); | ||
this.noCheckpoints = (Double) policyConfig.getConfig(Utils.getCompositeName(BELOW_THRESHOLD_NO_CHECKPOINTS, | ||
metricName), 1); | ||
this.lowThreshold = (Double) policyConfig.getConfig(String.join("_", LOW_THRESHOLD_CONF, metricName)); | ||
this.noCheckpoints | ||
= (Double) policyConfig.getConfig(String.join("_", BELOW_THRESHOLD_NO_CHECKPOINTS, metricName), 1); | ||
this.metricName = metricName; | ||
} | ||
|
||
@Override | ||
public Collection<Symptom> detect(Collection<Measurement> measurements) { | ||
ArrayList<Symptom> result = new ArrayList<>(); | ||
if (measurements.size() > 0) { | ||
MeasurementsTable measurementsTable = context.measurements().type(metricName).sort(false, SortKey.TIME_STAMP); | ||
Collection<String> belowThresholdAssignments = new ArrayList(); | ||
for (String component : measurementsTable.uniqueComponents()) { | ||
MeasurementsTable componentData = measurementsTable.component(component); | ||
for (String instance : componentData.uniqueInstances()) { | ||
MeasurementsTable instanceData = measurementsTable.instance(instance).last((int) noCheckpoints); | ||
if (instanceData.valueBetween(Double.MIN_VALUE, lowThreshold).size() == noCheckpoints) { | ||
LOG.fine(String.format("Instance %s has values below the limit for the last %s checkpoints", instance, | ||
noCheckpoints)); | ||
belowThresholdAssignments.add(instance); | ||
} | ||
if (measurements.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
MeasurementsTable measurementsTable = context.measurements().type(metricName).sort(false, SortKey.TIME_STAMP); | ||
Collection<String> assignments = new ArrayList<>(); | ||
for (String component : measurementsTable.uniqueComponents()) { | ||
MeasurementsTable componentData = measurementsTable.component(component); | ||
for (String instance : componentData.uniqueInstances()) { | ||
MeasurementsTable instanceData = componentData.instance(instance).last((int) noCheckpoints); | ||
if (instanceData.valueBetween(Double.MIN_VALUE, lowThreshold).size() == noCheckpoints) { | ||
LOG.fine(String.format("Instance %s has values below the limit %s for the last %s checkpoints", | ||
instance, lowThreshold, noCheckpoints)); | ||
assignments.add(instance); | ||
} | ||
} | ||
if (belowThresholdAssignments.size() > 0) { | ||
Symptom s = new Symptom(Utils.getCompositeName(SYMPTOM_LOW, metricName), context.checkpoint(), | ||
belowThresholdAssignments); | ||
result.add(s); | ||
} | ||
} | ||
return result; | ||
|
||
if (assignments.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
Symptom s = new Symptom(String.join("_", SYMPTOM_LOW, metricName), context.checkpoint(), assignments); | ||
return Collections.singletonList(s); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/microsoft/dhalion/examples/AlertPolicy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/microsoft/dhalion/examples/AlertResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/microsoft/dhalion/examples/CSVMetricsProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/microsoft/dhalion/examples/UncommonUtilizationDiagnoser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/test/java/com/microsoft/dhalion/detectors/AboveThresholdDetectorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/test/java/com/microsoft/dhalion/detectors/BelowThresholdDetectorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/test/java/com/microsoft/dhalion/examples/CSVMetricsProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/test/java/com/microsoft/dhalion/examples/NodeStatTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.