fix(ops): 收紧运维邮件 fallback 和去重
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
3fdd5cbaef
commit
a6bb6d481b
@ -686,6 +686,21 @@ func (s *OpsAlertEvaluatorService) maybeSendAlertEmail(ctx context.Context, runt
|
||||
if !s.emailLimiter.Allow(time.Now().UTC()) {
|
||||
continue
|
||||
}
|
||||
if s.emailService.notificationEmailService != nil {
|
||||
if err := s.emailService.notificationEmailService.Send(ctx, NotificationEmailSendInput{
|
||||
Event: NotificationEmailEventOpsAlert,
|
||||
RecipientEmail: addr,
|
||||
RecipientName: emailRecipientName(addr),
|
||||
SourceType: "ops_alert",
|
||||
SourceID: fmt.Sprintf("%d", event.ID),
|
||||
Variables: opsAlertEmailVariables(rule, event),
|
||||
}); err == nil {
|
||||
anySent = true
|
||||
continue
|
||||
} else if !shouldFallbackNotificationEmail(err) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err := s.emailService.SendEmail(ctx, addr, subject, body); err != nil {
|
||||
// Ignore per-recipient failures; continue best-effort.
|
||||
continue
|
||||
@ -699,6 +714,46 @@ func (s *OpsAlertEvaluatorService) maybeSendAlertEmail(ctx context.Context, runt
|
||||
return anySent
|
||||
}
|
||||
|
||||
func opsAlertEmailVariables(rule *OpsAlertRule, event *OpsAlertEvent) map[string]string {
|
||||
variables := map[string]string{
|
||||
"rule_name": "-",
|
||||
"severity": "-",
|
||||
"alert_status": "-",
|
||||
"metric_type": "-",
|
||||
"operator": "-",
|
||||
"metric_value": "-",
|
||||
"threshold_value": "-",
|
||||
"triggered_at": time.Now().UTC().Format(time.RFC3339),
|
||||
"alert_description": "-",
|
||||
}
|
||||
if rule != nil {
|
||||
variables["rule_name"] = strings.TrimSpace(rule.Name)
|
||||
variables["severity"] = strings.TrimSpace(rule.Severity)
|
||||
variables["metric_type"] = strings.TrimSpace(rule.MetricType)
|
||||
variables["operator"] = strings.TrimSpace(rule.Operator)
|
||||
variables["threshold_value"] = fmt.Sprintf("%.2f", rule.Threshold)
|
||||
if strings.TrimSpace(rule.Description) != "" {
|
||||
variables["alert_description"] = strings.TrimSpace(rule.Description)
|
||||
}
|
||||
}
|
||||
if event != nil {
|
||||
variables["alert_status"] = strings.TrimSpace(event.Status)
|
||||
if event.MetricValue != nil {
|
||||
variables["metric_value"] = fmt.Sprintf("%.2f", *event.MetricValue)
|
||||
}
|
||||
if event.ThresholdValue != nil {
|
||||
variables["threshold_value"] = fmt.Sprintf("%.2f", *event.ThresholdValue)
|
||||
}
|
||||
if !event.FiredAt.IsZero() {
|
||||
variables["triggered_at"] = event.FiredAt.UTC().Format(time.RFC3339)
|
||||
}
|
||||
if strings.TrimSpace(event.Description) != "" {
|
||||
variables["alert_description"] = strings.TrimSpace(event.Description)
|
||||
}
|
||||
}
|
||||
return variables
|
||||
}
|
||||
|
||||
func buildOpsAlertEmailBody(rule *OpsAlertRule, event *OpsAlertEvent) string {
|
||||
if rule == nil || event == nil {
|
||||
return ""
|
||||
|
||||
@ -337,6 +337,7 @@ func (s *OpsScheduledReportService) runReport(ctx context.Context, report *opsSc
|
||||
}
|
||||
|
||||
subject := fmt.Sprintf("[Ops Report] %s", strings.TrimSpace(report.Name))
|
||||
templateVariables := opsScheduledReportEmailVariables(report, now)
|
||||
|
||||
attempts := 0
|
||||
for _, to := range recipients {
|
||||
@ -345,6 +346,24 @@ func (s *OpsScheduledReportService) runReport(ctx context.Context, report *opsSc
|
||||
continue
|
||||
}
|
||||
attempts++
|
||||
if s.emailService.notificationEmailService != nil {
|
||||
if err := s.emailService.notificationEmailService.Send(ctx, NotificationEmailSendInput{
|
||||
Event: NotificationEmailEventOpsScheduledReport,
|
||||
RecipientEmail: addr,
|
||||
RecipientName: emailRecipientName(addr),
|
||||
SourceType: "ops_scheduled_report",
|
||||
SourceID: opsScheduledReportDeliverySourceID(report),
|
||||
ReminderKey: now.UTC().Format("2006-01-02T15:04"),
|
||||
Variables: templateVariables,
|
||||
RawHTMLVariables: map[string]string{
|
||||
"report_html": content,
|
||||
},
|
||||
}); err == nil {
|
||||
continue
|
||||
} else if !shouldFallbackNotificationEmail(err) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err := s.emailService.SendEmail(ctx, addr, subject, content); err != nil {
|
||||
// Ignore per-recipient failures; continue best-effort.
|
||||
continue
|
||||
@ -353,6 +372,46 @@ func (s *OpsScheduledReportService) runReport(ctx context.Context, report *opsSc
|
||||
return attempts, nil
|
||||
}
|
||||
|
||||
func opsScheduledReportDeliverySourceID(report *opsScheduledReport) string {
|
||||
if report == nil {
|
||||
return "scheduled_report"
|
||||
}
|
||||
parts := []string{
|
||||
strings.TrimSpace(report.ReportType),
|
||||
strings.TrimSpace(report.Name),
|
||||
strings.TrimSpace(report.Schedule),
|
||||
}
|
||||
joined := strings.Trim(strings.Join(parts, ":"), ":")
|
||||
if joined == "" {
|
||||
return "scheduled_report"
|
||||
}
|
||||
return joined
|
||||
}
|
||||
|
||||
func opsScheduledReportEmailVariables(report *opsScheduledReport, now time.Time) map[string]string {
|
||||
end := now.UTC()
|
||||
start := end
|
||||
name := "Ops report"
|
||||
reportType := "scheduled_report"
|
||||
if report != nil {
|
||||
if strings.TrimSpace(report.Name) != "" {
|
||||
name = strings.TrimSpace(report.Name)
|
||||
}
|
||||
if strings.TrimSpace(report.ReportType) != "" {
|
||||
reportType = strings.TrimSpace(report.ReportType)
|
||||
}
|
||||
if report.TimeRange > 0 {
|
||||
start = end.Add(-report.TimeRange)
|
||||
}
|
||||
}
|
||||
return map[string]string{
|
||||
"report_name": name,
|
||||
"report_type": reportType,
|
||||
"report_start_time": start.Format(time.RFC3339),
|
||||
"report_end_time": end.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OpsScheduledReportService) generateReportHTML(ctx context.Context, report *opsScheduledReport, now time.Time) (string, error) {
|
||||
if s == nil || s.opsService == nil || report == nil {
|
||||
return "", fmt.Errorf("service not initialized")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user