private void Aggregate(ref AggregatedAlert?aggregatedAlert, StatusNotificationWriter writer, DateTime start, StatusResultsOrganizer child, float ignoreRatingsBetterThan) { // does this child have children? if (child.ChildrenCount > 0) { System.Diagnostics.Debug.Assert(child.NatureOfSystem == StatusNatureOfSystem.ChildrenIrrelevant || child.ChildrenCount > 1); // recurse for this level too RenderTargetedResults(writer, start, child, ignoreRatingsBetterThan); } else { // can we aggregate this one? if (aggregatedAlert != null && aggregatedAlert.CanBeAggregated(child.Target, child.OverallReport)) { aggregatedAlert.Aggregate(child.Source, child.Target, child.MostRecentTime, child.OverallReport); } else // this one can't be aggregated with previous ones, so we need to flush the previously-aggregated alerts and start a new aggregation { if (aggregatedAlert != null) { writer.WriteAggregatedAlert(aggregatedAlert); } aggregatedAlert = new AggregatedAlert(child.Source, child.Target, child.MostRecentTime, child.OverallReport); } } }
} // string.IsNullOrEmpty ensures response is not null /// <summary> /// Computes a summary status report based on <see cref="Properties"/>, <see cref="NatureOfSystem"/>, and <see cref="Children"/>, when a node-level report is not available. /// </summary> /// <param name="includeHtmlTag">Whether or not to include the html and body tags.</param> /// <param name="ignoreRatingsBetterThan">A value indicating which reports to completely ignore.</param> /// <param name="ignorePendingRatings">Whether or not to ignore pending ratings.</param> /// <param name="notificationTimeZone">An optional <see cref="TimeZoneInfo"/> that will be used to convert the notification time. If not specified, UTC will be used.</param> /// <returns>A <see cref="StatusAuditAlert"/> summarizing the overall state of the system.</returns> public StatusAuditAlert GetSummaryAlerts(bool includeHtmlTag, float ignoreRatingsBetterThan, bool ignorePendingRatings, TimeZoneInfo?notificationTimeZone = null) { DateTime start = AmbientClock.UtcNow; StatusResultsOrganizer organized = new StatusResultsOrganizer(this); organized.ComputeOverallRatingAndSort(); DateTime notificationTime = TimeZoneInfo.ConvertTimeFromUtc(organized.MostRecentTime, notificationTimeZone ?? TimeZoneInfo.Utc); StatusNotificationWriter writer = new StatusNotificationWriter(notificationTime); // build HTML style and header for the indicated rating and rating range float overallRating = organized.SortRating; if (includeHtmlTag) { writer.EnterHtmlAndBody(overallRating); } writer.EnterStatusRange(overallRating); StatusRatingRange ratingRange = StatusRating.FindRange(overallRating); // filter irrelevant top-level reports AggregatedAlert?aggregatedAlert = null; foreach (StatusResultsOrganizer child in organized.Children) { // use the specified child rating, or okay if one is not specified float childRating = child.SortRating; // is this one better than the cutoff? stop now because all the subsequent reports are better than this one! (because they're sorted by rating) if (childRating > ignoreRatingsBetterThan || (ignorePendingRatings && float.IsNaN(childRating))) { break; } StatusRatingRange childRatingRange = StatusRating.FindRange(childRating); if (childRatingRange != ratingRange) { if (aggregatedAlert != null) { writer.WriteAggregatedAlert(aggregatedAlert); aggregatedAlert = null; } writer.LeaveStatusRange(); writer.EnterStatusRange(childRating); ratingRange = childRatingRange; } Aggregate(ref aggregatedAlert, writer, start, child, ignoreRatingsBetterThan); } if (aggregatedAlert != null) { writer.WriteAggregatedAlert(aggregatedAlert); aggregatedAlert = null; } writer.LeaveStatusRange(); if (includeHtmlTag) { writer.LeaveBodyAndHtml(); } StatusAuditAlert alert = new StatusAuditAlert(overallRating, string.Empty, writer.Terse, writer.Details); return(alert); }
private void RenderTargetedResults(StatusNotificationWriter writer, DateTime start, StatusResultsOrganizer results, float ignoreRatingsBetterThan) { float rating = results.SortRating; writer.EnterTarget(results.Target, rating); AggregatedAlert?aggregatedAlert = null; foreach (StatusResultsOrganizer child in results.Children) { // is this one better than the cutoff? stop now because all the subsequent reports are better than this one! if (child.OverallRating > ignoreRatingsBetterThan) { break; } Aggregate(ref aggregatedAlert, writer, start, child, ignoreRatingsBetterThan); } if (aggregatedAlert != null) { writer.WriteAggregatedAlert(aggregatedAlert); } writer.LeaveTarget(); }