高性能事件日志

11

我一直在尝试各种方法以批量获取事件日志数据(1000+条/秒)。

我需要一些可以过滤旧日志的东西,现在我存储了最后记录的事件记录ID,并检索所有事件ID大于该ID的记录...

我尝试了EventLogQuery/EventLogReader,这个方法速度很快,但是当我想要提取消息数据时就变慢了。为了获取安全日志的格式化消息,我需要调用EventLogRecord.FormattedMessage(),这会使我的日志速度减慢到每秒约150条,即便是易于格式化的日志也会更差。

我尝试了System.Diagnostics.EventLog,这个方法不允许我构建过滤器,所以每次运行此方法都必须加载所有事件日志,然后我可以解析任何重复项(从上次扫描开始)。我有一个服务器,在过去的两天中有200k个事件日志,由于这个原因内存使用情况变得可怕,所以这是不行的。

我尝试了WMI,使用System.Management.ManagementObjectCollection,这个方法具有过滤功能,可以快速地从安全事件日志中提取消息数据(接近每秒1000条),但是它会到达大约50/60k并开始变慢,最终只能做大约1-2条/秒,最终我会得到Quota Violation错误。

所以要么:

有没有办法避免配额违规错误,或者我应该使用其他方法来以这样的速度获取事件日志?

编辑:

我写了一篇关于此的博客文章:

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

总的来说:WINAPI是您最好的选择,可以编写C++/CLR或使用PInvoke。


2
出于好奇,你为什么需要这样做?如果你需要所有的事件日志记录,并且需要对它们进行搜索,最好编写一个程序,定期将它们放入数据库中并清理事件日志。然后使用你的数据库进行搜索。 - lahsrah
从本地机器还是远程机器? - csharptest.net
你能展示一下你正在使用的WQL语句来检索事件日志吗? - RRUZ
@RRUZ:SELECT * FROM Win32_NTLogEvent WHERE logfile='Security',这个还没有实现ID截止(在它截断之前无法进行主扫描)。 - StrangeWill
@StrangeWill你得出了什么结论?Wevtutil.exe是最合适的解决方案吗? - Ryan Penfold
显示剩余2条评论
2个回答

3

我可以研究一下命令行工具:

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

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

它可以保存书签并从书签继续,同时还可以处理更复杂的查询。

例如,假设您希望获取所有ID为1530的事件,每组1000个,从上次保存的书签开始,以英语预渲染:

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

这将产生像这样的事件:

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

使用快速轻量级的XML解析器,您应该能够在并行生成下一个结果页面的同时快速处理这些数据。如果您直接捕获进程输出,则甚至不需要将其写入磁盘。只需确保您还捕获了std::error,因为此实用程序也会将错误写入该输出。


我之前看过Wevtutil.exe,但它并不符合我的需求,直到你给了我/F:RenderedXML命令,这使得我可以获取全部消息信息。这似乎非常完美,我会对其进行一些测试。 - StrangeWill
虽然我在我的开发系统上只能推送大约600条记录/秒,但这应该足够了。我可以在大约2.5分钟内发送一整天的日志,我们的设置平均执行/查询时间约为0.5秒。一旦我完全实施并运行它,我会向您反馈我的结果。 - StrangeWill
有趣的是,在Windows 2003上不存在这个工具。 :( - StrangeWill
让我问一下:在收集事件后,您会怎样处理它们?我个人解决问题的方法是使用WMI EventQueries,让服务器将所有相关事件发送给我。这样,我可以得到更类似于流的行为,可以找到时间进行评估,筛选[远程和本地]并将其存储起来。自从十年前以来,我一直使用我的http://www.manfbraun.de/EventlogCollectorServices/ [需要IE][仅提及,无需下载]。br++mabra - mabra
我将对它们进行过滤并将它们推送到服务器。由于事件数量太大,我发现WMI事件查询速度远远不够快(并且对DCOM造成了很大压力)。 - StrangeWill
嗯,你的EventQuery是什么??我曾经看到服务器每秒发送几百个事件[!!!!而我正在查询安全事件{通常不这样做}]。我以这种方式监视大约125台服务器,并且 - 在让wmi过滤发送机器之后 - 我得到了1/s和300/s之间的数据[很少]。++mabra - mabra

2

我能从中期望什么样的速度提升?乍一看,我没有看到在API级别过滤它的方法,我担心要挖掘数百万条记录来获取10-100k(月末类型的东西),当然我可能可以反向查找并且没问题。如果你找到了一个合理的使用方法,我会把文档放在口袋里,考虑用C++/CLR项目来构建一个托管对象供C#使用。 - StrangeWill
有趣的是,我在实现他们的示例时完全没有运气,格式化消息失败得很惨。 (事件类别显示基本消息,为正文格式化消息导致错误317),无论是让系统格式化还是指定应用程序事件日志DLL。事件数据转储会产生二进制垃圾。 - StrangeWill
编辑:这完全是我的应用程序,将示例放入自己的项目中,运行良好。显然,让系统格式化消息会破坏很多东西,我只能添加对注册表查找的支持。 - StrangeWill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接