11

So I've been trying various ways to get Event Log data in bulk (1000+ records/second).

I need something that can filter out old logs, right now I store the last recorded event record ID and retrieve all records where the event ID is greater than that....

I've tried EventLogQuery/EventLogReader, this works fast except when I want to pull message data, in order to get a formatted message for security logs I need to call EventLogRecord.FormattedMessage(), this brings my log speed to about 150/second with easy to format logs, even worse with complicated ones.

I've tried System.Diagnoistics.EventLog, this doesn't allow me to build filters, so every time I run this it must load ALL event logs, then I can parse off any duplicates (from the last scan). I have a sever that has 200k event logs over the past two days, memory usage gets terrible due to this, so that is a no-go.

I've tried WMI using System.Management.ManagementObjectCollection, this has filtering and can pull message data from the security event log FAST (approaching ~1000/second), however it will go to about 50/60k and start to drag it's feet, down to doing about 1-2/second, eventually I'll get a Quota Violation error. :(

So either:

Is there a way to avoid the quota violation error, or do I want to use some other method for pulling event logs at this speed?

Edit:

I wrote a blog post detailing what I've learned about this:

http://www.roushtech.net/2013/10/30/high-performance-event-log-reading/

Mostly: WINAPI is your best bet, either write C++/CLR or use PInvoke.

7
  • 2
    Out of curiosity, why do you need to do this? If you need all your event log records and need them to be searchable it might be better to write a program that puts them into a database periodically and cleans up the event log. Then use your database to search.
    – lahsrah
    Commented Aug 3, 2011 at 22:02
  • From the local machine, or a remote one? Commented Aug 3, 2011 at 22:07
  • Can you show the WQL sentence which you are using to retrieve the Event log?
    – RRUZ
    Commented Aug 3, 2011 at 22:26
  • @sylon: That is pretty much what we're trying to do, but I'm not sure how I feel about purging logs on every run. Commented Aug 4, 2011 at 13:50
  • @csharptest.net: local machine. Commented Aug 4, 2011 at 13:51

2 Answers 2

3

I might look into the command-line utility:

C:/> Wevtutil.exe qe Application /f:XML

Documentation: http://technet.microsoft.com/en-us/library/cc732848(WS.10).aspx

It will save a bookmark and continue from bookmark as well as serve to process much more complicated queries.

For example, let's say you want all events of id 1530, in a group of 1000, from the last bookmark you saved, pre-rendered in english:

Wevtutil qe Application /f:RenderedXml /bm:bookmark.pos /sbm:bookmark.pos /c:1000 /e:Log /l:en-us /q:Event[System/EventID='1530']

This yeilds events that look like:

<Log>
  <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
      <Provider Name="Microsoft-Windows-User Profiles Service" Guid="{89B1E9F0-5AFF-44A6-9B44-0A07A7CE5845}"/>
      <EventID>1530</EventID>
      <Version>0</Version>
      <Level>3</Level>
      <Task>0</Task>
      <Opcode>0</Opcode>
      <Keywords>0x8000000000000000</Keywords>
      <TimeCreated SystemTime="2011-06-16T22:55:32.305140500Z"/>
      <EventRecordID>26196</EventRecordID>
      <Correlation/>
      <Execution ThreadID="4168" ProcessID="1660"/>
      <Channel>Application</Channel>
      <Computer>hostname.WORKGROUP</Computer>
      <Security UserID="S-1-5-18"/>
    </System>
    <EventData Name="EVENT_HIVE_LEAK">
      <Data Name="Detail">0 user registry handles leaked from \Registry\User\S-1-5-82: </Data>
    </EventData>
    <RenderingInfo Culture="en-US">
      <Message>Windows detected your registry file is still in use by other applications or services. The file will be unloaded now. The applications or services that hold your registry file may not function properly afterwards. DETAIL - 0 user registry handles leaked from \Registry\User\S-1-5-82: </Message>
      <Level>Warning</Level>
      <Task/>
      <Opcode>Info</Opcode>
      <Channel>Application</Channel>
      <Provider>Microsoft-Windows-User Profile Service</Provider>
      <Keywords/>
    </RenderingInfo>
  </Event>

Using a fast light-weight xml parser, you should be able to scream through this data while in parallel producing the next result page. It's not even necessary to write this to disk if you capture the process output directly. Just be sure you are also capturing the std::error since this utility will also write errors to that output.

6
  • I looked at Wevtutil.exe before and it wasn't up to par with what I needed, until you gave me /F:RenderedXML, which gives me full message information. This seems to be perfect, I'll run some tests against it. Commented Aug 4, 2011 at 13:54
  • Though I'm only pushing about 600 records/second on my development system, this should be enough. I can ship all of one day's logs in about 2.5 minutes, I'll average about .5 seconds of execution/query on our setup. Once I have this fully implemented and running I'll get back to you with my results. Commented Aug 4, 2011 at 14:37
  • Interesting, this tool doesn't exist on Windows 2003. :( Commented Aug 5, 2011 at 18:31
  • Let me ask:What do you do with your events, after you've collected them? My personal solution for the problem was to use WMI EventQueries and let the servers send me all relevant events. This way, I am getting a more stream alike behavior where I can find time to evaluate, filter [remote and local] and store them away. I am doing this since ten years with my manfbraun.de/EventlogCollectorServices [IE REQUIRED][just mentioned, no download]. br++mabra
    – mabra
    Commented Aug 10, 2011 at 21:13
  • I'd be filtering them and pushing them to a server. I've found that WMI EventQueries is not nearly fast enough (and puts a lot of strain on DCOM) due to the volume of events. Commented Aug 22, 2011 at 21:16
2

I found that managed code was too slow and I ended up using the win32 APIs to retrieve the event logs (local and/or remote). They are easy enough to implement and there are a lot of examples out there of how to do it. It will also be much faster than anything you try and do with xml.

New API: http://msdn.microsoft.com/en-us/library/aa385780(v=vs.85).aspx

Old API: http://msdn.microsoft.com/en-us/library/aa363652(v=vs.85).aspx

I also found that the pre-vista API worked fine for what I needed and actually performed better than the new API on post-vista machines.

3
  • What kind of increase in speed can I expect from this? I'm not seeing a way to filter this at the API level at first glance, and I'm worried about digging millions of records to pull 10-100k (end of the month type stuff), of course I could probably reverse seek and be ok. If you've found a reasonable way to use it though I'll keep the documentation in my back pocket and my mind on a C++/CLR project that will allow me to build a managed object for C# to use. Commented Aug 5, 2011 at 13:22
  • Interesting enough, I'm having absolutely no luck even implementing their example, format message fails spectacularly. (Event category shows a basic message, format message for the body results in error 317), regardless of letting the system format it or specifying the Application Event Log DLL. Event data dump pukes binary garbage. Commented Aug 8, 2011 at 15:24
  • Edit: It's entirely my application, dropped the example into it's own project, works fine. Apparently letting the message be formatted by the system breaks a lot of things, and I'll just have to add support for lookups in the registry. Commented Aug 8, 2011 at 15:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.