public void ReturnsTrueIfActiveIncident() { var parentRowKey = "parentRowKey"; var group = new IncidentGroupEntity { StartTime = Cursor - StartMessageDelay, RowKey = parentRowKey }; var unlinkedIncident = new IncidentEntity { StartTime = Cursor, ParentRowKey = "something else" }; var shortIncident = new IncidentEntity { StartTime = Cursor - StartMessageDelay, EndTime = Cursor - TimeSpan.FromTicks(1), ParentRowKey = parentRowKey }; var activeIncident = new IncidentEntity { StartTime = Cursor - StartMessageDelay, ParentRowKey = parentRowKey }; Table.SetupQuery(unlinkedIncident, shortIncident, activeIncident); var result = Filter.CanPostMessages(group, Cursor); Assert.True(result); }
public bool CanPostMessages(IncidentGroupEntity group, DateTime cursor) { var duration = (group.EndTime ?? cursor) - group.StartTime; if (duration < _eventStartMessageDelay) { _logger.LogInformation("Incident group has not been active for longer than the messaging delay."); return(false); } var linkedIncidentsQuery = _table.GetChildEntities <IncidentEntity, IncidentGroupEntity>(group); var activeIncidents = linkedIncidentsQuery .Where(i => i.IsActive) .ToList(); var incidentsActiveAfterDelay = linkedIncidentsQuery .Where(i => i.EndTime >= group.StartTime + _eventStartMessageDelay) .ToList(); _logger.LogInformation("Incident group is linked to {ActiveIncidentsCount} active incidents and {DelayActiveIncidentsCount} incidents that were active after the messaging delay.", activeIncidents.Count, incidentsActiveAfterDelay.Count); var hasBeenActiveLongerThanDelay = activeIncidents.Any() || incidentsActiveAfterDelay.Any(); return(hasBeenActiveLongerThanDelay); }
public void ReturnsFalseIfDurationOfGroupTooShort(IncidentGroupEntity group) { var result = Filter.CanPostMessages(group, Cursor); Assert.False(result); Table .Verify( x => x.CreateQuery <IncidentEntity>(), Times.Never()); }
public async Task CreatesEntityAndDoesNotIncreaseSeverity(ComponentStatus existingStatus) { var input = new ParsedIncident(Incident, "the path", ComponentStatus.Degraded); IncidentEntity entity = null; Table .Setup(x => x.InsertOrReplaceAsync(It.IsAny <ITableEntity>())) .Returns(Task.CompletedTask) .Callback <ITableEntity>(e => { Assert.IsType <IncidentEntity>(e); entity = e as IncidentEntity; }); var group = new IncidentGroupEntity { RowKey = "parentRowKey", AffectedComponentStatus = (int)existingStatus }; Provider .Setup(x => x.GetAsync(input)) .ReturnsAsync(group); var expectedPath = "the provided path"; PathProvider .Setup(x => x.Get(input)) .Returns(expectedPath); var result = await Factory.CreateAsync(input); Assert.Equal(entity, result); Assert.Equal(input.Id, entity.IncidentApiId); Assert.Equal(group.RowKey, entity.ParentRowKey); Assert.Equal(expectedPath, entity.AffectedComponentPath); Assert.Equal((int)input.AffectedComponentStatus, entity.AffectedComponentStatus); Assert.Equal(input.StartTime, entity.StartTime); Assert.Equal(input.EndTime, entity.EndTime); Assert.Equal((int)existingStatus, group.AffectedComponentStatus); Table .Verify( x => x.InsertOrReplaceAsync(It.IsAny <IncidentEntity>()), Times.Once()); Table .Verify( x => x.ReplaceAsync(It.IsAny <IncidentGroupEntity>()), Times.Never()); }
public void ThrowsWithMissingPath() { var eventWithMessage = new EventEntity(Level2A.Path, DefaultStartTime, ComponentStatus.Degraded); var messageForEventWithMessage = new MessageEntity(eventWithMessage, DefaultStartTime, "", MessageType.Manual); var missingPathIncidentGroupForEventWithMessage = new IncidentGroupEntity(eventWithMessage, "missingPath", ComponentStatus.Degraded, DefaultStartTime); Table.SetupQuery(messageForEventWithMessage); Table.SetupQuery(missingPathIncidentGroupForEventWithMessage); Table.SetupQuery(eventWithMessage); Assert.Throws <InvalidOperationException>(() => Exporter.Export()); }
public void AppliesActiveEntitiesToComponentTree() { var eventWithMessage = new EventEntity(Level2A.Path, DefaultStartTime, ComponentStatus.Degraded); var messageForEventWithMessage = new MessageEntity(eventWithMessage, DefaultStartTime, "", MessageType.Manual); var degradedIncidentGroupForEventWithMessage = new IncidentGroupEntity(eventWithMessage, Level3AFrom2A.Path, ComponentStatus.Degraded, DefaultStartTime); var downIncidentGroupForEventWithMessage = new IncidentGroupEntity(eventWithMessage, Level3AFrom2A.Path, ComponentStatus.Down, DefaultStartTime); var upIncidentGroupForEventWithMessage = new IncidentGroupEntity(eventWithMessage, Level3AFrom2A.Path, ComponentStatus.Up, DefaultStartTime); var inactiveIncidentGroupForEventWithMessage = new IncidentGroupEntity(eventWithMessage, Level3BFrom2A.Path, ComponentStatus.Degraded, DefaultStartTime, DefaultStartTime); var eventWithoutMessage = new EventEntity(Level2B.Path, DefaultStartTime, ComponentStatus.Degraded); var incidentGroupForEventWithoutMessage = new IncidentGroupEntity(eventWithoutMessage, Level3AFrom2B.Path, ComponentStatus.Degraded, DefaultStartTime); var inactiveEventWithMessage = new EventEntity(Level2B.Path, DefaultStartTime + TimeSpan.FromDays(1), ComponentStatus.Degraded, DefaultStartTime + TimeSpan.FromDays(2)); var messageForInactiveEventWithMessage = new MessageEntity(inactiveEventWithMessage, DefaultStartTime + TimeSpan.FromDays(1), "", MessageType.Manual); var incidentGroupForInactiveEventWithMessage = new IncidentGroupEntity(inactiveEventWithMessage, Level3BFrom2B.Path, ComponentStatus.Degraded, DefaultStartTime + TimeSpan.FromDays(1)); Table.SetupQuery(messageForEventWithMessage, messageForInactiveEventWithMessage); Table.SetupQuery( degradedIncidentGroupForEventWithMessage, downIncidentGroupForEventWithMessage, upIncidentGroupForEventWithMessage, inactiveIncidentGroupForEventWithMessage, incidentGroupForEventWithoutMessage, incidentGroupForInactiveEventWithMessage); Table.SetupQuery(eventWithMessage, eventWithoutMessage, inactiveEventWithMessage); var result = Exporter.Export(); // Status of events with messages are applied. AssertComponentStatus(ComponentStatus.Degraded, Level2A, eventWithMessage); // Most severe status affecting same component is applied. AssertComponentStatus( ComponentStatus.Down, Level3AFrom2A, degradedIncidentGroupForEventWithMessage, downIncidentGroupForEventWithMessage, upIncidentGroupForEventWithMessage); // Status of inactive incident groups are not applied. AssertComponentStatus(ComponentStatus.Up, Level3BFrom2A, inactiveIncidentGroupForEventWithMessage); // Status of events without messages are not applied. // Status of inactive events with messages are not applied. AssertComponentStatus(ComponentStatus.Up, Level2B, eventWithoutMessage, inactiveEventWithMessage); // Status of incident groups for events without messages are not applied. AssertComponentStatus(ComponentStatus.Up, Level3AFrom2B, incidentGroupForEventWithoutMessage); // Status of incident groups for inactive events with messages are not applied. AssertComponentStatus(ComponentStatus.Up, Level3BFrom2B, incidentGroupForInactiveEventWithMessage); }
private void AssertChange(IncidentGroupEntity group, MessageType type, MessageChangeEvent change) { DateTime expectedTimestamp; switch (type) { case MessageType.Start: expectedTimestamp = group.StartTime; break; case MessageType.End: expectedTimestamp = group.EndTime.Value; break; default: throw new ArgumentException(nameof(type)); } Assert.Equal(expectedTimestamp, change.Timestamp); Assert.Equal(group.AffectedComponentPath, change.AffectedComponentPath); Assert.Equal(group.AffectedComponentStatus, (int)change.AffectedComponentStatus); Assert.Equal(type, change.Type); }
public void GetsChanges() { var cursor = new DateTime(2018, 10, 9); var eventEntity = new EventEntity { RowKey = "rowKey" }; var groupFromDifferentEvent = new IncidentGroupEntity { ParentRowKey = "different" }; var filteredGroup = new IncidentGroupEntity { ParentRowKey = eventEntity.RowKey }; Filter .Setup(x => x.CanPostMessages(filteredGroup, cursor)) .Returns(false); var activeGroup = new IncidentGroupEntity { ParentRowKey = eventEntity.RowKey, AffectedComponentPath = "path", AffectedComponentStatus = 99, StartTime = new DateTime(2018, 10, 10) }; Filter .Setup(x => x.CanPostMessages(activeGroup, cursor)) .Returns(true); var inactiveGroup = new IncidentGroupEntity { ParentRowKey = eventEntity.RowKey, AffectedComponentPath = "path 2", AffectedComponentStatus = 101, StartTime = new DateTime(2018, 10, 11), EndTime = new DateTime(2018, 10, 12), }; Filter .Setup(x => x.CanPostMessages(inactiveGroup, cursor)) .Returns(true); Table.SetupQuery(groupFromDifferentEvent, filteredGroup, activeGroup, inactiveGroup); var result = Provider.Get(eventEntity, cursor); Assert.Equal(3, result.Count()); var firstChange = result.First(); AssertChange(activeGroup, MessageType.Start, firstChange); var secondChange = result.ElementAt(1); AssertChange(inactiveGroup, MessageType.Start, secondChange); var thirdChange = result.ElementAt(2); AssertChange(inactiveGroup, MessageType.End, thirdChange); }