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
Status - add export logic for two-layer aggregation #566
Merged
Merged
Changes from 1 commit
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
8efe75e
add export for two-layer aggregation
a2b789e
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
e0ea057
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
270dce6
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
e7c586e
no-op change to force CI to go
28e714f
remove special contract resolver
80b626c
throw exception instead
8886876
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
5747def
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
00c4f2f
Merge branch 'sb-groupfactory' of https://github.com/NuGet/NuGet.Jobs…
5ea1922
fix aggregationstrategy bug
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// 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.Threading.Tasks; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
|
||
namespace StatusAggregator.Container | ||
{ | ||
public class ContainerWrapper : IContainerWrapper | ||
{ | ||
private readonly CloudBlobContainer _container; | ||
|
||
public ContainerWrapper(CloudBlobContainer container) | ||
{ | ||
_container = container; | ||
} | ||
|
||
public Task CreateIfNotExistsAsync() | ||
{ | ||
return _container.CreateIfNotExistsAsync(); | ||
} | ||
|
||
public Task SaveBlobAsync(string name, string contents) | ||
{ | ||
var blob = _container.GetBlockBlobReference(name); | ||
return blob.UploadTextAsync(contents); | ||
} | ||
} | ||
} |
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,17 @@ | ||
// 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.Threading.Tasks; | ||
using Microsoft.WindowsAzure.Storage.Blob; | ||
|
||
namespace StatusAggregator.Container | ||
{ | ||
/// <summary> | ||
/// Simple wrapper for <see cref="CloudBlobContainer"/> that exists for unit-testing. | ||
/// </summary> | ||
public interface IContainerWrapper | ||
{ | ||
Task CreateIfNotExistsAsync(); | ||
Task SaveBlobAsync(string name, string contents); | ||
} | ||
} |
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,92 @@ | ||
// 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.Linq; | ||
using Microsoft.Extensions.Logging; | ||
using NuGet.Jobs.Extensions; | ||
using NuGet.Services.Status; | ||
using NuGet.Services.Status.Table; | ||
using StatusAggregator.Factory; | ||
using StatusAggregator.Table; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public class ComponentExporter : IComponentExporter | ||
{ | ||
private readonly ITableWrapper _table; | ||
private readonly IComponentFactory _factory; | ||
|
||
private readonly ILogger<ComponentExporter> _logger; | ||
|
||
public ComponentExporter( | ||
ITableWrapper table, | ||
IComponentFactory factory, | ||
ILogger<ComponentExporter> logger) | ||
{ | ||
_table = table ?? throw new ArgumentNullException(nameof(table)); | ||
_factory = factory ?? throw new ArgumentNullException(nameof(factory)); | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
} | ||
|
||
public IComponent Export() | ||
{ | ||
using (_logger.Scope("Exporting active entities to component.")) | ||
{ | ||
var rootComponent = _factory.Create(); | ||
|
||
// Apply the active entities to the component tree. | ||
var activeEvents = _table | ||
.GetActiveEntities<EventEntity>() | ||
.ToList() | ||
.Where(e => | ||
_table | ||
.GetChildEntities<MessageEntity, EventEntity>(e) | ||
.ToList() | ||
.Any()) | ||
.ToList(); | ||
|
||
_logger.LogInformation("Found {EventCount} active events with messages.", activeEvents.Count); | ||
|
||
var activeIncidentGroups = activeEvents | ||
.SelectMany(e => | ||
_table | ||
.GetChildEntities<IncidentGroupEntity, EventEntity>(e) | ||
.Where(i => i.IsActive) | ||
.ToList()) | ||
.ToList(); | ||
|
||
_logger.LogInformation("Found {GroupCount} active incident groups linked to active events with messages.", activeIncidentGroups.Count); | ||
|
||
var activeEntities = activeIncidentGroups | ||
.Concat<IComponentAffectingEntity>(activeEvents) | ||
// Only apply entities with a non-Up status. | ||
.Where(e => e.AffectedComponentStatus != (int)ComponentStatus.Up) | ||
// If multiple events are affecting a single region, the event with the highest severity should affect the component. | ||
.GroupBy(e => e.AffectedComponentPath) | ||
.Select(g => g.OrderByDescending(e => e.AffectedComponentStatus).First()) | ||
.ToList(); | ||
|
||
_logger.LogInformation("Active entities affect {PathCount} distinct subcomponents.", activeEntities.Count); | ||
foreach (var activeEntity in activeEntities) | ||
{ | ||
using (_logger.Scope("Applying active entity affecting {AffectedComponentPath} of severity {AffectedComponentStatus} at {StartTime} to root component", | ||
activeEntity.AffectedComponentPath, activeEntity.AffectedComponentStatus, activeEntity.StartTime)) | ||
{ | ||
var currentComponent = rootComponent.GetByPath(activeEntity.AffectedComponentPath); | ||
|
||
if (currentComponent == null) | ||
{ | ||
_logger.LogWarning("Couldn't find component corresponding to active entities."); | ||
continue; | ||
} | ||
|
||
currentComponent.Status = (ComponentStatus)activeEntity.AffectedComponentStatus; | ||
} | ||
} | ||
|
||
return rootComponent; | ||
} | ||
} | ||
} | ||
} |
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,55 @@ | ||
// 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.Linq; | ||
using Microsoft.Extensions.Logging; | ||
using NuGet.Jobs.Extensions; | ||
using NuGet.Services.Status; | ||
using NuGet.Services.Status.Table; | ||
using StatusAggregator.Table; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public class EventExporter : IEventExporter | ||
{ | ||
private readonly ITableWrapper _table; | ||
private readonly ILogger<EventExporter> _logger; | ||
|
||
public EventExporter( | ||
ITableWrapper table, | ||
ILogger<EventExporter> logger) | ||
{ | ||
_table = table ?? throw new ArgumentNullException(nameof(table)); | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
} | ||
|
||
public Event Export(EventEntity eventEntity) | ||
{ | ||
using (_logger.Scope("Exporting event {EventRowKey}.", eventEntity.RowKey)) | ||
{ | ||
var messages = _table.GetChildEntities<MessageEntity, EventEntity>(eventEntity) | ||
.ToList() | ||
// Don't show empty messages. | ||
.Where(m => !string.IsNullOrEmpty(m.Contents)) | ||
.ToList(); | ||
|
||
_logger.LogInformation("Event has {MessageCount} messages that are not empty.", messages.Count); | ||
|
||
if (!messages.Any()) | ||
{ | ||
return null; | ||
} | ||
|
||
return new Event( | ||
eventEntity.AffectedComponentPath, | ||
eventEntity.StartTime, | ||
eventEntity.EndTime, | ||
messages | ||
.OrderBy(m => m.Time) | ||
.Select(m => new Message(m.Time, m.Contents))); | ||
} | ||
} | ||
} | ||
} |
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,46 @@ | ||
// 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.Linq; | ||
using Microsoft.Extensions.Logging; | ||
using NuGet.Services.Status; | ||
using NuGet.Services.Status.Table; | ||
using StatusAggregator.Table; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public class EventsExporter : IEventsExporter | ||
{ | ||
private readonly TimeSpan _eventVisibilityPeriod; | ||
|
||
private readonly ITableWrapper _table; | ||
private readonly IEventExporter _exporter; | ||
|
||
private readonly ILogger<EventsExporter> _logger; | ||
|
||
public EventsExporter( | ||
ITableWrapper table, | ||
IEventExporter exporter, | ||
StatusAggregatorConfiguration configuration, | ||
ILogger<EventsExporter> logger) | ||
{ | ||
_table = table ?? throw new ArgumentNullException(nameof(table)); | ||
_exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); | ||
_eventVisibilityPeriod = TimeSpan.FromDays(configuration?.EventVisibilityPeriodDays ?? throw new ArgumentNullException(nameof(configuration))); | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
} | ||
|
||
public IEnumerable<Event> Export(DateTime cursor) | ||
{ | ||
return _table | ||
.CreateQuery<EventEntity>() | ||
.Where(e => e.IsActive || (e.EndTime >= cursor - _eventVisibilityPeriod)) | ||
.ToList() | ||
.Select(_exporter.Export) | ||
.Where(e => e != null) | ||
.ToList(); | ||
} | ||
} | ||
} |
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,15 @@ | ||
// 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 NuGet.Services.Status; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public interface IComponentExporter | ||
{ | ||
/// <summary> | ||
/// Exports the status of the current active entities to an <see cref="IComponent"/>. | ||
/// </summary> | ||
IComponent Export(); | ||
} | ||
} |
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,17 @@ | ||
// 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 NuGet.Services.Status; | ||
using NuGet.Services.Status.Table; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public interface IEventExporter | ||
{ | ||
/// <summary> | ||
/// Exports <paramref name="eventEntity"/> as a <see cref="Event"/>. If it should not be exported, returns <c>null</c>. | ||
/// </summary> | ||
Event Export(EventEntity eventEntity); | ||
} | ||
} |
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,17 @@ | ||
// 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 NuGet.Services.Status; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public interface IEventsExporter | ||
{ | ||
/// <summary> | ||
/// Exports recent events. | ||
/// </summary> | ||
IEnumerable<Event> Export(DateTime cursor); | ||
} | ||
} |
9 changes: 5 additions & 4 deletions
9
src/StatusAggregator/IStatusExporter.cs → ...tatusAggregator/Export/IStatusExporter.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 |
---|---|---|
@@ -1,16 +1,17 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// 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 NuGet.Services.Status; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace StatusAggregator | ||
namespace StatusAggregator.Export | ||
{ | ||
public interface IStatusExporter | ||
{ | ||
/// <summary> | ||
/// Builds a <see cref="ServiceStatus"/> and exports it to public storage so that it can be consumed by other services. | ||
/// </summary> | ||
Task<ServiceStatus> Export(); | ||
Task Export(DateTime cursor); | ||
} | ||
} | ||
} |
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,18 @@ | ||
// 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.Threading.Tasks; | ||
using NuGet.Services.Status; | ||
|
||
namespace StatusAggregator.Export | ||
{ | ||
public interface IStatusSerializer | ||
{ | ||
/// <summary> | ||
/// Serializes <paramref name="rootComponent"/> and <paramref name="recentEvents"/> and saves to storage with a time of <paramref name="cursor"/>. | ||
/// </summary> | ||
Task Serialize(DateTime cursor, IComponent rootComponent, IEnumerable<Event> recentEvents); | ||
} | ||
} |
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.
Why isn't this an exception?
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.
my bad, will fix