1

I am trying to get Serilog in my asp.net core project to log certain types of logs to a different sink depending on what is being logged, but all I end up with is 2 seperate logs with the exact same content. I want to configure the logger so that if the type is 'Weather logs', it logs to Weather log file, else it logs to nin log file. I have serilog.aspnetcore and expressions installed

Here is my code and config:

using Microsoft.AspNetCore.Mvc;
using Serilog;

namespace LoggerTest.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
        private static readonly string[] nins = new[]
        {
        "1", "2", "3", "4", "6", "7", "8", "9", "10", "11"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
            _logger.LogInformation("WeatherForecast controller called ");
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            var type = "Weather logs";
            var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)],

            })
            .ToArray();
            _logger.LogInformation("Weather logs: Informantion obtained is {@Result}", result);
            type = "Nin logs";
            var test = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = nins[Random.Shared.Next(Summaries.Length)],

            })
            .ToArray();
            _logger.LogInformation("{@Type}: Informantion obtained is {@Test}", type, test[0]);
            return result;
        }


    }
}

My program.cs file:

using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders();

builder.Host.UseSerilog((context, configuration) =>
    configuration.ReadFrom.Configuration(context.Configuration));

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseSerilogRequestLogging();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

my appsettings.json:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "logs/weather-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByIncludingOnly",
            "Args": {
              "expression": "@m like 'Weather logs%'"
            }
          }
        ]
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/nin-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        }

      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  },


  "AllowedHosts": "*"
}

The two log files contain the same information:

{"@t":"2024-04-01T20:59:11.4950381Z","@mt":"WeatherForecast controller called ","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.5670441Z","@mt":"{@Type}: Weather logs: Informantion obtained is {@Result}","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","Type":"Weather logs","Result":[{"Date":"2024-04-02","TemperatureC":7,"TemperatureF":44,"Summary":"Hot","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-03","TemperatureC":8,"TemperatureF":46,"Summary":"Chilly","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-04","TemperatureC":25,"TemperatureF":76,"Summary":"Mild","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-05","TemperatureC":-16,"TemperatureF":4,"Summary":"Bracing","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-06","TemperatureC":37,"TemperatureF":98,"Summary":"Sweltering","Type":null,"$type":"WeatherForecast"}],"SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.5855717Z","@mt":"{@Type}: Informantion obtained is {@Test}","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","Type":"Nin logs","Test":{"Date":"2024-04-02","TemperatureC":9,"TemperatureF":48,"Summary":"11","Type":null,"$type":"WeatherForecast"},"SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.6216513Z","@mt":"HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms","@r":["184.2060"],"@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","RequestMethod":"GET","RequestPath":"/WeatherForecast","StatusCode":200,"Elapsed":184.206,"SourceContext":"Serilog.AspNetCore.RequestLoggingMiddleware","RequestId":"0HN2IHQ4JSE88:00000009","ConnectionId":"0HN2IHQ4JSE88"}
2
  • Do you need to do this via appsettings.json? While I think it's possible, the syntax makes it pretty convoluted to put together. Doing this in code using WriteTo.Conditional() should make life much easier. Commented Apr 5, 2024 at 2:36
  • do you need using serilog.expressions? Commented Sep 16, 2024 at 0:41

2 Answers 2

0

It seems like the issue lies in the configuration of your Serilog filters. You're using the ByIncludingOnly filter, but it's not working as expected. Instead, you can use ByIncluding filter with an expression that specifies the log event properties to filter on.

{
  "Serilog": {
    "Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "logs/weather-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByIncluding",
            "Args": {
              "expression": "Contains(@m, 'Weather logs')"
            }
          }
        ]
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/nin-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByIncluding",
            "Args": {
              "expression": "!Contains(@m, 'Weather logs')"
            }
          }
        ]
      }
    ],
    "Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"]
  },
  "AllowedHosts": "*"
}

Ensure you have the Serilog.Filters.Expressions package installed for this to work properly. You can install it using NuGet:

dotnet add package Serilog.Filters.Expressions

With this configuration, logs containing "Weather logs" will be written to logs/weather-.json, and others will be written to logs/nin-.json.

Sign up to request clarification or add additional context in comments.

1 Comment

I tried that and the same set of logs are logging to both files. I also noticed that the documentation says that Serilog.Filters.Expression is deprecated and suggests using Serilog.Expressions instead.
0

This worked for me:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Default": "Information",
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "StartsWith(@m,'Nin logs')"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "Logs/nin.json",
                  "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
                  "rollingInterval": "Day",
                  "retainedFileCountLimit": 7
                }
              }
            ]
          }
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "StartsWith(@m,'Weather logs')"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "Logs/weather.json",
                  "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
                  "rollingInterval": "Day",
                  "retainedFileCountLimit": 7
                }
              }
            ]
          }
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName"
    ],
    "Properties": {
      "Application": "MultipleLogFilesSample"
    }
  },



  "AllowedHosts": "*"
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.