Пример #1
0
        public IBulbCacheReadObject SetSignal(Guid bulbId, BulbSignal signal)
        {
            var statusData = ProlongOrChangeStatus(signal, bulbId);

            UpdateParentByChild(statusData);
            return(statusData);
        }
Пример #2
0
        protected void ProlongStatus(BulbSignal signal, BulbCacheWriteObject data)
        {
            // проверим пробел
            var  nextStartDate = GetStartDate(data, signal);
            bool hasSpace      = data.ActualDate < nextStartDate;

            if (hasSpace)
            {
                throw new Exception("Тут не должно быть пробела");
            }

            // разрыва нет
            // у виртуальных колбасок нет смысла увеличивать счетчик, т.к. это приводит только к лишнему сохранению объектов
            if (data.IsLeaf)
            {
                data.Count++;
            }

            data.HasSignal = signal.HasSignal;
            data.Message   = signal.Message;
            if (signal.EventId != Guid.Empty)
            {
                data.LastEventId = signal.EventId;
            }
            data.LastChildBulbId = signal.ChildBulbId;

            // у листьев время завершения меняется,
            // а у родителей время завершения меняется только когда начинется новый статус
            if (data.IsLeaf)
            {
                // это нужно, например, чтобы у проверок и метрик EndDate показывал время последнего выполнения
                data.EndDate = signal.ProcessDate;

                // актуальность проверки и метрики определяется последним значением
                if (data.EventCategory == EventCategory.MetricStatus ||
                    data.EventCategory == EventCategory.UnitTestStatus)
                {
                    data.ActualDate = signal.ActualDate;
                }
                else if (data.EventCategory == EventCategory.ComponentEventsStatus)
                {
                    if (signal.ActualDate > data.ActualDate)
                    {
                        data.ActualDate = signal.ActualDate;
                    }
                }
                else
                {
                    throw new Exception("Неизвестный тип лампочки " + data.EventCategory);
                }
            }
            else
            {
                // у виртуальных лампочек время актуальности и завершения не меняется при продлении
                data.ActualDate = EventHelper.InfiniteActualDate;
            }

            CreateOrUpdateStatusEvent(signal.AccountId, data);
        }
Пример #3
0
        public IBulbCacheReadObject SetUnknownStatus(Guid accountId, Guid statusId, DateTime processDate)
        {
            var signal = BulbSignal.CreateUnknown(accountId, processDate);
            var data   = ProlongOrChangeStatus(signal, statusId);

            UpdateParentByChild(data);
            return(data);
        }
Пример #4
0
        protected void CalculateComponentEventsStatus(Guid accountId, Guid eventsStatusId)
        {
            var processDate   = DateTime.Now;
            var eventService  = Context.EventService;
            var statusService = Context.BulbService;
            var request       = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = eventsStatusId
            };

            // получаем объект для записи, чтобы заблокировать доступ, но ничего не пишем
            using (var data = AllCaches.StatusDatas.Write(request))
            {
                if (data.Actual(processDate))
                {
                    // событий не было вообще
                    if (data.LastEventId == null)
                    {
                        return;
                    }

                    // проверим, что событие актуально
                    var lastEvent = eventService.GetEventCacheOrNullById(accountId, data.LastEventId.Value);
                    if (lastEvent != null)
                    {
                        bool isActual = EventImportanceHelper.Get(data.Status) == lastEvent.Importance &&
                                        lastEvent.ActualDate >= processDate;

                        if (isActual)
                        {
                            // ничего не изменилось, статус актуален
                            return;
                        }
                    }
                }

                // ищем событие, которое пересекается со статусом
                var nextEvent = eventService.GetDangerousEvent(
                    accountId,
                    data.ComponentId.Value,
                    processDate);

                if (nextEvent != null)
                {
                    var noSignalImportance = Api.EventImportance.Unknown;
                    var signal             = BulbSignal.Create(processDate, nextEvent, noSignalImportance, accountId);
                    statusService.SetSignal(data.Id, signal);
                    return;
                }

                // нет актуальных событий
                var unknownSignal = BulbSignal.CreateUnknown(accountId, processDate);
                statusService.SetSignal(eventsStatusId, unknownSignal);
            }
        }
