Обработка событий из журнала событий и реагирование по определенному шаблону (Rx?)


Мне нужно обработать события, поступающие из EventLog. Это легко сделать с помощьюEventLogWatcher , прикрепленного к событию Eventrecordwrited. Однако запрос, который меня интересует (eventid = = 299 | / eventid == 500), предоставляет больше событий, чем мне нужно. Вот пример потока

Event ID   Correlation ID
299        1AD...  (this is actually a guid)  X1
500        1AD...                             X2
500        1AD...
500        1AD...
299        43B...                             Y1
299        EDB...                             Z1
500        43B...                             Y2
500        EDB...                             Z2
500        43B...
500        43B...
Меня интересует событие 299 и первое событие 500, которое соответствует корреляционному идентификатору события 299. Я отметил их в потоке выше, это выходная коллекция, которой я являюсь интересует: [X1, X2, Y1, Y2, Z1, Z2], который, вероятно, является словарем, использующим идентификатор корреляции в качестве ключа и кортеж EventRecord в качестве значения
{ 1AD.., <X1, X2> }
{ 43B.., <Y1, Y2> }
{ EDB.., <Z1, Z2> }

В общем случае события могут приходить по порядку (299 и затем 500), но в ситуации с высоким параллелизмом я предвижу, что два события 299 сойдутся вместе, а затем 500 событий, поэтому я не хочу полагаться на порядок событий. Идентификатор корреляции является ключом для их корреляции (что является первым свойством события eventRecord.Properties[0])

Я думаю, что это можно решить с помощью государства но было бы интересно посмотреть, если кто-нибудь придумает решение с Rx, представленное запросом к наблюдаемому. Это позволит сохранить логику сопоставления шаблонов в одном месте.

UPDATE : вот ответ на решение. Спасибо Гидеону, это была именно та отправная точка, в которой я нуждалась!

var pairs = events
            .Where(e299 => e299.EventArgs.EventRecord.Id == 299)
            .SelectMany(e299 => events.Where(e500 => e500.EventArgs.EventRecord.Id == 500 &&
                                                    e299.EventArgs.EventRecord.Properties[0].Value.ToString() ==
                                                    e500.EventArgs.EventRecord.Properties[0].Value.ToString())
                                    .Take(1), 
                        (e299, e500) => new { First = e299, Second = e500 });

Заранее спасибо, Матиас

3 6

3 ответа:

Если 299 событий всегда предшествуют 500 событиям, то SelectMany и Where должно быть достаточно.

var events; //declared somewhere

var pairs = from e299 in events
            where e299.eventid == 299
            from e500 in events
            where e500.eventid == 500 &&
                  e299.Correlation == e500.Correlation
            select new with {Correlation = e299.Correlation,
                             First = e299,
                             Second = e500}

Если ваш источник содержит несколько 500 событий для каждого коррелированного события 299, вам может потребоваться переключиться на лямбда-синтаксис и добавить Take(1) ко второй подписке.

Вы должны смотреть на использование Observable.Когда, с присоединениями. Это позволит вам создавать сложные паттерны соединения, как вы хотите.

Например смотрите, https://stackoverflow.com/a/3868608/13131 и руководство по системе.Реактивный.Присоединяется .

Я не знаю, что вы подразумеваете под "государственной машиной".

Но вы можете написать наблюдатель, который собирает (eventid = = 299 | / eventid = = 500). Используя стратегию дроссельной заслонки (соберите последние 1000 событий или последнюю минуту, я не знаю), он вызывает событие, когда обнаруживает пару событий 299, 500 имеют один и тот же guid, удаляя затем из своего внутреннего словаря/списка событий.

Тогда этот добрый наблюдатель является наблюдаемым для остальной части вашей системы.

Может быть, список мог бы соберите события, и когда новое событие обнаружено, что-то вроде

События.Где (e => e. eventid = = newevent.код события && ((е.идентификатора == 299 && newev.ИД == 500) || (электронные.идентификатора == 500 && newev.ИД == 299))

Может быть достаточно в производительности, вместо того, чтобы иметь словарь по guid.

Увидимся позже, Мэтью!