// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using EpicGames.Core; using Microsoft.Extensions.Logging; namespace EpicGames.Horde.Issues.Handlers { /// /// Instance of a particular systemic error /// [IssueHandler] public class SystemicIssueHandler : IssueHandler { /// /// Known systemic errors /// static readonly HashSet s_knownSystemic = new HashSet { KnownLogEvents.Horde, KnownLogEvents.Horde_InvalidPreflight }; /// public override int Priority => 10; /// /// Determines if the given event id matches /// /// The event id to compare /// True if the given event id matches public static bool IsMatchingEventId(EventId eventId) { return s_knownSystemic.Contains(eventId) || (eventId.Id >= KnownLogEvents.Systemic.Id && eventId.Id <= KnownLogEvents.Systemic_Max.Id); } bool _nonSystemicError = false; readonly IssueHandlerContext _context; readonly List _issues = new List(); /// /// Constructor /// public SystemicIssueHandler(IssueHandlerContext context) => _context = context; /// public override bool HandleEvent(IssueEvent logEvent) { if (logEvent.EventId != null) { if (IsMatchingEventId(logEvent.EventId.Value)) { if (_nonSystemicError) { return true; } else { IssueEventGroup issue = new IssueEventGroup("Systemic", "Systemic {Severity} in {Nodes}", IssueChangeFilter.None); issue.Keys.Add(IssueKey.FromStep(_context.StreamId, _context.TemplateId, _context.NodeName)); issue.Events.Add(logEvent); _issues.Add(issue); logEvent.AuditLogger?.LogDebug("Fingerprint key: '{Key}' generated from event: '{Event}'", $"{_context.StreamId}:{_context.NodeName}", logEvent.Render()); return true; } } else if (logEvent.Severity >= LogLevel.Error) { // We've seen a non-systemic error event, so ignore this systemic event to prevent superfluous issues from being created _nonSystemicError = true; } } return false; } /// public override IEnumerable GetIssues() => _issues; } }