Dynamic Serilog Filtering
Another quick note to put a “hidden” Serilog feature onto the radar. By now, LoggingLevelSwitch
is quite well-known as a way to change the Serilog level at runtime:
var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Information);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.Console(theme: AnsiConsoleTheme.Code)
.CreateLogger();
Log.Debug("No one will see this");
// Later, when things go wrong...
levelSwitch.MinimumLevel = LogEventLevel.Debug;
Log.Debug("This event is captured");
You can use LoggingLevelSwitch
to build remote level control into your ops infrastucture: this was always a favorite feature in ops dashboards for the various messaging-driven systems I’ve worked on. The basic idea is to have all endpoints accept a control message that sets their logging level, and a management UI to trigger it. (Remote level control is so hard to live without once you’ve had it that I built support for it directly into Serilog.Sinks.Seq to enable log level control per API key.)
But what happens when you suffer a log flood from a misbehaving app or service? Switching the level up to Error
or Fatal
can help, but then you completely lose visibility into what the app is doing, so have no option but to immediately redeploy it with the problem events suppressed.
The little-known LoggingFilterSwitch
is Serilog’s answer to this problem. It’s currently tucked away in the Serilog.Filters.Expressions package, but I can see it migrating to the core package in some form, someday.
// Initially include everything with `true`
var filterSwitch = new LoggingFilterSwitch("true");
Log.Logger = new LoggerConfiguration()
.Filter.ControlledBy(filterSwitch)
.WriteTo.Console(theme: AnsiConsoleTheme.Code)
.CreateLogger();
Log.Error("Noisy failure!");
// Sssh...
filterSwitch.Expression = "@Message not like 'Noisy%'";
Log.Error("Noisy failure!");
(I’ve omitted it from the example, but you’d generally use both LoggingLevelSwitch
and LoggingFilterSwitch
together in the same configuration.)
The expression language includes support for event properties, text, regular expressions, math, logic, and even some esoteric features inherited from Seq like collection wildcard comparisons:
Tags[?] = 'test'
How to push filters out to applications and services is left to the imagination - if you haven’t explored the possibility of controlling your logging remotely, though, it’s well worth investigating. Have fun!