gpt4 book ai didi

c# - 高效快速地阅读 Windows 日志

转载 作者:可可西里 更新时间:2023-11-01 13:26:29 25 4
gpt4 key购买 nike

我想要完成的是一个 C# 应用程序,它将从 Windows 事件日志中读取日志并将它们存储在其他地方。这必须很快,因为一些将安装它的设备会生成大量日志/秒。

到目前为止,我已经尝试了三种方法:

本地WMI:效果不佳,需要加载的集合大小导致的错误和异常太多。EventLogReader:我认为这是完美的解决方案,因为它允许您使用 XPath 表达式查询事件日志。问题是,当您想要获取每个日志的消息内容时(通过调用 FormatDescription()),长时间收集会花费太多时间。例如:我可以在 0.11 秒内读取 12k 日志,如果我只是浏览它们的话。如果我为每个日志添加一行来存储消息,则需要将近 6 分钟才能完成完全相同的操作,这对于如此少的日志数量来说简直是疯了。我不知道是否可以对 EventLogReader 进行任何类型的优化以更快地获取消息,我在 MS 文档和 Internet 上都找不到任何内容。

我还发现您可以使用名为 EventLog 的类来读取日志条目。但是,这项技术不允许您输入任何类型的过滤器,因此您基本上必须将整个日志列表加载到内存中,然后根据需要将其过滤掉。这是一个例子:

EventLog eventLog = EventLog.GetEventLogs().FirstOrDefault(el => el.Log.Equals("Security", StringComparison.OrdinalIgnoreCase));
var newEntries = (from entry in eventLog.Entries.OfType()
orderby entry.TimeWritten ascending
where entry.TimeWritten > takefrom
select entry);

尽管在获取消息方面速度更快,但内存使用量可能很高,我不想在部署此解决方案的设备上造成任何问题。

谁能帮我解决这个问题?我找不到任何解决方法或方法来实现这样的目标。

谢谢!

最佳答案

您可以试试 EventLogReader 类。参见 https://learn.microsoft.com/en-us/previous-versions/bb671200(v=vs.90)

它比 EventLog 类更好,因为访问 EventLog.Entries 集合具有令人讨厌的属性,即当您从中读取时,它的计数可能会发生变化。更糟糕的是,读取发生在 IO 线程池线程上,这将使您的应用程序因未处理的异常而崩溃。至少几年前是这样。

EventLogReader 还使您能够提供查询字符串来过滤您感兴趣的事件。如果您编写新应用程序,这就是方法。

这是一个应用程序,展示了如何并行阅读:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Threading.Tasks;

namespace EventLogReading
{
class Program
{
static volatile bool myHasStoppedReading = false;

static void ParseEventsParallel()
{
var sw = Stopwatch.StartNew();
var query = new EventLogQuery("Application", PathType.LogName, "*");

const int BatchSize = 100;

ConcurrentQueue<EventRecord> events = new ConcurrentQueue<EventRecord>();
var readerTask = Task.Factory.StartNew(() =>
{
using (EventLogReader reader = new EventLogReader(query))
{
EventRecord ev;
bool bFirst = true;
int count = 0;
while ((ev = reader.ReadEvent()) != null)
{
if ( count % BatchSize == 0)
{
events.Enqueue(ev);
}
count++;
}
}
myHasStoppedReading = true;
});

ConcurrentQueue<KeyValuePair<string, EventRecord>> eventsWithStrings = new ConcurrentQueue<KeyValuePair<string, EventRecord>>();

Action conversion = () =>
{
EventRecord ev = null;
using (var reader = new EventLogReader(query))
{
while (!myHasStoppedReading || events.TryDequeue(out ev))
{
if (ev != null)
{
reader.Seek(ev.Bookmark);
for (int i = 0; i < BatchSize; i++)
{
ev = reader.ReadEvent();
if (ev == null)
{
break;
}
eventsWithStrings.Enqueue(new KeyValuePair<string, EventRecord>(ev.FormatDescription(), ev));
}
}
}
}
};

Parallel.Invoke(Enumerable.Repeat(conversion, 8).ToArray());

sw.Stop();
Console.WriteLine($"Got {eventsWithStrings.Count} events with strings in {sw.Elapsed.TotalMilliseconds:N3}ms");
}

static void ParseEvents()
{
var sw = Stopwatch.StartNew();
List<KeyValuePair<string, EventRecord>> parsedEvents = new List<KeyValuePair<string, EventRecord>>();

using (EventLogReader reader = new EventLogReader(new EventLogQuery("Application", PathType.LogName, "*")))
{
EventRecord ev;
while ((ev = reader.ReadEvent()) != null)
{
parsedEvents.Add(new KeyValuePair<string, EventRecord>(ev.FormatDescription(), ev));
}
}

sw.Stop();
Console.WriteLine($"Got {parsedEvents.Count} events with strings in {sw.Elapsed.TotalMilliseconds:N3}ms");
}

static void Main(string[] args)
{
ParseEvents();
ParseEventsParallel();
}
}
}
Got 20322 events with strings in 19,320.047ms
Got 20323 events with strings in 5,327.064ms

这提供了 4 倍的体面加速。我需要使用一些技巧来加快速度,因为出于某些奇怪的原因,ProviderMetadataCachedInformation 类不是线程安全的,并且在 Format 方法内部使用了一个锁(this),这会阻止并行读取.关键技巧是再次打开转换线程中的事件日志,然后通过事件书签 Api 在那里读取一堆查询事件。这样您就可以独立地格式化字符串。

更新1

我在 .NET 5 中进行了更改,将性能提高了三倍,最高可达 20。请参阅 https://github.com/dotnet/runtime/issues/34568。您还可以从 .NET Core 复制 EventLogReader 类并改用这个类,这将为您提供相同的加速。

我的博客文章描述了完整的故事:https://aloiskraus.wordpress.com/2020/07/20/ms-performance-hud-analyze-eventlog-reading-performance-in-realtime/

关于c# - 高效快速地阅读 Windows 日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53430475/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com