Search code examples
c#.net.net-coreserilog

Serilog Range level filtering


In log4net you have the option to declare different fileappenders with a levelMin levelMax range. In that way you can have one file for debug and one file for error. How can I have the same behavior in serilog file sink. I have this code but you are only allowed to specify MinimumLevel

Log.Logger = new LoggerConfiguration()
            .WriteTo.Async(a =>
            {
                a.RollingFile($"{AppDomain.CurrentDomain.BaseDirectory}\\Logs\\error.txt", 
                    restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
            })
            .WriteTo.Async(a =>
            {
                a.RollingFile($"{AppDomain.CurrentDomain.BaseDirectory}\\Logs\\log.txt",
                    restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug);
            })
            .CreateLogger();

It creates two files but in the log.txt I also see the error level messages


Solution

  • In Serilog you can do use sub-loggers with a filter applied to each of them:

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Verbose()
        .WriteTo.Logger(c =>
            c.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug)
                .WriteTo.File("Debug.log"))
        .WriteTo.Logger(c =>
            c.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
                .WriteTo.File("Error.log"))
        .CreateLogger();
    
    Log.Debug("This goes to Debug.log only");
    Log.Error("This goes to Error.log only");
    
    Log.CloseAndFlush();
    

    Alternatively, you can use the Serilog.Sinks.Map if you just want to map a LogEventLevel to a file.

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Verbose()
        .WriteTo.Map(evt => evt.Level, (level, wt) => wt.File($"{level}.log"))
        .CreateLogger();
    
    Log.Debug("This goes to Debug.log only");
    Log.Error("This goes to Error.log only");
    
    Log.CloseAndFlush();