Skip to content

[Robustness] EventLogReader.ReadEvents — materializes the entire result set in memory before MaxResults limit can apply #970

@Christophe-Rogiers

Description

@Christophe-Rogiers

Severity: Warning

File: src/Servy.Core/Logging/EventLogReader.cs

Lines: 15-33

Code:

public IEnumerable<ServyEventLogEntry> ReadEvents(EventLogQuery query)
{
    using (var reader = new System.Diagnostics.Eventing.Reader.EventLogReader(query))
    {
        var results = new List<ServyEventLogEntry>();

        for (EventRecord evt = reader.ReadEvent(); evt != null; evt = reader.ReadEvent())
        {
            using (evt) { results.Add(MapToDto(evt)); }
        }

        return results;
    }
}

Explanation:

ReadEvents reads every record matching the EventLogQuery into an in-memory List<ServyEventLogEntry> before returning. The caller (EventLogService.SearchAsync) then applies MaxResults = 10_000 after the fact, by breaking out of its own iteration:

results.Add(evt);
if (results.Count >= MaxResults) break;

But that break only short-circuits the SECOND filter loop — ReadEvents has already pulled and materialized the entire underlying result set. On a busy host (Application log can hold tens or hundreds of thousands of entries that match a broad query), this can balloon memory and freeze the UI thread that triggered the query, even though the visible result is capped at 10,000.

Suggested fix:

Make ReadEvents a true streaming enumerator (yield return), so the caller-side break actually stops the SCM-side cursor:

public IEnumerable<ServyEventLogEntry> ReadEvents(EventLogQuery query)
{
    using (var reader = new System.Diagnostics.Eventing.Reader.EventLogReader(query))
    {
        for (EventRecord evt = reader.ReadEvent(); evt != null; evt = reader.ReadEvent())
        {
            using (evt) { yield return MapToDto(evt); }
        }
    }
}

Alternatively, pass MaxResults into ReadEvents and stop reading once that many records have been mapped.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions