Processing events from the event log and responding to a specific pattern (Rx?)

I need to handle events from EventLog. This is easy to use with the EventLogWatcher associated with the EventRecordWritten event. However, the query I'm interested in (eventid == 299 || eventid == 500) provides more events than I need. Below is an example of a stream

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... 

I am interested in event 299 and the first event 500, which corresponds to the correlation identifier of event 299. I noted them in the stream above that the output collection that interests me is: [X1, X2, Y1, Y2, Z1, Z2] , which is probably a dictionary, using the correlation identifier as the key and EventRecord tuple as the value

 { 1AD.., <X1, X2> } { 43B.., <Y1, Y2> } { EDB.., <Z1, Z2> } 

In the general case, events can occur (299, and then 500), but in conditions of a high level of concurrency, I foresee two 299 events that come together and then 500 events, so I do not want to rely on the order of events to arrive, the correlation ID is the key to their correlations (which is the first property of the eventRecord.Properties[0] event)

I think this can be resolved using a state machine, but it would be interesting to know if anyone has a solution with Rx represented by a query for the observable. This will support the pattern matching logic in one place.

UPDATE : here is the answer to the solution. Thank you, Gideon, this was exactly the starting point I needed!

 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 }); 

Thanks in advance, Matthias

+6
source share
3 answers

If 299 events are always present before 500 events, SelectMany and Where should be sufficient.

 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} 

If your source has several 500 events for each 299 correlated event, you may need to switch to lambda syntax and add Take(1) to the second subscription.

+5
source

You should look at using Observable.When using Joins. This will allow you to create complex union patterns as you wish.

For example, see fooobar.com/questions/258848 / ... and the System.Reactive.Joins Guide .

+2
source

I don’t know what you mean with a state machine.

But you could write an observer that collects (eventid == 299 || eventid == 500). Using a throttle strategy (collect the last 1000 events or the last minute, I don't know), he raises an event when he detects a couple of events. 299, 500 have the same guid, then deleting from their internal dictionary / list of Events.

Then, an observer of this kind is EXCLUDED for the rest of your system.

Perhaps the list may collect events, and when a new event is detected, something like

events.Where (e => e.eventid == newevent.eventid && ((e.id == 299 & newev.id == 500) || (e.id == 500 & newev.id == 299))

may be enough in performance, instead of having a guid dictionary.

See you later, Matthew!

0
source

Source: https://habr.com/ru/post/912934/


All Articles