Пример #5
0
        protected void UpdateParentByChild(IBulbCacheReadObject childBulb)
        {
            if (childBulb == null)
            {
                return;
            }
            var parentId = childBulb.GetParentId();

            if (parentId == null)
            {
                return;
            }
            var parentRequest = new AccountCacheRequest()
            {
                AccountId = childBulb.AccountId,
                ObjectId  = parentId.Value
            };
            IBulbCacheReadObject rParent = null;

            using (var parent = AllCaches.StatusDatas.Write(parentRequest))
            {
                // менять выключенного родителя нельзя, его надо сначала включить
                if (parent.Status == MonitoringStatus.Disabled)
                {
                    return;
                }

                var processDate = DateTime.Now;

                BulbSignal signal = null;

                if (childBulb.Status > parent.Status)
                {
                    // 1. если дочерний опаснее
                    signal  = BulbSignal.CreateFromChild(processDate, childBulb);
                    rParent = ProlongOrChangeStatus(signal, parent.Id);
                }
                else
                {
                    // 2. если дочерний менее опасный и он был последней причиной
                    if (childBulb.Status < parent.Status && parent.LastChildBulbId == childBulb.Id)
                    {
                        // нужно расчитать занова
                        CalculateByChilds(parent);
                    }
                }
            }
            if (rParent != null)
            {
                UpdateParentByChild(rParent);
            }
        }
Пример #6
0
        protected IBulbCacheReadObject ProlongOrChangeStatus(BulbSignal signal, Guid statusDataId)
        {
            var request = new AccountCacheRequest()
            {
                AccountId = signal.AccountId,
                ObjectId  = statusDataId
            };
            IBulbCacheReadObject rBulb = null;

            using (var wStatusData = AllCaches.StatusDatas.Write(request))
            {
                rBulb = wStatusData;

                // если сигнал протух, то игнорируем его
                if (signal.ActualDate < wStatusData.EndDate)
                {
                    return(rBulb);
                }

                // вставим пробел
                var startTime = GetStartDate(wStatusData, signal);
                if (wStatusData.ActualDate < startTime)
                {
                    var noSignal = BulbSignal.CreateNoSignal(signal.AccountId, wStatusData.ActualDate, signal.NoSignalImportance);
                    ChangeStatus(noSignal, wStatusData);
                }

                // теперь лампочка актуальная, обработаем сигнал
                if (wStatusData.Status == signal.Status && wStatusData.HasSignal == signal.HasSignal)
                {
                    // продлим
                    ProlongStatus(signal, wStatusData);
                }
                else
                {
                    // изменим
                    ChangeStatus(signal, wStatusData);
                }

                // запомним к какому статусу привело событие
                // сервис юнит-тестов сам обновит LastStatusId (в целях оптимизации)
                // if (wStatusData.EventCategory != EventCategory.UnitTestStatus)
                {
                    UpdateLastStatusId(signal.AccountId, signal.EventId, wStatusData);
                }
                wStatusData.BeginSave();
            }

            return(rBulb);
        }
Пример #7
0
        public static BulbSignal CreateDisable(Guid accountId, DateTime processTime)
        {
            var signal = new BulbSignal()
            {
                AccountId          = accountId,
                ActualDate         = EventHelper.InfiniteActualDate, // чтобы статус был актуален вечно
                StartDate          = processTime,
                ProcessDate        = processTime,
                Status             = MonitoringStatus.Disabled,
                Message            = "Объект выключен",
                NoSignalImportance = EventImportance.Unknown // при выключении пробел будет серым
            };

            return(signal);
        }
Пример #8
0
        public static BulbSignal CreateUnknown(Guid accountId, DateTime startDate)
        {
            var signal = new BulbSignal()
            {
                AccountId          = accountId,
                StartDate          = startDate,
                ProcessDate        = startDate,
                ActualDate         = EventHelper.InfiniteActualDate,
                Message            = "Нет данных",
                Status             = MonitoringStatus.Unknown,
                NoSignalImportance = EventImportance.Unknown,
                IsSpace            = true // todo ??? пробел ли это ???
            };

            return(signal);
        }
