// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Nodes; using EpicGames.Core; using Microsoft.Extensions.Logging; namespace EpicGames.Horde.Issues.Handlers { using JsonObject = System.Text.Json.Nodes.JsonObject; /// /// Handler for log events with issue fingerprints embedded in the structured log data itself /// [IssueHandler] public class ExternalIssueHandler : IssueHandler { static readonly JsonNodeOptions s_jsonNodeOptions = new JsonNodeOptions { PropertyNameCaseInsensitive = true }; static readonly JsonSerializerOptions? s_jsonSerializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; readonly List _issues = new List(); /// public override int Priority => 20; /// public override bool HandleEvent(IssueEvent issueEvent) { foreach (JsonLogEvent line in issueEvent.Lines) { IssueFingerprint? issueData = ParseIssueFingerprint(line); if (issueData != null) { IssueEventGroup group = new IssueEventGroup(issueData.Type, issueData.SummaryTemplate, issueData.ChangeFilter); if (issueData.Keys != null) { group.Keys.UnionWith(issueData.Keys); } if (issueData.Metadata != null) { group.Metadata.UnionWith(issueData.Metadata); } group.Events.Add(issueEvent); _issues.Add(group); issueEvent.AuditLogger?.LogDebug("{IssueType} issue added for event: '{Event}'", group.Type, issueEvent.Render()); return true; } } return false; } /// public override IEnumerable GetIssues() => _issues; static IssueFingerprint? ParseIssueFingerprint(JsonLogEvent line) { JsonNode? node = JsonObject.Parse(line.Data.Span, s_jsonNodeOptions); if (node != null) { JsonObject? properties = node["properties"] as JsonObject; if (properties != null) { JsonObject? issue = properties["$issue"] as JsonObject; if (issue != null) { IssueFingerprint? fingerprint = JsonSerializer.Deserialize(issue, s_jsonSerializerOptions); if (fingerprint != null) { return fingerprint; } } } } return null; } } }