This repository has been archived by the owner on Jul 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
[Availability] Update StatusAggregator to support new AI availability test alerts #778
Merged
Merged
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
be352de
add ai availability alert parsing
73b7cd1
add tests
b86c26c
improve parsing unit tests
b480b73
Merge branch 'dev' of https://github.com/NuGet/NuGet.Jobs into sb-aia…
331bc0b
add AI parsing handler to DI
e0d5d39
fix message change event processor when path does not exist
0e9f648
fix unit tests
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
src/StatusAggregator/Parse/AIAvailabilityIncidentRegexParsingHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Text.RegularExpressions; | ||
using Microsoft.Extensions.Logging; | ||
using NuGet.Services.Incidents; | ||
using NuGet.Services.Status; | ||
|
||
namespace StatusAggregator.Parse | ||
{ | ||
public class AIAvailabilityIncidentRegexParsingHandler : EnvironmentPrefixIncidentRegexParsingHandler | ||
{ | ||
public const string TestGroupName = "Test"; | ||
public const string AffectedComponentPathGroupName = "AffectedComponentPath"; | ||
private static string SubtitleRegEx = $@"AI Availability test '(?<{TestGroupName}>.+)' is failing!( \((?<{AffectedComponentPathGroupName}>.+)\))?"; | ||
|
||
private readonly ILogger<AIAvailabilityIncidentRegexParsingHandler> _logger; | ||
|
||
public AIAvailabilityIncidentRegexParsingHandler( | ||
IEnumerable<IIncidentRegexParsingFilter> filters, | ||
ILogger<AIAvailabilityIncidentRegexParsingHandler> logger) | ||
: base(SubtitleRegEx, filters) | ||
{ | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
} | ||
|
||
public override bool TryParseAffectedComponentPath(Incident incident, GroupCollection groups, out string affectedComponentPath) | ||
{ | ||
var test = groups[TestGroupName].Value; | ||
affectedComponentPath = groups[AffectedComponentPathGroupName].Value; | ||
var environment = groups[EnvironmentRegexParsingFilter.EnvironmentGroupName].Value; | ||
_logger.LogInformation("Test is named {Test} and affects {AffectedComponentPath} in the {Environment} environment.", test, affectedComponentPath, environment); | ||
return !string.IsNullOrEmpty(affectedComponentPath); | ||
} | ||
|
||
public override bool TryParseAffectedComponentStatus(Incident incident, GroupCollection groups, out ComponentStatus affectedComponentStatus) | ||
{ | ||
affectedComponentStatus = ComponentStatus.Down; | ||
joelverhagen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
tests/StatusAggregator.Tests/Parse/AIAvailabilityIncidentRegexParsingHandlerTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.Extensions.Logging; | ||
using Moq; | ||
using NuGet.Services.Incidents; | ||
using NuGet.Services.Status; | ||
using StatusAggregator.Parse; | ||
using Xunit; | ||
using Match = System.Text.RegularExpressions.Match; | ||
|
||
namespace StatusAggregator.Tests.Parse | ||
{ | ||
public class AIAvailabilityIncidentRegexParsingHandlerTests | ||
{ | ||
public class TheTryParseAffectedComponentPathMethod : AIAvailabilityIncidentRegexParsingHandlerTest | ||
{ | ||
scottbommarito marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[Theory] | ||
[InlineData("blah blah blah blah", false, "")] | ||
[InlineData("[env] AI Availability test 'test' is failing!", false, "")] | ||
[InlineData("[env] AI Availability test '' is failing! (path)", false, "")] | ||
[InlineData("[env] AI Availability test 'test' is failing! ()", false, "")] | ||
[InlineData("[env] AI Availability test 'test' is failing! (path)", true, "path")] | ||
public void ReturnsExpectedResponse(string title, bool success, string affectedComponentPath) | ||
{ | ||
var incident = new Incident { Title = title }; | ||
IncidentParsingHandlerTestUtility.AssertTryParseAffectedComponentPath( | ||
Handler, incident, success, affectedComponentPath); | ||
} | ||
} | ||
|
||
public class TheTryParseAffectedComponentStatusMethod : AIAvailabilityIncidentRegexParsingHandlerTest | ||
{ | ||
[Fact] | ||
public void ReturnsExpectedResponse() | ||
{ | ||
var result = Handler.TryParseAffectedComponentStatus(new Incident(), Match.Empty.Groups, out var status); | ||
Assert.True(result); | ||
Assert.Equal(ComponentStatus.Down, status); | ||
} | ||
} | ||
|
||
public class AIAvailabilityIncidentRegexParsingHandlerTest | ||
{ | ||
public string Environment = "env"; | ||
public AIAvailabilityIncidentRegexParsingHandler Handler { get; } | ||
|
||
public AIAvailabilityIncidentRegexParsingHandlerTest() | ||
{ | ||
Handler = Construct( | ||
new[] { IncidentParsingHandlerTestUtility.CreateEnvironmentFilter(Environment) }); | ||
} | ||
} | ||
|
||
public class TheConstructor | ||
: EnvironmentPrefixIncidentRegexParsingHandlerTests.TheConstructor<AIAvailabilityIncidentRegexParsingHandler> | ||
{ | ||
protected override AIAvailabilityIncidentRegexParsingHandler Construct(IEnumerable<IIncidentRegexParsingFilter> filters) | ||
{ | ||
return AIAvailabilityIncidentRegexParsingHandlerTests.Construct(filters.ToArray()); | ||
} | ||
} | ||
|
||
public static AIAvailabilityIncidentRegexParsingHandler Construct(params IIncidentRegexParsingFilter[] filters) | ||
{ | ||
return new AIAvailabilityIncidentRegexParsingHandler( | ||
filters, | ||
Mock.Of<ILogger<AIAvailabilityIncidentRegexParsingHandler>>()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
tests/StatusAggregator.Tests/Parse/IncidentParsingHandlerTestUtility.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Text.RegularExpressions; | ||
using Microsoft.Extensions.Logging; | ||
using Moq; | ||
using NuGet.Services.Incidents; | ||
using NuGet.Services.Status; | ||
using StatusAggregator.Parse; | ||
using Xunit; | ||
using Match = System.Text.RegularExpressions.Match; | ||
|
||
namespace StatusAggregator.Tests.Parse | ||
{ | ||
public static class IncidentParsingHandlerTestUtility | ||
{ | ||
public static EnvironmentRegexParsingFilter CreateEnvironmentFilter(params string[] environments) | ||
{ | ||
var config = new StatusAggregatorConfiguration | ||
{ | ||
Environments = environments | ||
}; | ||
|
||
return new EnvironmentRegexParsingFilter( | ||
config, | ||
Mock.Of<ILogger<EnvironmentRegexParsingFilter>>()); | ||
} | ||
|
||
public static SeverityRegexParsingFilter CreateSeverityFilter(int severity) | ||
{ | ||
var config = new StatusAggregatorConfiguration | ||
{ | ||
MaximumSeverity = severity | ||
}; | ||
|
||
return new SeverityRegexParsingFilter( | ||
config, | ||
Mock.Of<ILogger<SeverityRegexParsingFilter>>()); | ||
} | ||
|
||
public static void AssertTryParseAffectedComponentPath( | ||
IIncidentRegexParsingHandler handler, | ||
Incident incident, | ||
bool success, | ||
string expectedAffectedComponentPath = null) | ||
{ | ||
var affectedComponentPath = string.Empty; | ||
var result = | ||
TryGetMatch(incident.Title, handler.RegexPattern, out var match) && | ||
handler.TryParseAffectedComponentPath(incident, match.Groups, out affectedComponentPath); | ||
|
||
Assert.Equal(success, result); | ||
if (!result) | ||
{ | ||
return; | ||
} | ||
|
||
Assert.Equal(expectedAffectedComponentPath, affectedComponentPath); | ||
} | ||
|
||
public static void AssertTryParseAffectedComponentStatus( | ||
IIncidentRegexParsingHandler handler, | ||
Incident incident, | ||
bool success, | ||
ComponentStatus expectedAffectedComponentStatus = ComponentStatus.Up) | ||
{ | ||
var affectedComponentStatus = ComponentStatus.Up; | ||
var result = | ||
TryGetMatch(incident.Title, handler.RegexPattern, out var match) && | ||
handler.TryParseAffectedComponentStatus(incident, match.Groups, out affectedComponentStatus); | ||
|
||
Assert.Equal(success, result); | ||
if (!result) | ||
{ | ||
return; | ||
} | ||
|
||
Assert.Equal(expectedAffectedComponentStatus, affectedComponentStatus); | ||
} | ||
|
||
private static bool TryGetMatch(string title, string pattern, out Match match) | ||
{ | ||
match = null; | ||
try | ||
{ | ||
match = Regex.Match(title, pattern, RegexOptions.None, TimeSpan.FromSeconds(5)); | ||
} | ||
catch | ||
{ | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the past, all component paths were specified by the job, and if a component path was specified that did not exist, the process would crash.
Because I'm adding an alert that specifies its own component path, I felt it was best to remove this protection. The StatusAggregator job would be essentially permanently stuck if it encountered a malformed AI alert. This way, the process will gracefully ignore any non-existent component paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good move.