Пример #9
0
        public IBulbCacheReadObject GetActual(
            Guid accountId,
            Guid statusId,
            DateTime processDate,
            EventImportance noSignalImportance)
        {
            var request = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = statusId
            };
            var data = AllCaches.StatusDatas.Find(request);

            // статус актуальный
            if (data.Actual(processDate))
            {
                return(data);
            }

            // статус протух
            IBulbCacheReadObject rStatus = null;

            using (var rStatus2 = AllCaches.StatusDatas.Write(request))
            {
                rStatus = rStatus2;
                if (rStatus.Actual(processDate))
                {
                    return(rStatus);
                }

                var signal = BulbSignal.CreateNoSignal(accountId, data.ActualDate, noSignalImportance);
                //var signal = new BulbSignal()
                //{
                //    AccountId = accountId,
                //    IsSpace = true,
                //    ActualDate = EventHelper.InfiniteActualDate,
                //    ProcessDate = processDate,
                //    StartDate = data.ActualDate, // data.ActualDate всегда меньше processDate
                //    Status = noSignalStatus,
                //    Message = "Нет данных",
                //    NoSignalImportance = noSignalImportance
                //};
                ProlongOrChangeStatus(signal, statusId);
            }
            UpdateParentByChild(rStatus);
            return(rStatus);
        }
Пример #10
0
        public static BulbSignal CreateNoSignal(Guid accountId, DateTime startDate, EventImportance noSignalImportance)
        {
            var noSignalStatus = MonitoringStatusHelper.Get(noSignalImportance);
            var signal         = new BulbSignal()
            {
                AccountId          = accountId,
                StartDate          = startDate,
                ProcessDate        = startDate,
                ActualDate         = EventHelper.InfiniteActualDate,
                Message            = "Нет сигнала",
                Status             = noSignalStatus,
                NoSignalImportance = EventImportance.Unknown,
                IsSpace            = true
            };

            return(signal);
        }
Пример #11
0
        public static BulbSignal CreateFromChild(DateTime processDate, IBulbCacheReadObject child)
        {
            var signal = new BulbSignal()
            {
                AccountId          = child.AccountId,
                Status             = child.Status,
                NoSignalImportance = EventImportance.Unknown,
                StartDate          = processDate,
                ProcessDate        = processDate,
                ActualDate         = EventHelper.InfiniteActualDate,
                EventId            = child.StatusEventId,
                IsSpace            = child.IsSpace,
                Message            = child.Message,
                ChildBulbId        = child.Id
            };

            return(signal);
        }
Пример #12
0
        protected IBulbCacheReadObject UpdateEnableOrDisableStatusData(IMetricCacheReadObject metric)
        {
            var statusService         = Context.BulbService;
            IBulbCacheReadObject data = null;
            var processDate           = DateTime.Now;

            if (metric.CanProcess)
            {
                var unknownSignal = BulbSignal.CreateUnknown(metric.AccountId, processDate);
                data = statusService.SetSignal(metric.StatusDataId, unknownSignal);
            }
            else
            {
                var disableSignal = BulbSignal.CreateDisable(metric.AccountId, processDate);
                data = statusService.SetSignal(metric.StatusDataId, disableSignal);
            }
            //Context.ComponentService.CalculateAllStatuses(metric.AccountId, metric.ComponentId);
            return(data);
        }
Пример #13
0
        public void CalculateByChilds(Guid accountId, Guid statusId, List <Guid> childs)
        {
            var processDate = DateTime.Now;
            var request     = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = statusId
            };
            IBulbCacheReadObject rBulb = null;

            using (var statusData = AllCaches.StatusDatas.Write(request))
            {
                var childsList = new List <IBulbCacheReadObject>();
                foreach (var childId in childs)
                {
                    var childRequest = new AccountCacheRequest()
                    {
                        AccountId = accountId,
                        ObjectId  = childId
                    };
                    var child = AllCaches.StatusDatas.Find(childRequest);

                    // Disabled и Unknown не влияют на родителей
                    if (child != null && child.Status != MonitoringStatus.Disabled && child.Status != MonitoringStatus.Unknown)
                    {
                        childsList.Add(child);
                    }
                }
                var mostDandger = childsList.OrderByDescending(x => x.Status).FirstOrDefault();
                if (mostDandger == null)
                {
                    var signal = BulbSignal.CreateUnknown(accountId, processDate);
                    rBulb = ProlongOrChangeStatus(signal, statusId);
                }
                else
                {
                    var signal = BulbSignal.CreateFromChild(processDate, mostDandger);
                    rBulb = ProlongOrChangeStatus(signal, statusId);
                }
            }
            UpdateParentByChild(rBulb);
        }
