/// <summary> /// This is a function for analyze one layer for root cause, we select one dimension with values who contributes the most to the anomaly. /// </summary> private RootCause AnalyzeOneLayer(RootCauseLocalizationInput src) { RootCause dst = new RootCause(); dst.Items = new List <RootCauseItem>(); DimensionInfo dimensionInfo = SeparateDimension(src.AnomalyDimension, src.AggregateSymbol); Tuple <PointTree, PointTree, Dictionary <Dictionary <string, object>, TimeSeriesPoint> > pointInfo = GetPointsInfo(src, dimensionInfo); PointTree pointTree = pointInfo.Item1; PointTree anomalyTree = pointInfo.Item2; Dictionary <Dictionary <string, Object>, TimeSeriesPoint> dimPointMapping = pointInfo.Item3; //which means there is no anomaly point with the anomaly dimension or no point under anomaly dimension if (anomalyTree.ParentNode == null || dimPointMapping.Count == 0) { return(dst); } dst.Items.AddRange(LocalizeRootCauseByDimension(anomalyTree, pointTree, src.AnomalyDimension, dimensionInfo.AggDims)); GetRootCauseDirectionAndScore(dimPointMapping, src.AnomalyDimension, dst, _beta, pointTree, src.AggregateType, src.AggregateSymbol); return(dst); }
private void GetRootCauseDirectionAndScore(Dictionary <Dictionary <string, Object>, TimeSeriesPoint> dimPointMapping, Dictionary <string, Object> anomalyRoot, RootCause dst, double beta, PointTree pointTree, AggregateType aggType, Object aggSymbol) { TimeSeriesPoint anomalyPoint = GetPointByDimension(dimPointMapping, anomalyRoot, pointTree, aggType, aggSymbol); if (dst.Items.Count > 1) { //get surprise value and explanatory power value List <RootCauseScore> scoreList = new List <RootCauseScore>(); foreach (RootCauseItem item in dst.Items) { TimeSeriesPoint rootCausePoint = GetPointByDimension(dimPointMapping, item.Dimension, pointTree, aggType, aggSymbol); if (anomalyPoint != null && rootCausePoint != null) { Tuple <double, double> scores = GetSurpriseAndExplanatoryScore(rootCausePoint, anomalyPoint); scoreList.Add(new RootCauseScore(scores.Item1, scores.Item2)); item.Direction = GetRootCauseDirection(rootCausePoint); } } //get final score for (int i = 0; i < scoreList.Count; i++) { if (aggType.Equals(AggregateType.Max) || aggType.Equals(AggregateType.Min)) { dst.Items[i].Score = 1; } else { dst.Items[i].Score = GetFinalScore(scoreList[i].Surprise, Math.Abs(scoreList[i].ExplanatoryScore), beta); } } } else if (dst.Items.Count == 1) { TimeSeriesPoint rootCausePoint = GetPointByDimension(dimPointMapping, dst.Items[0].Dimension, pointTree, aggType, aggSymbol); if (anomalyPoint != null && rootCausePoint != null) { Tuple <double, double> scores = GetSurpriseAndExplanatoryScore(rootCausePoint, anomalyPoint); if (aggType.Equals(AggregateType.Max) || aggType.Equals(AggregateType.Min)) { dst.Items[0].Score = 1; } else { dst.Items[0].Score = GetFinalScore(scores.Item1, scores.Item2, beta); } dst.Items[0].Direction = GetRootCauseDirection(rootCausePoint); } } }
private void LocalizeRootCausesByDimension(PointTree anomalyTree, PointTree pointTree, Dictionary <string, Object> anomalyDimension, List <string> aggDims) { IEnumerable <BestDimension> best; if (anomalyTree.ChildrenNodes.Count == 0) { //has no children node information, should use the leaves node (whose point has no aggregated dimensions) information best = SelectOrderedDimension(pointTree.Leaves, anomalyTree.Leaves, aggDims); } else { //has no leaves information, should calculate the entropy information according to the children nodes best = SelectOrderedDimensions(pointTree.ChildrenNodes, anomalyTree.ChildrenNodes, aggDims); } if (best == null) { _preparedCauses.Add(new RootCause { Items = new List <RootCauseItem>() { new RootCauseItem(anomalyDimension) } }); } bool rootAsAnomaly = false; foreach (var dimension in best) { RootCause rootCause = new RootCause { Items = new List <RootCauseItem>() }; rootCause.GainRatio = dimension.GainRatio; List <TimeSeriesPoint> children = null; if (anomalyTree.ChildrenNodes.ContainsKey(dimension.DimensionKey)) { //Use children node information to get top anomalies children = GetTopAnomaly(anomalyTree.ChildrenNodes[dimension.DimensionKey], anomalyTree.ParentNode, pointTree.ChildrenNodes[dimension.DimensionKey].Count > 0 ? pointTree.ChildrenNodes[dimension.DimensionKey] : pointTree.Leaves, dimension.DimensionKey, !(pointTree.ChildrenNodes[dimension.DimensionKey].Count > 0)); } else { //Use leaves node informatin to get top anomalies children = GetTopAnomaly(anomalyTree.Leaves, anomalyTree.ParentNode, pointTree.Leaves, dimension.DimensionKey, true); } if (children == null) { //As the cause couldn't be found, the root cause should be itself if (!rootAsAnomaly) { rootAsAnomaly = true; rootCause.Items.Add(new RootCauseItem(anomalyDimension)); } } else { rootCause.Items.AddRange(children.Select(anomaly => new RootCauseItem(UpdateDimensionValue(anomalyDimension, dimension.DimensionKey, anomaly.Dimension[dimension.DimensionKey]), new List <string>() { dimension.DimensionKey }))); } _preparedCauses.Add(rootCause); } }