Search code examples
c#.netserilog

Log just this information to a other file with Serilog


I have a .NET 5.0 console application with Serilog nugget. The serilog part of appsettings.json looks like this :

"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
  {
    "Name": "Console",
    "Args": {
      "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
      "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
    }
  },
  {
    "Name": "File",
    "Args": {
      "path": "/Logs/SharedTreatment_logs.txt",
      "outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
      "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
      "fileSizeLimitBytes": 1000000,
      "rollOnFileSizeLimit": "true",
      "shared": "true",
      "flushToDiskInterval": 3
    }

  }
]

It is loaded with this code :

    Serilog.Debugging.SelfLog.Enable(Console.Error);
    
                var configuration = new ConfigurationBuilder()
                                .AddJsonFile("appsettings.json")
                                .Build();
    
                var logger = loggerConfiguration.ReadFrom.Configuration(configuration).CreateLogger();
                
                Log.Logger = logger?.ForContext<T>() ?? throw new ArgumentNullException(nameof(logger));

Host.CreateDefaultBuilder(args).UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))

Each class in the solution got a ILogger injection for example ILogger<MyClass> logger.

The question is how I create a new logger that uses another log configuration section from the appsettings.json to log to another file in such a class?

Update : After a lot of seraching and testing I think I found a way to do this. Im still however not sure it is the right way or the best way?

I have to create 2 sub-loggers, one for the main logging that excludes files and one that only log files like this :

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "Enrich": [ "FromLogContext" ],
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "@p['LogToFile']"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "Logs/SharedTreatment_logs_Second.txt",
                  "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
                }
              }
            ]
          }
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByExcluding",
                "Args": {
                  "expression": "@p['LogToFile']"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "Logs/SharedTreatment_logs.txt",
                  "outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
                  "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
                  "fileSizeLimitBytes": 1000000,
                  "rollOnFileSizeLimit": "true",
                  "shared": "true",
                  "flushToDiskInterval": 3
                }
              }
            ]
          }
        }
      }


    ]
  }
}

This is how the C# code looks like :

static void Main(string[] args)
        {
           
            Console.WriteLine("Hello World!");
            Log.Logger = new LoggerConfiguration().DefaultLoggerSetup<Program>();
            using (LogContext.PushProperty("LogToFile", true))
            {
                Log.Information("LogToFileTest");
            }

            Log.Information("Just log");
            Log.CloseAndFlush();

        }

Two files is creaed and the filtered logs is where they should be.


Solution

  • To solve this I hade to create a separated log entry in the appsettings.json like this :

    {
              "Name": "Logger",
              "Args": {
                "configureLogger": {
                  "Filter": [
                    {
                      "Name": "ByIncludingOnly",
                      "Args": {
                        "expression": "@p['LogToFile']"
                      }
                    }
                  ],
                  "WriteTo": [
                    {
                      "Name": "File",
                      "Args": {
                        "path": "Logs/SharedTreatment_logs_Second.txt",
                        "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
                      }
                    }
                  ]
                }
              }
            },
    

    I den hade to push the specific loggings to this logger like this :

    using (LogContext.PushProperty("LogToFile", true))
                    { _logger.LogInformation("Incoming Message   MessageGuid : {MessageGuid} , MessageChainGuid : {MessageChainGuid}, SharedTreatment : {SharedTreatment}", incomingMessage.MessageGuid, incomingMessage.MessageChainGuid, incomingMessage.SharedTreatment); }