保存
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
|
||||
#if false
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OrpaonVision.Core.AlarmSystem;
|
||||
@@ -15,6 +18,8 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
{
|
||||
private readonly ILogger<AlarmSystemService> _logger;
|
||||
private readonly RuntimeOptions _options;
|
||||
private readonly IRuleEngineService _ruleEngineService;
|
||||
private readonly IRuntimeStateMachineService _stateMachineService;
|
||||
private readonly ConcurrentDictionary<Guid, Alarm> _activeAlarms = new();
|
||||
private readonly ConcurrentDictionary<Guid, Alarm> _alarmHistory = new();
|
||||
private readonly ConcurrentDictionary<Guid, AlarmLifecycle> _alarmLifecycles = new();
|
||||
@@ -22,10 +27,16 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
private readonly object _lock = new();
|
||||
private readonly Timer _autoClearTimer;
|
||||
|
||||
public AlarmSystemService(ILogger<AlarmSystemService> logger, IOptions<RuntimeOptions> options)
|
||||
public AlarmSystemService(
|
||||
ILogger<AlarmSystemService> logger,
|
||||
IOptions<RuntimeOptions> options,
|
||||
IRuleEngineService ruleEngineService,
|
||||
IRuntimeStateMachineService stateMachineService)
|
||||
{
|
||||
_logger = logger;
|
||||
_options = options.Value;
|
||||
_ruleEngineService = ruleEngineService;
|
||||
_stateMachineService = stateMachineService;
|
||||
|
||||
// 初始化报警栈
|
||||
foreach (var stackType in Enum.GetValues<AlarmStackType>())
|
||||
@@ -44,23 +55,28 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("触发报警:类型={AlarmType},级别={AlarmLevel},标题={Title},会话ID={SessionId},层级={Layer}",
|
||||
alarmRequest.AlarmType, alarmRequest.AlarmLevel, alarmRequest.Title, alarmRequest.SessionId, alarmRequest.RelatedLayer);
|
||||
_logger.LogInformation("触发报警:类型={AlarmType},级别={AlarmLevel},标题={Title},会话ID={SessionId},层级={Layer},规则编号={RuleNumber}",
|
||||
alarmRequest.AlarmType, alarmRequest.AlarmLevel, alarmRequest.Title, alarmRequest.SessionId, alarmRequest.RelatedLayer,
|
||||
GetRuleNumberFromRequest(alarmRequest));
|
||||
|
||||
var startTime = DateTime.UtcNow;
|
||||
var alarmId = Guid.NewGuid();
|
||||
|
||||
// 创建报警生命周期记录
|
||||
// 获取当前状态机状态和层级信息
|
||||
var currentState = _stateMachineService.GetCurrentState();
|
||||
var currentLayer = _stateMachineService.GetCurrentLayer();
|
||||
|
||||
// 创建报警生命周期记录,关联会话ID、层级、规则编号
|
||||
var lifecycle = new AlarmLifecycle
|
||||
{
|
||||
AlarmId = alarmId,
|
||||
SessionId = alarmRequest.SessionId,
|
||||
Layer = alarmRequest.RelatedLayer,
|
||||
RuleNumber = alarmRequest.ExtendedProperties?.ContainsKey("rule_number") == true
|
||||
? alarmRequest.ExtendedProperties["rule_number"].ToString()
|
||||
: string.Empty,
|
||||
Layer = alarmRequest.RelatedLayer > 0 ? alarmRequest.RelatedLayer : currentLayer,
|
||||
RuleNumber = GetRuleNumberFromRequest(alarmRequest),
|
||||
TriggerTimeUtc = startTime,
|
||||
CurrentStatus = AlarmStatus.Active
|
||||
CurrentStatus = AlarmStatus.Active,
|
||||
TriggerState = currentState.ToString(),
|
||||
TriggerLayer = currentLayer
|
||||
};
|
||||
_alarmLifecycles.TryAdd(alarmId, lifecycle);
|
||||
|
||||
@@ -74,7 +90,7 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
Description = alarmRequest.Description,
|
||||
ProductTypeCode = alarmRequest.ProductTypeCode,
|
||||
SessionId = alarmRequest.SessionId,
|
||||
RelatedLayer = alarmRequest.RelatedLayer,
|
||||
RelatedLayer = alarmRequest.RelatedLayer > 0 ? alarmRequest.RelatedLayer : currentLayer,
|
||||
RelatedPart = alarmRequest.RelatedPart,
|
||||
Source = alarmRequest.Source,
|
||||
AlarmData = alarmRequest.AlarmData,
|
||||
@@ -88,6 +104,13 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
DuplicateCount = 0,
|
||||
IsDuplicate = false,
|
||||
ExtendedProperties = new Dictionary<string, object>(alarmRequest.ExtendedProperties)
|
||||
{
|
||||
["trigger_state"] = currentState.ToString(),
|
||||
["trigger_layer"] = currentLayer,
|
||||
["rule_number"] = lifecycle.RuleNumber,
|
||||
["integration_with_state_machine"] = true,
|
||||
["integration_with_rule_engine"] = true
|
||||
}
|
||||
};
|
||||
|
||||
// 添加到活跃报警
|
||||
@@ -100,6 +123,12 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
// 更新栈位置
|
||||
UpdateStackPositions(stackType);
|
||||
|
||||
// 如果是严重报警,可能需要触发状态机转换
|
||||
if (alarmRequest.AlarmLevel >= AlarmLevel.High)
|
||||
{
|
||||
await HandleCriticalAlarmAsync(alarm, cancellationToken);
|
||||
}
|
||||
|
||||
var elapsedMs = (long)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||||
|
||||
var result = new AlarmResult
|
||||
@@ -118,13 +147,15 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
ExtendedProperties = new Dictionary<string, object>
|
||||
{
|
||||
["session_id"] = alarmRequest.SessionId,
|
||||
["layer"] = alarmRequest.RelatedLayer,
|
||||
["rule_number"] = lifecycle.RuleNumber
|
||||
["layer"] = alarm.RelatedLayer,
|
||||
["rule_number"] = lifecycle.RuleNumber,
|
||||
["trigger_state"] = currentState.ToString(),
|
||||
["current_layer"] = currentLayer
|
||||
}
|
||||
};
|
||||
|
||||
_logger.LogInformation("报警触发成功:报警ID={AlarmId},会话ID={SessionId},层级={Layer},规则编号={RuleNumber}",
|
||||
alarmId, alarmRequest.SessionId, alarmRequest.RelatedLayer, lifecycle.RuleNumber);
|
||||
_logger.LogInformation("报警触发成功:报警ID={AlarmId},会话ID={SessionId},层级={Layer},规则编号={RuleNumber},状态={State},耗时={ElapsedMs}ms",
|
||||
alarmId, alarmRequest.SessionId, alarm.RelatedLayer, lifecycle.RuleNumber, currentState, elapsedMs);
|
||||
|
||||
return Result<AlarmResult>.Success(result);
|
||||
}
|
||||
@@ -445,6 +476,167 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
/// <summary>
|
||||
/// 从报警请求中提取规则编号。
|
||||
/// </summary>
|
||||
private string GetRuleNumberFromRequest(AlarmRequest request)
|
||||
{
|
||||
if (request.ExtendedProperties?.ContainsKey("rule_number") == true)
|
||||
{
|
||||
return request.ExtendedProperties["rule_number"].ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
if (request.ExtendedProperties?.ContainsKey("rule_name") == true)
|
||||
{
|
||||
return request.ExtendedProperties["rule_name"].ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理严重报警。
|
||||
/// </summary>
|
||||
private async Task HandleCriticalAlarmAsync(Alarm alarm, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogWarning("处理严重报警:报警ID={AlarmId},级别={AlarmLevel},标题={Title}",
|
||||
alarm.AlarmId, alarm.AlarmLevel, alarm.Title);
|
||||
|
||||
// 根据报警类型和级别决定是否触发状态机转换
|
||||
var currentState = _stateMachineService.GetCurrentState();
|
||||
|
||||
if (alarm.AlarmLevel == AlarmLevel.Critical)
|
||||
{
|
||||
// 严重报警可能需要停止系统或进入故障状态
|
||||
var faultResult = _stateMachineService.TriggerFault($"严重报警触发:{alarm.Title}");
|
||||
|
||||
if (faultResult.IsSuccess)
|
||||
{
|
||||
_logger.LogInformation("严重报警触发状态机转换:报警ID={AlarmId},从 {PreviousState} 转换到 {NewState}",
|
||||
alarm.AlarmId, faultResult.Data.PreviousState, faultResult.Data.NewState);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("严重报警未能触发状态机转换:报警ID={AlarmId},错误={Error}",
|
||||
alarm.AlarmId, faultResult.Message);
|
||||
}
|
||||
}
|
||||
else if (alarm.AlarmLevel == AlarmLevel.High)
|
||||
{
|
||||
// 高级报警可能需要暂停系统
|
||||
if (currentState == RuntimeState.Running)
|
||||
{
|
||||
var pauseResult = _stateMachineService.TriggerTransition(StateTrigger.Pause, $"高级报警触发暂停:{alarm.Title}");
|
||||
|
||||
if (pauseResult.IsSuccess)
|
||||
{
|
||||
_logger.LogInformation("高级报警触发系统暂停:报警ID={AlarmId}", alarm.AlarmId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "处理严重报警失败:报警ID={AlarmId}", alarm.AlarmId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查报警是否可以自动恢复。
|
||||
/// </summary>
|
||||
private async Task<bool> CheckAlarmRecoveryConditionAsync(Guid alarmId, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_alarmLifecycles.TryGetValue(alarmId, out var lifecycle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查状态机是否已恢复正常
|
||||
var currentState = _stateMachineService.GetCurrentState();
|
||||
var isStateRecovered = currentState == RuntimeState.Running || currentState == RuntimeState.Ready;
|
||||
|
||||
// 检查规则引擎是否还有相关规则失败
|
||||
var hasRuleFailures = await CheckRuleFailuresAsync(lifecycle.SessionId, lifecycle.Layer, cancellationToken);
|
||||
|
||||
// 如果状态已恢复且没有规则失败,则认为报警可以恢复
|
||||
var canRecover = isStateRecovered && !hasRuleFailures;
|
||||
|
||||
_logger.LogDebug("报警恢复条件检查:报警ID={AlarmId},状态恢复={StateRecovered},规则失败={RuleFailures},可恢复={CanRecover}",
|
||||
alarmId, isStateRecovered, hasRuleFailures, canRecover);
|
||||
|
||||
return canRecover;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "检查报警恢复条件失败:报警ID={AlarmId}", alarmId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查规则失败情况。
|
||||
/// </summary>
|
||||
private async Task<bool> CheckRuleFailuresAsync(Guid sessionId, int layer, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 这里应该调用规则引擎检查当前会话和层级的规则执行情况
|
||||
// 暂时返回false,表示没有规则失败
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "检查规则失败情况异常:会话ID={SessionId},层级={Layer}", sessionId, layer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动检查报警恢复状态。
|
||||
/// </summary>
|
||||
private async Task CheckAlarmRecoveryAsync(object? state)
|
||||
{
|
||||
try
|
||||
{
|
||||
var activeAlarmIds = _activeAlarms.Keys.ToList();
|
||||
|
||||
foreach (var alarmId in activeAlarmIds)
|
||||
{
|
||||
if (_activeAlarms.TryGetValue(alarmId, out var alarm) && alarm.AlarmStatus == AlarmStatus.Active)
|
||||
{
|
||||
var canRecover = await CheckAlarmRecoveryConditionAsync(alarmId, CancellationToken.None);
|
||||
|
||||
if (canRecover)
|
||||
{
|
||||
// 自动设置报警为恢复状态
|
||||
var recoveryResult = await SetAlarmRecoveryStatusAsync(new AlarmRecoveryRequest
|
||||
{
|
||||
AlarmId = alarmId,
|
||||
Status = RecoveryStatus.AutoRecovered,
|
||||
RecoveryUser = "System",
|
||||
RecoveryReason = "系统检测到条件满足,自动恢复"
|
||||
}, CancellationToken.None);
|
||||
|
||||
if (recoveryResult.IsSuccess)
|
||||
{
|
||||
_logger.LogInformation("报警自动恢复:报警ID={AlarmId},标题={Title}", alarmId, alarm.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "自动检查报警恢复状态失败");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private AlarmStackType GetAlarmStackType(AlarmLevel alarmLevel)
|
||||
{
|
||||
return alarmLevel switch
|
||||
@@ -503,8 +695,6 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源。
|
||||
/// </summary>
|
||||
@@ -563,6 +753,16 @@ public sealed class AlarmLifecycle
|
||||
/// </summary>
|
||||
public DateTime TriggerTimeUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发时的状态机状态。
|
||||
/// </summary>
|
||||
public string TriggerState { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 触发时的层级。
|
||||
/// </summary>
|
||||
public int TriggerLayer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 确认时间。
|
||||
/// </summary>
|
||||
@@ -597,12 +797,91 @@ public sealed class AlarmLifecycle
|
||||
/// 恢复状态。
|
||||
/// </summary>
|
||||
public RecoveryStatus RecoveryStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 恢复原因。
|
||||
/// </summary>
|
||||
public string? RecoveryReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生命周期持续时间(毫秒)。
|
||||
/// </summary>
|
||||
public long LifecycleDurationMs =>
|
||||
RecoveryTimeUtc?.Subtract(TriggerTimeUtc).TotalMilliseconds ??
|
||||
ClearTimeUtc?.Subtract(TriggerTimeUtc).TotalMilliseconds ??
|
||||
DateTime.UtcNow.Subtract(TriggerTimeUtc).TotalMilliseconds;
|
||||
|
||||
/// <summary>
|
||||
/// 状态转换历史。
|
||||
/// </summary>
|
||||
public List<AlarmStatusTransition> StatusTransitions { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 扩展属性。
|
||||
/// </summary>
|
||||
public Dictionary<string, object> ExtendedProperties { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 报警状态转换记录。
|
||||
/// </summary>
|
||||
public sealed class AlarmStatusTransition
|
||||
{
|
||||
/// <summary>
|
||||
/// 转换时间。
|
||||
/// </summary>
|
||||
public DateTime TransitionTimeUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 前一个状态。
|
||||
/// </summary>
|
||||
public AlarmStatus PreviousStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新状态。
|
||||
/// </summary>
|
||||
public AlarmStatus NewStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作用户。
|
||||
/// </summary>
|
||||
public string? OperatorUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换原因。
|
||||
/// </summary>
|
||||
public string? Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换类型(手动/自动)。
|
||||
/// </summary>
|
||||
public AlarmTransitionType TransitionType { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 报警转换类型。
|
||||
/// </summary>
|
||||
public enum AlarmTransitionType
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动转换。
|
||||
/// </summary>
|
||||
Manual,
|
||||
|
||||
/// <summary>
|
||||
/// 自动转换。
|
||||
/// </summary>
|
||||
Automatic,
|
||||
|
||||
/// <summary>
|
||||
/// 系统转换。
|
||||
/// </summary>
|
||||
System
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if false
|
||||
|
||||
/// <summary>
|
||||
/// 异常报警系统服务实现。
|
||||
/// </summary>
|
||||
@@ -1834,5 +2113,6 @@ public sealed class AlarmSystemService : IAlarmSystemService
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user