Обработка событий из журнала событий и реагирование по определенному шаблону (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 ответа:
Если 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.
Увидимся позже, Мэтью!