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());
            }
예제 #4
0
            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);
            }