31

I am using Serilog for logging and cant' figure out how to separate log events to different files. For example, I want to log errors to error_log-ddmmyyyy.txt and warnings to warn_log-ddmmyyyy.txt.

Here goes my logger configuration:

Log.Logger = new LoggerConfiguration()
            .WriteTo.Logger(lc =>
                lc.Filter.ByIncludingOnly(Matching.WithProperty("Level", "Warning"))
                    .WriteTo.RollingFile(
                        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Logs\warn_log-{Date}.txt"),
                        outputTemplate: OutputTemplate))
            .WriteTo.Logger(lc =>
                lc.Filter.ByIncludingOnly(Matching.WithProperty("Level", "Error"))
                    .WriteTo.RollingFile(
                        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Logs\error_log-{Date}.txt"),
                        outputTemplate: OutputTemplate))
            .CreateLogger();

It only works when I specify {Level} property exatcly in log message.

I was trying to use:

Matching.WithProperty<LogEventLevel>("Level", l => l == LogEventLevel.Warning)

but it didn't work too.

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
Anton Kiprianov
  • 358
  • 1
  • 3
  • 5

6 Answers6

54

I use the following configuration and it works for me:

            Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .WriteTo.LiterateConsole()
                    .WriteTo.Logger(l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information).WriteTo.RollingFile(@"Logs\Info-{Date}.log"))
                    .WriteTo.Logger(l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug      ).WriteTo.RollingFile(@"Logs\Debug-{Date}.log"))
                    .WriteTo.Logger(l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Warning    ).WriteTo.RollingFile(@"Logs\Warning-{Date}.log"))
                    .WriteTo.Logger(l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error      ).WriteTo.RollingFile(@"Logs\Error-{Date}.log"))
                    .WriteTo.Logger(l => l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Fatal      ).WriteTo.RollingFile(@"Logs\Fatal-{Date}.log"))
                    .WriteTo.RollingFile(@"Logs\Verbose-{Date}.log")
                    .CreateLogger();
Dai
  • 141,631
  • 28
  • 261
  • 374
Ben Pretorius
  • 4,079
  • 4
  • 34
  • 28
  • 4
    Upvoted not regarding to the question, but because of the clean solution presented for logging different log levels in separate files. – Mohsen Kamrani May 02 '17 at 00:03
  • 2
    Like this one. The only question, is how it could be translated to JSON config file? I tried to find a syntax reference, but failed to to so for some reason. – Pritorian Feb 12 '18 at 13:43
  • 1
    I'm not sure you can do this in json config. My VS plugin ignores the Filter line when generating json. – Lukos Jul 03 '18 at 10:42
24

I think you need:

.ByIncludingOnly(evt => evt.Level == LogEventLevel.Warning)

Edit:

In many cases it's now more succinct to use Serilog.Sinks.Map. With it, the example can be written as:

Log.Logger = new LoggerConfiuration()
    .WriteTo.Map(
        evt => evt.Level,
        (level, wt) => wt.RollingFile("Logs\\" + level + "-{Date}.log"))
    .CreateLogger();
Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
  • ...mind looking at this question, the edit and last few comments in the answer...https://stackoverflow.com/questions/47565008/trouble-converting-serilog-configuration-code-line-to-json-configuration/47566787?noredirect=1#comment82106820_47566787 – dinotom Nov 30 '17 at 14:14
7

Usually for my use-cases I need multiple logs that will contain a minimum level for each. This way I can later investigate the logs more efficiently.

For more recent versions of Serilog I would suggest to use this:

Log.Logger = new LoggerConfiuration()
    .MinimumLevel.Debug()
    .WriteTo.File(path: "debug.log", rollingInterval: RollingInterval.Day)
    .WriteTo.File(path: "info.log", restrictedToMinimumLevel: LogEventLevel.Information, rollingInterval: RollingInterval.Day)
    .WriteTo.File(path: "error.log",restrictedToMinimumLevel: LogEventLevel.Error, rollingInterval: RollingInterval.Day)
    .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning)
    .CreateLogger();
Yaniv
  • 966
  • 12
  • 20
2

Serilog now has conditional sinks which make it really simple and clean to implement this:

Log.Logger = new LoggerConfiguration()
.WriteTo.Conditional(
    evt => evt.Level == LogEventLevel.Debug,
    wt => wt.RollingFile(@"Logs\Debug-{Date}.log"))
.WriteTo.Conditional(
    evt => evt.Level == LogEventLevel.Warning,
    wt => wt.RollingFile(@"Logs\Warning-{Date}.log"))
.CreateLogger();

You can put whatever condition you like in the first argument.

Tim Pickin
  • 369
  • 4
  • 15
0
var dateTimeNowString = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}";
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .WriteTo.Logger(
        x => x.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
            .WriteTo.File($"Logs/{dateTimeNowString}-Error.log")
    )
    .WriteTo.Logger(
        x => x.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Warning)
            .WriteTo.File($"Logs/{dateTimeNowString}-Warning.log")
    )
    .WriteTo.File($"Logs/{dateTimeNowString}-All.log")
    .WriteTo.Console()
    .CreateLogger();

These are my nuget packages:

    <PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
xhafan
  • 2,140
  • 1
  • 26
  • 26
0

Another variant is to have ERROR and FATAL in one file (instead of errors in one file and fatal in another). Seems to many files for me having them separate. Just to keep in mind "or" operator can be used.

Log.Logger = new LoggerConfiguration()
    .WriteTo.File("logs\\all.log", rollingInterval: RollingInterval.Day)
    .WriteTo.Logger(
        x => x.Filter.ByIncludingOnly(y => y.Level == Serilog.Events.LogEventLevel.Error || y.Level == Serilog.Events.LogEventLevel.Fatal)
        .WriteTo.File("logs\\error.log", rollingInterval: RollingInterval.Day))
    .CreateLogger();
nerlijma
  • 935
  • 1
  • 9
  • 24