Vixen
02b45cc4
csharp
public sealed class LogRateLimiter

Suppression of repeated events: the first few in each window get through, the rest are counted, and the next one that gets through carries the count so the log can say … (repeated 4 812 times).

No guide page documents this yet — the page shows what the code says about itself.

Remarks

Doc 13 asks for this by name, and the reason is not tidiness. One warning inside the frame loop is sixty lines a second, which is a log file nobody can read, a console the editor cannot keep up with, and — because the enabled path formats a string — real time spent on the sixty thousandth copy of a message whose first copy said everything.

Identity is the pair (category, event id), not the formatted text. ADR-008 gives every call site a stable id from docs/manual/log-events.md, so the id already identifies the message; hashing the formatted string instead would mean formatting it before deciding to drop it, which is the cost this exists to avoid. The consequence is that a warning whose arguments change every frame still collapses to one line plus a count — for flood control that is the wanted behaviour, and the line that survives is the most recent one rather than the first.

It fails open. The table of tracked events is bounded, and when it is full and nothing in it is stale enough to evict, novel events are admitted untracked rather than dropped. A rate limiter that loses the first report of a new error because a different event filled its table is worse than no rate limiter.

Records at Critical are never suppressed. There is no flood of them worth protecting against, and the one time there is, seeing all of them is the point.

A count is carried by the next record of the same identity, so an event that floods and then stops leaves its final tally unreported in the log itself. That is the cost of never emitting a line nobody asked for, from a timer of this class's own; SuppressedCount is the total, and a host that wants the tally reports it at shutdown alongside the other dropped-record counters.

Fields and properties (8)

  • public const int DefaultBurst

    How many records with the same identity pass per window by default.

  • public const int DefaultMaxTrackedEvents

    How many distinct events are tracked by default.

  • public TimeSpan Window

    How long a window lasts.

  • public int Burst

    How many records with the same identity pass per window.

  • public int MaxTrackedEvents

    How many distinct events are tracked at once.

  • public long SuppressedCount

    How many records this limiter has dropped, over its whole life.

  • public long UntrackedCount

    How many records were admitted without being tracked because the table was full — the count of times it failed open, which is what says the table is too small for the workload.

  • public int TrackedEventCount

    How many distinct events are being tracked right now.

Methods (3)

  • public LogRateLimiter(TimeSpan window, int burst = 4, int maxTrackedEvents = 1024, TimeProvider? timeProvider = null)

    Creates a limiter.

  • public bool TryAdmit(string category, EventId eventId, LogLevel level, out int suppressedCount)

    Decides whether a record gets through.

  • public void Reset()

    Forgets every tracked event, and with them every pending count. Counters keep their totals.

Used by (2)

  • LogSinkVixen.Core.Diagnostics
  • SinkTestsVixen.Core.Diagnostics.Tests