Пример #14
0
        protected DateTime GetStartDate(IBulbCacheReadObject bulb, BulbSignal signal)
        {
            var startDate = signal.StartDate;

            if (signal.Status > bulb.Status)
            {
                // более важные события могут обнулять длительность предыдущих
                // обычно statusData.EndDate = statusData.StartDate
                startDate = DateTimeHelper.Max(startDate, bulb.EndDate);
            }
            else
            {
                // менее важные не могут затирать более важные
                startDate = DateTimeHelper.Max(startDate, bulb.ActualDate);
            }

            // время начала нового статуса НЕ может быть больше текущей даты
            startDate = DateTimeHelper.Min(signal.ProcessDate, startDate);

            return(startDate);
        }
Пример #15
0
        public IBulbCacheReadObject Enable(Guid accountId, Guid unitTestId)
        {
            var cache = new AccountCache(accountId);
            IUnitTestCacheReadObject unitTestRead = null;

            // изменим юнит-тест
            using (var unitTest = cache.UnitTests.Write(unitTestId))
            {
                unitTestRead    = unitTest;
                unitTest.Enable = true;
                unitTest.BeginSave();
            }

            // обновим колбаски
            var statusService = Context.BulbService;
            var processDate   = DateTime.Now;
            var unknownSignal = BulbSignal.CreateUnknown(accountId, processDate);
            var data          = statusService.SetSignal(unitTestRead.StatusDataId, unknownSignal);

            Context.ComponentService.CalculateAllStatuses(accountId, unitTestRead.ComponentId);
            return(data);
        }
Пример #16
0
        protected void ChangeStatus(BulbSignal signal, BulbCacheWriteObject data)
        {
            // проверим пробел
            var startDate = GetStartDate(data, signal);

            if (startDate > data.ActualDate)
            {
                throw new Exception("startDate > data.ActualDate");
            }

            // обновим статус
            data.PreviousStatus = data.Status; // запомним предыдущий
            if (signal.EventId != Guid.Empty)
            {
                data.FirstEventId = signal.EventId;
                data.LastEventId  = signal.EventId;
            }
            data.Count           = 1;
            data.Message         = signal.Message;
            data.Status          = signal.Status;
            data.LastChildBulbId = signal.ChildBulbId;

            if (data.IsLeaf)
            {
                data.ActualDate = signal.ActualDate;
            }
            else
            {
                // время актуальности колбасок, которые НЕ являются листьями дерева, бесконечо
                data.ActualDate = EventHelper.InfiniteActualDate;
            }

            data.StartDate = startDate;
            data.HasSignal = signal.HasSignal;
            data.EndDate   = startDate; // меняется только при создании нового статуса

            var ownerId     = data.GetOwnerId();
            var statusEvent = AddStatusEvent(signal.AccountId, data, ownerId);
        }
Пример #17
0
        public void EnableMetric(Guid accountId, Guid metricId)
        {
            var cache = new AccountCache(accountId);
            IMetricCacheReadObject metricRead = null;

            // изменим метрику
            using (var metric = cache.Metrics.Write(metricId))
            {
                metricRead    = metric;
                metric.Enable = true;
                metric.BeginSave();
            }

            // обновим колбаски
            var statusService = Context.BulbService;
            var processDate   = DateTime.Now;
            var unknownSignal = BulbSignal.CreateUnknown(accountId, processDate);
            var data          = statusService.SetSignal(metricRead.StatusDataId, unknownSignal);

            Context.ComponentService.CalculateAllStatuses(accountId, metricRead.ComponentId);
            // return data;
        }
