Serilog Filter Sink by Custom Property

2.7k views Asked by At

I want to use Serilog.Expressions to filter my logging for a specific sink. In this instance, I only want to log to the Console Sink if my custom property MethodName is equal to "SomeOtherTask". Serilog is still logging to both Sinks for DoSomeWork and SomeOtherTask. Is there something wrong with my filter expression or how I have implemented my custom property MethodName or something else?

appsettings.json:

{
    "Serilog": {
        "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Expressions" ],
        "MinimumLevel": "Debug",
        "WriteTo": [
            {
                "Name": "Console",
                "Filter": [
                    {
                        "Name": "ByIncludingOnly",
                        "Args": {
                            "expression": "MethodName = 'SomeOtherTask'"
                        }
                    }
                ]
            },
            {
                "Name": "File",
                "Args": {
                    "path": "Logs/log.txt"
                }
            }
        ],
        "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
        "Properties": {
            "Application": "SerilogSplitLogTest"
        }
    }
}

Program.cs:

internal class Program
{
    static void Main()
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", true, true);
        
        var config = builder.Build();

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(config)
            .CreateLogger();

        new Program().Run(logger);

        Console.ReadKey(true);
    }

    public void Run(ILogger logger)
    {
        DoSomeWork(logger);
        SomeOtherTask(logger);
    }

    public void DoSomeWork(ILogger logger)
    {
        logger.Information("This should log to File");
    }

    public void SomeOtherTask(ILogger logger)
    {
        using (LogContext.PushProperty("MethodName", nameof(SomeOtherTask)))
        {
            logger.Information("This should log to Console");
        }
    }
}
1

There are 1 answers

1
Gaz83 On

I had similar issues of writing to 2 files, 1 was to have all the logging and there other was to be filtered by a property so it was a kind of condensed log. Here is how I did it.

First, make sure you install Serilog.Expressions. Doing this alone may solve your issue, if not then here is my WriteTo section of my config that I used.

Note: Marker is the custom property I was filtering on.

"WriteTo": [
  {
    "Name": "Logger",
    "Args": {
      "configureLogger": {
        "Filter": [
          {
            "Name": "ByIncludingOnly",
            "Args": {
              "expression": "Marker is not null"
            }
          }
        ],
        "WriteTo": [
          {
            "Name": "File",
            "Args": {
              "path": "D:\\Temp\\SerilogTesting.txt",
              "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] - [{Level:u3}] - [{SourceContext}.{Method}] - {Message:lj}{NewLine:1}{Exception:1}",
              "rollingInterval": "Day",
              "retainedFileCountLimit": 7,
              "shared": true
            }
          }
        ]
      }
    }
  },
  {
    "Name": "File",
    "Args": {
      "path": "D:\\Temp\\SerilogTesting.log",
      "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] - [{Level:u3}] - [{SourceContext}.{Method}] - {Message:lj}{NewLine:1}{Exception:1}",
      "rollingInterval": "Day",
      "retainedFileCountLimit": 7,
      "shared": true
    }
  },
  {
    "Name": "Console",
    "Args": {
      "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
      "outputTemplate": "[{Marker}][{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] - [{Level:u3}] - [{SourceContext}.{Method}] - {Message:lj}{NewLine:1}{Exception:1}"
    }
  }
]

Then my property was pushed like so

_logger.ForContext("Marker","LW").Information("Something to log");