2012-04-11 19 views
6

Necesito procesar eventos provenientes de EventLog. Esto es fácil usando el EventLogWatcher que se conecta al evento EventRecordWritten. Sin embargo, la consulta en la que estoy interesado (eventid == 299 || eventid == 500) proporciona más eventos de los que necesito. Aquí está un ejemplo de la corrienteProcesar eventos del Registro de eventos y reaccionar en un determinado patrón (Rx?)

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

Estoy interesado en el evento 299 y el primer evento 500 que coincide con el ID de correlación del evento 299. Yo les marcó en la corriente arriba, que es la colección de salida Estoy interesado en: [X1, X2, Y1, Y2, Z1, Z2] lo que probablemente es un diccionario utilizando el identificador de correlación como una llave y una tupla de EventRecord como el valor

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

En eventos en general puedan surgir en orden (299 y luego 500) pero en una situación de concurrencia alta preveo que se unirán dos 299 eventos y luego los 500 eventos, por lo que no deseo confiar en el orden en que se producen los eventos. El ID de correlación es la clave para correlacionarlos (que es la primera propiedad del evento eventRecord.Properties[0])

Creo que esto se puede resolver con una máquina de estado, pero sería interesante ver si alguien encuentra una solución con Rx representado por una consulta a un observable. Eso mantendría la lógica de coincidencia de patrones en un solo lugar.

ACTUALIZACIÓN: aquí está la respuesta a la solución. Gracias a Gideon, ¡fue exactamente el punto de partida que necesitaba!

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

Gracias de antemano, Matias

Respuesta

5

Si los 299 eventos siempre vienen antes de los 500 eventos, SelectMany y Where deberían ser suficientes.

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} 

Si la fuente tiene múltiples 500 eventos por cada 299 correlacionados caso, es posible que tenga que cambiar a la sintaxis lambda y añadir un Take(1) al segundo abono.

+0

¡listo! Gracias Gideon ... la consulta usando lambda y take (1) se incluyó en mi respuesta – woloski

0

que no sé lo que quiere decir con "una máquina de estados".

Pero podría escribir un observador que recopile (eventid == 299 || eventid == 500). Usando la estrategia de aceleración (recopilar los 1000 eventos más recientes, o el último minuto, no sé), plantea un evento cuando detecta un par de eventos 299, 500 tienen el mismo guid, eliminándolo de su diccionario interno/lista de eventos.

Entonces, ese amable observador ES EL observable para el resto de su sistema.

Tal vez una lista se puede recoger los acontecimientos, y cuando se detecta un evento nuevo, algo así como

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

podría ser suficiente en el rendimiento, en lugar de tener un diccionario por GUID.

Hasta luego, Mathew!

+0

Gracias Angel ... Almacenar en memoria los eventos y analizarlos fue mi primer acercamiento. Yo quería algo puro RX. – woloski

2

Debería observar usando Observable.When, with Joins. Esto te permitirá componer patrones de unión complejos como desees.

Por ejemplo, vea, https://stackoverflow.com/a/3868608/13131 y Guide to System.Reactive.Joins.

+0

Intenté usar And y When, pero no pude lograr el comportamiento correcto. Estoy seguro de que se puede resolver de alguna manera, todavía necesito más práctica con RX :). ¡Gracias por tu ayuda! – woloski

Cuestiones relacionadas