Пример #18
0
        protected IComponentCacheReadObject RecalculateComponentStatuses(IComponentCacheReadObject component)
        {
            var accountId = component.AccountId;
            var cache     = new AccountCache(accountId);
            IComponentCacheReadObject result = component;

            // обновим ParentEnable
            if (component.ParentId.HasValue)
            {
                var parent = cache.Components.Read(component.ParentId.Value);
                if (parent.CanProcess != component.ParentEnable)
                {
                    using (var componentWrite = cache.Components.Write(component))
                    {
                        componentWrite.ParentEnable = parent.CanProcess;
                        componentWrite.BeginSave();
                        component = componentWrite;
                    }
                    UpdateParentEnableFlags(component, true);
                }
            }

            // если время выключения истекло, то включим компонент
            if (component.Enable == false &&
                component.DisableToDate.HasValue &&
                component.DisableToDate < DateTime.Now)
            {
                using (var componentWrite = cache.Components.Write(component))
                {
                    componentWrite.Enable = true;
                    componentWrite.BeginSave();
                    component = componentWrite;
                    result    = component;
                }
                UpdateParentEnableFlags(component, true);
            }

            var statusService  = Context.BulbService;
            var allStatusesIds = component.GetAllStatusesIds();
            var allStatuses    = allStatusesIds.Select(cache.StatusDatas.Read).ToList();

            // если надо выключить
            if (component.CanProcess == false && allStatuses.Any(x => x.Status != Api.MonitoringStatus.Disabled))
            {
                // выключим все колбаски
                // выжно выключить их в этом порядке, чтобы не создать лишних событий колбасок-родителей
                var disableSignal = BulbSignal.CreateDisable(accountId, DateTime.Now);
                statusService.SetSignal(component.ExternalStatusId, disableSignal);
                statusService.SetSignal(component.ChildComponentsStatusId, disableSignal);
                statusService.SetSignal(component.InternalStatusId, disableSignal);
                statusService.SetSignal(component.EventsStatusId, disableSignal);
                statusService.SetSignal(component.UnitTestsStatusId, disableSignal);
                statusService.SetSignal(component.MetricsStatusId, disableSignal);
            }

            // обновим тесты
            var allUnitTestsStatusDataIds = new List <Guid>();

            foreach (var unitTestRef in component.UnitTests.GetAll())
            {
                using (var unitTest = cache.UnitTests.Write(unitTestRef.Id))
                {
                    if (unitTest.IsDeleted)
                    {
                        continue;
                    }
                    allUnitTestsStatusDataIds.Add(unitTest.StatusDataId);
                    if (unitTest.ParentEnable != component.CanProcess)
                    {
                        unitTest.ParentEnable = component.CanProcess;
                        unitTest.BeginSave();
                    }
                }
                Context.UnitTestService.GetUnitTestResult(component.AccountId, unitTestRef.Id);
            }

            // обновим метрики
            var  allMetricsStatusDataIds = new List <Guid>();
            Guid metricTypeId;

            foreach (var metricRef in component.Metrics.GetAll())
            {
                using (var metric = cache.Metrics.Write(metricRef.Id))
                {
                    if (metric.IsDeleted)
                    {
                        continue;
                    }
                    metricTypeId = metric.MetricTypeId;
                    allMetricsStatusDataIds.Add(metric.StatusDataId);
                    if (metric.ParentEnable != component.CanProcess)
                    {
                        metric.ParentEnable = component.CanProcess;
                        metric.BeginSave();
                    }
                }
                Context.MetricService.GetActualMetric(component.AccountId, component.Id, metricTypeId);
            }

            // проверим, нужно ли обновить детей
            var childComponentsStatusDataIds = new List <Guid>();

            foreach (var childRef in component.Childs.GetAll())
            {
                using (var child = cache.Components.Write(childRef.Id))
                {
                    if (child.IsDeleted)
                    {
                        continue;
                    }
                    childComponentsStatusDataIds.Add(child.ExternalStatusId);
                    if (child.ParentEnable != component.CanProcess)
                    {
                        child.ParentEnable = component.CanProcess;
                        child.BeginSave();
                    }
                }
                GetComponentExternalState(component.AccountId, childRef.Id);
            }

            if (component.CanProcess)
            {
                // обновим колбасу тестов явно (вдруг нет ни одного теста)
                statusService.CalculateByChilds(accountId, component.UnitTestsStatusId, allUnitTestsStatusDataIds);

                // обновим колбасу метрик явно (вдруг нет ни одной метрики)
                statusService.CalculateByChilds(accountId, component.MetricsStatusId, allMetricsStatusDataIds);

                // обновим колбасу событий
                CalculateComponentEventsStatus(accountId, component.EventsStatusId);

                // обновим внутренний статус
                var childsForInternal = new List <Guid>()
                {
                    component.EventsStatusId,
                    component.UnitTestsStatusId,
                    component.MetricsStatusId
                };
                statusService.CalculateByChilds(accountId, component.InternalStatusId, childsForInternal);

                // обновим колбасу дочерних
                statusService.CalculateByChilds(accountId, component.ChildComponentsStatusId, childComponentsStatusDataIds);

                // обновим внешний статус
                var childsForExternal = new List <Guid>()
                {
                    component.InternalStatusId,
                    component.ChildComponentsStatusId
                };
                statusService.CalculateByChilds(accountId, component.ExternalStatusId, childsForExternal);
            }
            return(result);
        }
