搭建消息告警模块以及跨网推送服务,支持企微,飞书,钉钉通知
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
using Model;
|
||||
using Model.Dto.Inspection;
|
||||
using Model.Entity.Inspection;
|
||||
using Model.Mapper;
|
||||
using ORM;
|
||||
using Service.Interface;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Service.Implement
|
||||
{
|
||||
/// <summary>
|
||||
/// 告警中心服务实现(全系统统一告警上报入口)
|
||||
/// 职责:默认内容生成 → 去重合并(防告警风暴)→ 落库 → 规则触发计数 → 通知队列入队
|
||||
/// </summary>
|
||||
public class AlertCenterService : IAlertCenterService
|
||||
{
|
||||
/// <summary>
|
||||
/// 合并窗口(分钟):窗口内同设备+同测点+同类型的活跃告警不新建记录,只累加触发次数。
|
||||
/// 后续可迁移到系统参数配置模块动态调整
|
||||
/// </summary>
|
||||
private const int MergeWindowMinutes = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 上报一条告警
|
||||
/// </summary>
|
||||
public async Task<Result<string>> RaiseAsync(AlertRaiseDto dto)
|
||||
{
|
||||
if (dto == null)
|
||||
{
|
||||
return Result<string>.Error("告警上报参数为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(dto.DeviceCode) && string.IsNullOrWhiteSpace(dto.Content))
|
||||
{
|
||||
return Result<string>.Error("设备编号与告警内容不能同时为空");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
// ===== 去重合并:窗口内相同 设备+测点+类型 的活跃告警(未确认/已确认)只累加不新建 =====
|
||||
var active = await SqlSugarContext.DbContext.Queryable<AlertMessageEntity>()
|
||||
.Where(x => x.IsDel == 0)
|
||||
.Where(x => x.DeviceCode == dto.DeviceCode && x.Metric == dto.Metric && x.AlertType == dto.AlertType)
|
||||
.Where(x => x.AlertStatus == AlertStatusEnum.Unacknowledged || x.AlertStatus == AlertStatusEnum.Acknowledged)
|
||||
.Where(x => x.LastAlertTime >= now.AddMinutes(-MergeWindowMinutes))
|
||||
.FirstAsync();
|
||||
|
||||
if (active != null)
|
||||
{
|
||||
// 累加触发次数、刷新最近告警时间与当前值;级别取更高者(告警升级)
|
||||
var mergedLevel = active.AlertLevel > dto.AlertLevel ? active.AlertLevel : dto.AlertLevel;
|
||||
await SqlSugarContext.DbContext.Updateable<AlertMessageEntity>()
|
||||
.SetColumns(x => new AlertMessageEntity
|
||||
{
|
||||
TriggerCount = x.TriggerCount + 1,
|
||||
LastAlertTime = now,
|
||||
CurrentValue = dto.CurrentValue ?? x.CurrentValue,
|
||||
AlertLevel = mergedLevel
|
||||
})
|
||||
.Where(x => x.Id == active.Id)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
// 合并告警也入队(是否真正推送由 Worker 按通知规则静默期决定)
|
||||
AlertNotifyBus.Publish(active.Id, false);
|
||||
return Result<string>.Success(active.Id.ToString());
|
||||
}
|
||||
|
||||
// ===== 新告警:生成默认内容 → 落库 → 规则计数 → 入队 =====
|
||||
var entity = dto.ToEntity();
|
||||
if (string.IsNullOrWhiteSpace(entity.Content))
|
||||
{
|
||||
entity.Content = BuildDefaultContent(entity);
|
||||
}
|
||||
entity.CreateTime = now;
|
||||
entity.FirstAlertTime = now;
|
||||
entity.LastAlertTime = now;
|
||||
entity.TriggerCount = 1;
|
||||
entity.AlertStatus = AlertStatusEnum.Unacknowledged;
|
||||
|
||||
await SqlSugarContext.DbContext.Insertable(entity).ExecuteCommandAsync();
|
||||
|
||||
// 来源为规则引擎时,回写规则触发统计(与黄的规则引擎模块联动)
|
||||
if (entity.RuleId > 0)
|
||||
{
|
||||
await SqlSugarContext.DbContext.Updateable<AlertRuleEntity>()
|
||||
.SetColumns(x => new AlertRuleEntity { TriggerCount = x.TriggerCount + 1, LastAlarmTime = now })
|
||||
.Where(x => x.Id == entity.RuleId)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
AlertNotifyBus.Publish(entity.Id, true);
|
||||
return Result<string>.Success(entity.Id.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<string>.Error("告警上报失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按内置模板生成默认告警内容(后续可由通知模板模块接管,见 TemplateCode 预留字段)
|
||||
/// </summary>
|
||||
private static string BuildDefaultContent(AlertMessageEntity e)
|
||||
{
|
||||
string device = string.IsNullOrWhiteSpace(e.DeviceName) ? e.DeviceCode ?? "未知设备" : $"{e.DeviceName}({e.DeviceCode})";
|
||||
string metric = string.IsNullOrWhiteSpace(e.Metric) ? "" : $" 测点[{e.Metric}]";
|
||||
string value = e.CurrentValue.HasValue ? $" 当前值 {e.CurrentValue.Value}" : "";
|
||||
string threshold = e.ThresholdValue.HasValue ? $",阈值 {e.ThresholdValue.Value}" : "";
|
||||
return $"{device}{metric} 触发告警:{value}{threshold}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user