private void SendAlertSignalEmail(InternalSignal signal, NamedValueSet props) { try { var smtpHost = props.GetValue <string>(AlertRule.MailHost); IEnumerable <string> recipients = ResolveMultipleEmailAddresses(props.GetArray <string>(AlertRule.MailTo)); string sender = ResolveSingleEmailAddress(props.GetValue <string>(AlertRule.MailFrom)); var email = new MailMessage(); string instanceMsg = GetInstanceMsg(signal.ReminderCount); signal.ReminderCount += 1; email.Subject = $"QDS Alert {EnvHelper.EnvName(IntClient.Target.ClientInfo.ConfigEnv)}. {signal.RuleName}: {signal.Status}"; if (signal.Status == AlertStatus.Alerted) { email.Subject += $"({instanceMsg})"; } var body = new StringBuilder(signal.SignalMessage); if (props.GetValue <bool>("rule.DebugEnabled", false)) { body.AppendLine(); body.AppendLine(); body.AppendLine("[debug-begin]"); props.LogValues(text => body.AppendLine(" " + text)); body.AppendLine("[debug-end]"); } email.Body = body.ToString(); SendEmail(smtpHost, email, sender, recipients); } catch (Exception excp) { ReportUncaughtError("EmailAlertSignal", signal.RuleName, excp, props); } }
protected override void OnCloseCallback() { try { // server shutting down // - publish all rule status as Undefined DateTimeOffset now = DateTimeOffset.Now; foreach (InternalRule rule in _ruleStore.Values) { try { var signal = new InternalSignal { RuleName = rule.RuleName, AlertServer = IntClient.Target.ClientInfo.HostName, Status = AlertStatus.Undefined, LastMonitored = now, SignalMessage = "AlertServer shutdown" }; PublishAlertSignal(signal); } catch (Exception ex) { ReportUncaughtError("OnCloseCallback", rule.RuleName, ex, null); } } // foreach rule } catch (Exception ex) { ReportUncaughtError("OnCloseCallback", null, ex, null); } }
private void PublishAlertSignal(InternalSignal signal) { AlertSignal item = signal.AsAlertSignal(); IntClient.Target.SaveObject(item, item.ItemName, item.ItemProps, TimeSpan.MaxValue); }
private void ProcessAllRules() { // note: no locks required - as we are inside main Dispatcher try { // publish latest rule status DateTimeOffset asAtTime = DateTimeOffset.Now; foreach (InternalRule rule in _ruleStore.Values) { var props = new NamedValueSet(); try { if ((rule.LastMonitored + rule.MonitorPeriod) < asAtTime) { // update LastMonitored first to prevent infinite looping // when there are repeated expression evaluation exceptions rule.LastMonitored = asAtTime; // build property set string smtpServer = rule.Properties.GetString(AlertRule.MailHost, null) ?? _defaultSmtpServer; string mailFrom = rule.Properties.GetString(AlertRule.MailFrom, null) ?? _defaultMailFrom; string[] recipients = rule.Properties.GetArray <string>(AlertRule.MailTo) ?? _defaultMailTo; props.Set(AlertRule.MailHost, smtpServer); props.Set(AlertRule.MailFrom, mailFrom); props.Set(AlertRule.MailTo, recipients); props.Set("host.AsAtTime", asAtTime); props.Set("host.HostName", IntClient.Target.ClientInfo.HostName); props.Set("rule.DebugEnabled", rule.Properties.GetValue <bool>("DebugEnabled", false)); props.Set("rule.RuleName", rule.RuleName); props.Set("rule.Disabled", rule.Disabled); props.Set("rule.DataSubsExpr", rule.DataSubsExpr.DisplayString()); props.Set("rule.Constraint", rule.Constraint.DisplayString()); props.Set("rule.Condition", rule.Condition.DisplayString()); props.Set("rule.MonitorPeriod", rule.MonitorPeriod); props.Add(rule.Properties); if (rule.CurrentReceivedItem != null) { props.Add(rule.CurrentReceivedItem.AppProps); props.Set("item.IsNotNull", true); } else { // no item received props.Set("item.IsNotNull", false); } AlertStatus newStatus; string statusMessage; var signal = new InternalSignal { RuleName = rule.RuleName, AlertServer = IntClient.Target.ClientInfo.HostName }; if (rule.Disabled) { newStatus = AlertStatus.Disabled; statusMessage = "the rule is disabled"; } else { // extend constraint ICoreItem item = rule.CurrentReceivedItem; object constraint = (item == null) ? rule.Constraint.Evaluate(props, null, DateTimeOffset.MinValue, DateTimeOffset.MinValue, asAtTime) : rule.Constraint.Evaluate(props, item.Name, item.Created, item.Expires, asAtTime); if (Expr.CastTo(constraint, false)) { object condition = item == null ? rule.Condition.Evaluate(props, null, DateTimeOffset.MinValue, DateTimeOffset.MinValue, asAtTime) : rule.Condition.Evaluate(props, item.Name, item.Created, item.Expires, asAtTime); if (Expr.CastTo(condition, false)) { newStatus = AlertStatus.Alerted; statusMessage = rule.SignalFormat; } else { newStatus = AlertStatus.AllClear; statusMessage = "the condition is no longer active"; } } else { newStatus = AlertStatus.Inactive; statusMessage = "the constraint is no longer satisfied"; } } props.Set("rule.Status", newStatus.ToString()); signal.Status = newStatus; signal.LastMonitored = asAtTime; signal.ReminderCount = 0; if (rule.LastSignal != null) { signal.ReminderCount = rule.LastSignal.ReminderCount; } if (newStatus == AlertStatus.Alerted) { signal.SignalMessage = props.ReplaceTokens(statusMessage); } else { signal.SignalMessage = $"The previous alert message sent from this server ({signal.AlertServer}) " + $"for this rule ({signal.RuleName}) has been withdrawn because {statusMessage}."; } // set instance (repeat) count if (newStatus != rule.LastStatus) { signal.ReminderCount = 0; } if ((newStatus != rule.LastStatus) || ((rule.LastPublished + rule.PublishPeriod) < asAtTime)) { rule.LastPublished = asAtTime; // publish signal PublishAlertSignal(signal); // email signal if status is or was alerted if ((newStatus == AlertStatus.Alerted) || (rule.LastStatus == AlertStatus.Alerted)) { Logger.LogInfo( "Rule '{0}' {1}: {2}", signal.RuleName, signal.Status, signal.SignalMessage); SendAlertSignalEmail(signal, props); } } // done rule.LastStatus = newStatus; rule.LastSignal = signal; } } catch (Exception ex) { ReportUncaughtError("MainCallback", rule.RuleName, ex, props); } } // foreach rule } catch (Exception ex) { ReportUncaughtError("MainCallback", null, ex, null); } }