Пример #19
0
        protected IBulbCacheReadObject SaveResultEvent(
            DateTime processDate,
            IUnitTestCacheReadObject unitTest,
            Event newEvent)
        {
            var request = new AccountCacheRequest()
            {
                AccountId = unitTest.AccountId,
                ObjectId  = unitTest.StatusDataId
            };

            using (var statusData = AllCaches.StatusDatas.Write(request))
            {
                // сохраним результаты
                var eventService = Context.EventService;
                IEventCacheReadObject lastEvent = null;
                if (statusData.LastEventId.HasValue)
                {
                    lastEvent = eventService.GetEventCacheOrNullById(
                        unitTest.AccountId,
                        statusData.LastEventId.Value);
                }

                // для системных проверок пробелы должны быть серыми,
                // чтобы из-за простоев агента зидиума не красить пользовательские проверки
                var noSignalImportance = unitTest.IsSystemType
                    ? EventImportance.Unknown
                    : EventImportance.Alarm;

                if (lastEvent == null)
                {
                    // todo не понятно нужно ли в результаты проверок вставлять пробелы?
                    // TryAddSpaceResultEvent(unitTest, newEvent, noSignalImportance);
                }
                else
                {
                    // например, чтобы обрезать бесконечную актуальность у события "нет сигнала"
                    if (lastEvent.ActualDate > newEvent.StartDate)
                    {
                        if (AllCaches.Events.ExistsInStorage(lastEvent))
                        {
                            using (var wLastEvent = AllCaches.Events.Write(lastEvent))
                            {
                                wLastEvent.ActualDate = newEvent.StartDate;
                                wLastEvent.BeginSave();
                            }
                        }
                    }
                }

                // синхронная вставка
                // асинхронное создание объектов сильно усложняет код, поэтому будет создавать всё синхронно
                eventService.Add(unitTest.AccountId, newEvent);

                // асинхронная вставка
                //var newEventCache = EventCacheWriteObject.CreateForAdd(newEvent);
                //AllCaches.Events.AddNew(newEventCache);

                using (var wUnitTest = AllCaches.UnitTests.Write(unitTest))
                {
                    wUnitTest.LastExecutionDate = newEvent.EndDate;

                    // расчитаем время следующего выполнения
                    if (unitTest.PeriodSeconds > 0)
                    {
                        var nextTime = wUnitTest.NextDate ?? processDate;
                        var period   = TimeSpan.FromSeconds(wUnitTest.PeriodSeconds.Value);
                        while (nextTime <= processDate)
                        {
                            nextTime = nextTime + period;
                        }
                        wUnitTest.NextDate = nextTime;
                    }
                    wUnitTest.BeginSave();
                }

                // обновим статус
                var statusService = Context.BulbService;
                var signal        = BulbSignal.Create(processDate, newEvent, noSignalImportance, unitTest.AccountId);
                var newStatus     = statusService.SetSignal(unitTest.StatusDataId, signal);

                return(newStatus);
            }
        }
