// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using EpicGames.Core;
namespace EpicGames.Horde.Issues.Handlers
{
///
/// Instance of a particular compile error
///
[IssueHandler(Tag = "Scoped")]
public class ScopedIssueHandler : IssueHandler
{
const string NodeName = "Node";
const string ScopeName = "Scope";
readonly IssueHandlerContext _context;
readonly List _issues = new List();
///
public override int Priority => 2;
///
/// Constructor
///
public ScopedIssueHandler(IssueHandlerContext context) => _context = context;
///
public override bool HandleEvent(IssueEvent logEvent)
{
string? scope = null;
foreach (JsonLogEvent line in logEvent.Lines)
{
JsonDocument document = JsonDocument.Parse(line.Data);
string? channelType;
string? channelText;
if (document.RootElement.TryGetNestedProperty("properties.channel.$type", out channelType) && document.RootElement.TryGetNestedProperty("properties.channel.$text", out channelText))
{
if (channelType != "Channel" || !channelText.StartsWith("Log", StringComparison.Ordinal))
{
scope = null;
break;
}
if (scope != null && scope != channelText)
{
scope = null;
break;
}
scope = channelText;
}
}
if (scope == null)
{
return false;
}
string fingerprintType = $"Scoped:{scope}";
string hashSource = logEvent.Render();
if (TryGetHash(hashSource, out Md5Hash hash))
{
IssueEventGroup issue = new IssueEventGroup(fingerprintType, "{Severity} in {Meta:Node} - {Meta:Scope}", IssueChangeFilter.All);
issue.Events.Add(logEvent);
issue.Keys.Add(IssueKey.FromHash(hash));
issue.Metadata.Add(NodeName, _context.NodeName);
issue.Metadata.Add(ScopeName, scope);
_issues.Add(issue);
return true;
}
return false;
}
///
public override IEnumerable GetIssues() => _issues;
static bool TryGetHash(string message, out Md5Hash hash)
{
string sanitized = message.ToUpperInvariant();
sanitized = Regex.Replace(sanitized, @"(?