I throttle events for all sinks registered in a Serilog logger: only 5 events per minute are allowed to be emitted by any sink.
I need a record (a Serilog event) in all the sinks that the throttling actually took place, otherwise I don't know if the exact max. allowed amount of events has been logged per minute or more events have been throttled.
I use my own throttle approach similar to the "official" PoC. I create an ILogEventFilter, and in its IsEnabled method I check the current rate of the events and want to write my "throttling happened" event to all the sinks directly (otherwise, e.g. if I write this event via the logger, I'm in endless recursion):
public class EventFilter : ILogEventFilter
{
public bool IsEnabled(LogEvent logEvent)
{
var enabled = ThrottledInvoker<string>.Invoke( // internally counts the calls, the method signature is simplified for the sake of this code sample
() => // method to call if throttling takes place
{
// send additional events/records into the sinks about throttling
var throttlingInfoEvent = new LogEvent(
logEvent.Timestamp,
logEvent.Level,
null,
MessageTemplate.Empty,
new[] {
new LogEventProperty("CustomMessage", new ScalarValue("Too many events of this kind.")),
});
// TODO: how to write to registered sinks?
sink1.Emit(throttlingInfoEvent);
sink2.Emit(throttlingInfoEvent);
// ...
// sinkN.Emit(throttlingInfoEvent);
},
TimeSpan.FromMinutes(1), // time period
5); // max. allowed event count per time period
return enabled;
}
}
I have found no Logger.Sinks property or anything alike. I understand that I can use reflection (issue on GitHub) to get private _sinks fields of my logger's aggregated sinks, but that smells.
I could initialize my filter before passing it to LoggerConfiguration.Filter.With() method, and pass all the sinks as my filter's constructor arguments. But the logger and sinks are configured by another component of the application which I don't have access to.
Is there a right/official way to do what I want?