Пример #20
0
        protected IBulbCacheReadObject SetMetricValue(
            IMetricTypeCacheReadObject metricType,
            MetricCacheWriteObject metric,
            double?value,
            DateTime processDate,
            DateTime actualDate,
            MonitoringStatus status,
            string message,
            bool hasSignal)
        {
            // Обновим текущие значения
            var equal = (value == null && metric.Value == null) || (value == metric.Value);

            if (!equal)
            {
                metric.BeginDate = processDate;
            }
            metric.ActualDate = actualDate;
            metric.Value      = value;

            // Обновим статус метрики
            var statusService      = Context.BulbService;
            var noSignalColor      = metric.NoSignalColor ?? metricType.NoSignalColor ?? ObjectColor.Red;
            var noSignalImportance = EventImportanceHelper.Get(noSignalColor);
            var signal             = new BulbSignal()
            {
                AccountId          = metric.AccountId,
                ActualDate         = metric.ActualDate,
                StartDate          = metric.BeginDate,
                IsSpace            = !hasSignal,
                EventId            = Guid.Empty,
                Message            = message,
                NoSignalImportance = noSignalImportance,
                ProcessDate        = processDate,
                Status             = status
            };

            var statusData = statusService.SetSignal(metric.StatusDataId, signal);

            // сохраним историю
            var color   = ObjectColorHelper.Get(status);
            var history = new MetricHistory()
            {
                ComponentId   = metric.ComponentId,
                MetricTypeId  = metric.MetricTypeId,
                Value         = value,
                BeginDate     = processDate,
                ActualDate    = actualDate,
                Color         = color,
                StatusEventId = statusData.StatusEventId,
                HasSignal     = hasSignal
            };

            var accountDbContext  = Context.GetAccountDbContext(metric.AccountId);
            var historyRepository = accountDbContext.GetMetricHistoryRepository();

            historyRepository.Add(history);

            Context.SaveChanges();
            return(statusData);
        }
Пример #21
0
        public void ProcessEvent(Guid accountId, Guid componentId, IEventCacheReadObject eventObj)
        {
            var categories = new[]
            {
                Api.EventCategory.ApplicationError,
                Api.EventCategory.ComponentEvent
            };

            if (categories.Contains(eventObj.Category) == false)
            {
                return;
            }

            var accountDbContext = Context.GetAccountDbContext(accountId);
            var component        = accountDbContext.GetComponentRepository().GetById(componentId);

            // если выключен, то ничего не делаем
            if (component.CanProcess == false)
            {
                return;
            }

            // отфильтруем события, которые не могут влиять на статус

            // если событие НЕ длится
            if (eventObj.StartDate == eventObj.ActualDate)
            {
                // возможно такие события могут продлить EndDate до eventObj.StartDate
                // пока будем их игнорировать, чтобы сделать алгоритм проще
                return;
            }
            var statusId           = component.EventsStatusId;
            var statusService      = Context.BulbService;
            var noSignalImportance = Api.EventImportance.Unknown;

            // получаем или создаем статус (колбаску)
            var request = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = statusId
            };

            using (var data = AllCaches.StatusDatas.Write(request))
            {
                DateTime processDate = DateTime.Now;

                // событие из будущего (завершается через 5 минут)
                if (eventObj.EndDate > processDate + TimeSpan.FromMinutes(5))
                {
                    // пусть будет, эту проблему должен решать отправитель
                    //return UpdateStatusResult.Canceled();
                }

                // события из прошлого игнорируем, иначе будет ерунда при обновлении родительской колбасы
                // т.е. будет несоответствие наложения дочерних колбасок на родительскую
                if (eventObj.ActualDate <= processDate)
                {
                    return;
                }

                // если событие протухло
                if (eventObj.ActualDate <= data.EndDate)
                {
                    return;
                }

                var status = MonitoringStatusHelper.Get(eventObj.Importance);
                var signal = BulbSignal.Create(processDate, eventObj, noSignalImportance);

                // 0. если это первый сигнал после пробела
                if (data.HasSignal == false)
                {
                    statusService.SetSignal(data.Id, signal);
                    return;
                }

                // 1. событие менее важное, чем текущий статус
                if (status < data.Status)
                {
                    // событие поменяло важность, нодо расчитать занова!
                    if (data.LastEventId == eventObj.Id)
                    {
                        CalculateComponentEventsStatus(accountId, component.EventsStatusId);
                        return;
                    }

                    // текущий статус актуальней
                    if (data.ActualDate >= eventObj.ActualDate)
                    {
                        return;
                    }

                    // на актуальный статус менее важные события не влияют
                    if (data.Actual(processDate))
                    {
                        return;
                    }

                    // статус протух, а событие актуальное
                    // нужно расчитать, т.к. могут быть более важные актуальные события
                    CalculateComponentEventsStatus(accountId, component.EventsStatusId);
                    return;
                }

                // 2. событие такой же важности как статус
                if (status == data.Status)
                {
                    // продлеваем
                    statusService.SetSignal(data.Id, signal);
                    return;
                }

                // 3. событие более важное, чем текущий статус
                statusService.SetSignal(data.Id, signal);
            }
        }