/// <summary> /// Writes a notification for the specified <see cref="AggregatedAlert"/>. /// </summary> /// <param name="aggregatedAlert">An <see cref="AggregatedAlert"/> that should be written to the notification.</param> public void WriteAggregatedAlert(AggregatedAlert aggregatedAlert) { if (_tabLevel <= 1) { throw new InvalidOperationException("A status range must be entered before aggregated alerts can be written!"); } StatusAuditAlert auditAlert = aggregatedAlert.CommonAlert ?? StatusAuditAlert.None; StatusRatingRange range = StatusRating.FindRange(auditAlert.Rating); string rangeName = StatusRating.GetRangeName(range); string rangeColor = StatusRating.GetRangeForegroundColor(auditAlert.Rating); string rgbColor = StatusRating.GetRatingRgbForegroundColor(aggregatedAlert.RatingSum / aggregatedAlert.Sources.Count); List <StatusPropertyRange> propertyRanges = aggregatedAlert.PropertyRanges; OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(aggregatedAlert.Target + ": " + aggregatedAlert.TerseSources + "->"); #if RAWRATINGS _details.Append("[RATING=" + auditAlert.Rating.ToString(DebugRatingFloatFormat) + "] "); #endif _details.Append(aggregatedAlert.Target + ": " + aggregatedAlert.DetailsSources + " reporting: "); // multi-line alert details or properties to list? if ((aggregatedAlert.CommonAlert?.Details != null && (aggregatedAlert.CommonAlert.Details.Contains("<br/>", StringComparison.Ordinal) || aggregatedAlert.CommonAlert.Details.Contains("</div>", StringComparison.Ordinal))) || (propertyRanges != null && propertyRanges.Count > 0)) { CloseHeader(_details, _terse, _tabLevel); EnterTabLevel(); OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(RenderTerse(auditAlert.Terse).Replace("\n", "\n" + new string(' ', _tabLevel), StringComparison.Ordinal)); _details.AppendLine(RenderDetails(auditAlert.Details)); CloseHeader(_details, _terse, _tabLevel); // are there properties? if (propertyRanges != null && propertyRanges.Count > 0) { _details.Append(" because"); foreach (StatusPropertyRange propertyRange in aggregatedAlert.PropertyRanges) { OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(propertyRange.ToString()); _details.AppendLine(propertyRange.ToString()); CloseHeader(_details, _terse, _tabLevel); } } LeaveTabLevel(); } else { _terse.Append(RenderTerse(auditAlert.Terse)); _details.Append(' '); _details.Append(RenderDetails(auditAlert.Details)); CloseHeader(_details, _terse, _tabLevel); } }
/// <summary> /// Enters a target section. Should be matched by a subsequent call to <see cref="LeaveTarget"/>. /// </summary> /// <param name="target">The name of the target owning this section.</param> /// <param name="rating">The overall status rating for this target.</param> public void EnterTarget(string target, float rating) { if (_tabLevel < 2) { throw new InvalidOperationException("A status range must be entered before a target is!"); } string rgbColor = StatusRating.GetRatingRgbForegroundColor(rating); StatusRatingRange range = StatusRating.FindRange(rating); OpenHeader(_details, _terse, _tabLevel, (StatusRatingRange)(-1), rgbColor); _terse.Append(target); _details.Append(target); CloseHeader(_details, _terse, _tabLevel); EnterTabLevel(); }