private Tuple <PointTree, PointTree, Dictionary <Dictionary <string, object>, TimeSeriesPoint> > GetPointsInfo(RootCauseLocalizationInput src, DimensionInfo dimensionInfo) { PointTree pointTree = new PointTree(); PointTree anomalyTree = new PointTree(); DimensionComparer dc = new DimensionComparer(); Dictionary <Dictionary <string, object>, TimeSeriesPoint> dimPointMapping = new Dictionary <Dictionary <string, object>, TimeSeriesPoint>(dc); List <TimeSeriesPoint> totalPoints = GetTotalPointsForAnomalyTimestamp(src); Dictionary <string, Object> subDim = GetSubDim(src.AnomalyDimension, dimensionInfo.DetailDims); foreach (TimeSeriesPoint point in totalPoints) { if (ContainsAll(point.Dimension, subDim)) { if (!dimPointMapping.ContainsKey(point.Dimension)) { dimPointMapping.Add(point.Dimension, point); bool isValidPoint = point.IsAnomaly == true; if (ContainsAll(point.Dimension, subDim)) { BuildTree(pointTree, dimensionInfo.AggDims, point, src.AggregateSymbol); if (isValidPoint) { BuildTree(anomalyTree, dimensionInfo.AggDims, point, src.AggregateSymbol); } } } } } return(new Tuple <PointTree, PointTree, Dictionary <Dictionary <string, Object>, TimeSeriesPoint> >(pointTree, anomalyTree, dimPointMapping)); }
/// <summary> /// This is a function for analyzing one layer for root cause. We rank dimensions according to their likelihood of containing the root case. /// For each dimension, we select one dimension with values who contributes the most to the anomaly. /// </summary> private List <RootCause> AnalyzeOneLayer(RootCauseLocalizationInput src) { 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) { _preparedCauses.Add(new RootCause() { Items = new List <RootCauseItem>() }); return(_preparedCauses); } LocalizeRootCausesByDimension(anomalyTree, pointTree, src.AnomalyDimension, dimensionInfo.AggDims); foreach (var dst in _preparedCauses) { GetRootCauseDirectionAndScore(dimPointMapping, src.AnomalyDimension, dst, _beta, pointTree, src.AggregateType, src.AggregateSymbol); } return(_preparedCauses); }
private void BuildTree(PointTree tree, List <string> aggDims, TimeSeriesPoint point, Object aggSymbol) { int aggNum = 0; string nextDim = null; foreach (string dim in aggDims) { if (IsAggregationDimension(point.Dimension[dim], aggSymbol)) { aggNum++; } else { nextDim = dim; } } if (aggNum == aggDims.Count) { tree.ParentNode = point; } else if (aggNum == aggDims.Count - 1) { if (!tree.ChildrenNodes.ContainsKey(nextDim)) { tree.ChildrenNodes.Add(nextDim, new List <TimeSeriesPoint>()); } tree.ChildrenNodes[nextDim].Add(point); } if (aggNum == 0) { tree.Leaves.Add(point); } }
private List <RootCauseItem> LocalizeRootCauseByDimension(PointTree anomalyTree, PointTree pointTree, Dictionary <string, Object> anomalyDimension, List <string> aggDims) { BestDimension best = null; if (anomalyTree.ChildrenNodes.Count == 0) { //has no children node information, should use the leaves node(whose point has no aggrgated dimensions) information best = SelectBestDimension(pointTree.Leaves, anomalyTree.Leaves, aggDims); } else { //has no leaves information, should calculate the entropy information according to the children nodes best = SelectBestDimension(pointTree.ChildrenNodes, anomalyTree.ChildrenNodes, aggDims); } if (best == null) { return(new List <RootCauseItem>() { new RootCauseItem(anomalyDimension) }); } List <TimeSeriesPoint> children = null; if (anomalyTree.ChildrenNodes.ContainsKey(best.DimensionKey)) { //Use children node information to get top anomalies children = GetTopAnomaly(anomalyTree.ChildrenNodes[best.DimensionKey], anomalyTree.ParentNode, pointTree.ChildrenNodes[best.DimensionKey].Count > 0 ? pointTree.ChildrenNodes[best.DimensionKey] : pointTree.Leaves, best.DimensionKey, !(pointTree.ChildrenNodes[best.DimensionKey].Count > 0)); } else { //Use leaves node informatin to get top anomalies children = GetTopAnomaly(anomalyTree.Leaves, anomalyTree.ParentNode, pointTree.Leaves, best.DimensionKey, true); } if (children == null) { //As the cause couldn't be found, the root cause should be itself return(new List <RootCauseItem>() { new RootCauseItem(anomalyDimension) }); } else { List <RootCauseItem> causes = new List <RootCauseItem>(); // For the found causes, we return the result foreach (TimeSeriesPoint anomaly in children) { causes.Add(new RootCauseItem(UpdateDimensionValue(anomalyDimension, best.DimensionKey, anomaly.Dimension[best.DimensionKey]), new List <string>() { best.DimensionKey })); } return(causes); } }
/// <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 <string, TimeSeriesPoint> > pointInfo = GetPointsInfo(src, dimensionInfo); PointTree pointTree = pointInfo.Item1; PointTree anomalyTree = pointInfo.Item2; Dictionary <string, 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 TimeSeriesPoint GetPointByDimension(Dictionary <Dictionary <string, Object>, TimeSeriesPoint> dimPointMapping, Dictionary <string, Object> dimension, PointTree pointTree, AggregateType aggType, Object aggSymbol) { if (dimPointMapping.ContainsKey(dimension)) { return(dimPointMapping[dimension]); } int count = 0; TimeSeriesPoint p = new TimeSeriesPoint(dimension); DimensionInfo dimensionInfo = SeparateDimension(dimension, aggSymbol); Dictionary <string, Object> subDim = GetSubDim(dimension, dimensionInfo.DetailDims); foreach (TimeSeriesPoint leave in pointTree.Leaves) { if (ContainsAll(leave.Dimension, subDim)) { count++; p.Value = +leave.Value; p.ExpectedValue = +leave.ExpectedValue; p.Delta = +leave.Delta; } } if (aggType.Equals(AggregateType.Avg)) { p.Value = p.Value / count; p.ExpectedValue = p.ExpectedValue / count; p.Delta = p.Delta / count; } if (count > 0) { return(p); } else { return(null); } }
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); } }