Alexander
Alexander

Reputation: 1487

Configuring Serilog RollingFile with appsettings.json

I'm trying to configure Serilog for a .NET Core project. Here's what I have in my appsettings.json:

 "Serilog": 
{
    "MinimumLevel": "Verbose",
    "Enrich": ["FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId"],
    "WriteTo": [
      { "Name": "RollingFile",
        "Args": {
          "pathFormat": "C:/Logfiles/testapp/log-{Date}.json",
          "textFormatter": "JsonFormatter",
          "fileSizeLimitBytes": 2147483648,
          "retainedFileCountLimit": 5
        }
      }
    ]
  }

The problem I see is that JsonFormatter is not picked up, and instead I get entries using the default text formatter. I tried using "formatter": "JsonFormatter", but got the same result.

It all works fine if I configure Serilog in code:

var jsonSink = new RollingFileSink(config["Logger:FilePath"], new JsonFormatter(), 2147483648, 5);

var logger = new Serilog.LoggerConfiguration().WriteTo.Sink(jsonSink);

Here is the relevant section of my project.json:

"Serilog": "2.2.1",
"Serilog.Extensions.Logging": "1.1.0",
"Serilog.Sinks.Literate": "2.0.0",
"Serilog.Sinks.Seq": "2.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Serilog.Enrichers.Thread": "2.0.0",
"Serilog.Enrichers.Process": "2.0.0",
"Serilog.Sinks.ColoredConsole": "2.0.0",
"Serilog.Settings.Configuration": "2.2.0"

Upvotes: 36

Views: 111353

Answers (6)

Udara Kasun
Udara Kasun

Reputation: 2216

ASP.NET Core Console Application with .Net 6

Nuget Pakages

<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />

<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="8.0.0" />

<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

Programe.cs

//Configuration Initialization
 IConfiguration configuration = new ConfigurationBuilder()
 .SetBasePath(Environment.CurrentDirectory)
 .AddJsonFile("appsettings.json", optional: true, true)
 .Build();

//Dependency Injection Initialization
ServiceCollection services = new();
services.AddSingleton(configuration);
services.AddScoped<ITestService, TestService>();

//Create Logger
Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration.GetSection("Logging"))
   .CreateLogger();

//Logger Initialization
services.AddLogging(loggingBuilder =>
{
    loggingBuilder.AddSerilog(Log.Logger, true);
});

var provider = services.BuildServiceProvider();
ILogger<Program> _logger = provider.GetService<ILogger<Program>>() ?? throw new Exception("Log Service provider is null");

Exception ex = new Exception("Custom Error"); 
       
 //Sample Log
_logger.LogInformation("Hello Serilog");   
_logger.LogError(ex,"Error");
_logger.LogWarning("Warning Msg");

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Serilog": {
      "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
      "MinimumLevel": "Debug",
      "WriteTo": [
        {
          "Name": "Console",
          "Args": {
            "outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
          }
        },
        {
          "Name": "File",
          "Args": {
            "path": "C:\\LOGS\\Log-.log",
            "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{;}] [{EventId}] {Message}{NewLine}{Exception}",
            "rollOnFileSizeLimit": false,
            "fileSizeLimitBytes": 4194304,
            "retainedFileCountLimit": 1,
            "rollingInterval": "Day"
          }
        }
      ]
    }
  }
}

Output File

2024-01-31 10:58:04.284 +03:00 [Information] [{;}] [] Hello Serilog
2024-01-31 10:58:04.290 +03:00 [Error] [{;}] [] Custom Error
2024-01-31 10:58:04.291 +03:00 [Warning] [{;}] [] Warning Msg

Upvotes: 0

Mike O.
Mike O.

Reputation: 89

I realize, this is an old post, but no answer was accepted to date. So, here is what I see as a problem: formatter class was selected, yet its namespace was not specified. Something like the following worked for me:

"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog.Formatting.Json"

Upvotes: 0

Mujib Khan
Mujib Khan

Reputation: 256

This works fine for me. "RollingFile" is no longer supported, hence "File" and "pathFormat" is just "path"

"Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Debug",
        "System": "Debug"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "C:\\Temp\\Logs\\log-appstngs.log",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}",
          "rollOnFileSizeLimit": true,
          "fileSizeLimitBytes": 4194304,
          "retainedFileCountLimit": 10,
          "rollingInterval": "Minute"
        }
      }
    ]
  },

Upvotes: 17

Dmytro
Dmytro

Reputation: 81

The folowing configuration works:

"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Information", 
"WriteTo": [
  {
    "Name": "Console",
    "Args": {
      "outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
    }
  },
  {
    "Name": "RollingFile",
    "Args": {
      "pathFormat": "Logs\\log-{Date}.json",
      "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
      "fileSizeLimitBytes": 104857600
    }
  }


 ]
}

In Program.cs:

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
            .AddEnvironmentVariables()
            .Build();    
public static void Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                    .ReadFrom.Configuration(Configuration)
                    .CreateLogger();
    ...
    }

and

public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseConfiguration(Configuration)
                .ConfigureLogging(log => { log.AddSerilog(Log.Logger); })
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

And inject logger to your controller:

public class UsersController : ControllerBase
{
private readonly ILogger<UsersController> _logger;

  public UsersController(ILogger<UsersController> logger)
     {
      _logger = logger;        
     }
     //your code
    }

Example of result which I got:

{
"@t": "2019-04-12T14:03:08.2789776Z",
"@mt": "GetUserMessages()=> ",
"@r": [
    "000117"
],
"Elapsed": 117,
"SourceContext": "MyProject.Web.Controllers.UsersController",
"ActionId": "1b8bc4b9-5858-415b-ab4e-56ba14a5a1ca",
"ActionName": "MyProject.Web.Controllers.UsersController.GetUserMessages (MyProject.Web)",
"RequestId": "0HLLVSDFSA43ES:00000001",
"RequestPath": "/TestAppId/messages",
"CorrelationId": null,
"ConnectionId": "0HLLVSDFSA43ES"
}

Upvotes: 4

Jeremy Ray Brown
Jeremy Ray Brown

Reputation: 1577

The following works:

var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "C:\\logs\\log-{Date}.txt"),
                            outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}")
            //.ReadFrom.Configuration(Configuration)
            .CreateLogger();

        Log.Logger.Information("test");

The following also works (only showing CreateLogger portion):

Log.Logger = new LoggerConfiguration()
            //.MinimumLevel.Debug()
            //.WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "C:\\logs\\log-{Date}.txt"),
            //                outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}")
            .ReadFrom.Configuration(Configuration)
            .CreateLogger();

The appsettings.json file (relevant section here is Serilog):

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "Serilog": {
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "RollingFile",
        "Args": {
          "pathFormat": "C:\\logs\\log-{Date}.txt",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] [{EventId}] {Message}{NewLine}{Exception}"
        }
      }
    ]
  }
}

The NuGet packages in project.json:

  • "Serilog": "2.3.0",
  • "Serilog.Extensions.Logging": "1.3.1",
  • "Serilog.Sinks.RollingFile": "3.2.0",
  • "Serilog.Sinks.File": "3.1.1",
  • "Serilog.Settings.Configuration": "2.2.0"

My target framework is net452.

Upvotes: 17

Nicholas Blumhardt
Nicholas Blumhardt

Reputation: 31832

The formatter argument needs to be a fully-qualified type name. Try:

"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"

Upvotes: 24

Related Questions