2

In my .NET Core 3.1 project, I have installed Serilog and tried to follow all of the implementing details but for some reason it is not logging into a SQL Server table.

Here is the code - Web API program:

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            var iWebHost = CreateHostBuilder(args).Build();
            var path = Directory.GetCurrentDirectory();
            var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
            var configuration = new ConfigurationBuilder()
                .SetBasePath(path)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environmentName}.json", optional: true)
            .Build();

            var logger = new LoggerConfiguration()
                .Enrich.FromLogContext()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();

            Log.Logger = logger;
            iWebHost.Run();
        }
        catch (Exception exception)
        {
            Log.Fatal(exception, "Error starting");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .UseSerilog();
}

appsetting.json and appsettings.development.json

{
"Serilog": {
    "Using": [ "Serilog.Sinks.MSSqlServer" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "System": "Warning",
        "Microsoft": "Warning"
      },
      "WriteTo": [
        {
          "Name": "MSSqlServer",
          "Args": {
            "connectionString": "Server=localhost; Initial Catalog=GP; User ID=lc; Password=lc",
            "tableName": "Log"
          }
        }
      ]
    }
  }
}

Here is my main controller

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

    public MainController(ILogger<MainController> logger)
    {
        _logger = logger;
    }
}

And here is the controller that I want to write logs from:

public async Task<ResponseBase> GetAsync(RequestBase request)
{
    _logger.LogInformation("in controller");
    // other code
    // return;
}

Here is my log entity

public class Log
{
    public int Id { get; set; }
    public string Message { get; set; }
    public string MessageTemplate { get; set; }
    public string Level { get; set; }
    public DateTimeOffset TimeStamp { get; set; }
    public string Exception { get; set; }
    public string Properties { get; set; }
    public string LogEvent { get; set; }
}
7
  • You don't have any other sinks so any problems with the database sink won't be logged anywhere. Configure your logger in code first to ensure everything is OK, eg the data source is correct, the server is running, the database exists, the log table is created etc Commented Jul 16, 2020 at 11:15
  • @Panagiotis Kanavos I have checked all that. logger is configured and injected, server is running, database exists and log table also exists Commented Jul 16, 2020 at 11:18
  • Your code is calling UseSerilog before creating the logger itself. By default UseSerilog() uses the static logger or creates a new one. The way it's called now, there's no static logger to use Commented Jul 16, 2020 at 11:46
  • @PanagiotisKanavos Could you elaborate more please? how can I fix the issue now? what options do I have? Commented Jul 16, 2020 at 11:56
  • @PanagiotisKanavos sorry but you rnaswer below didn't work Commented Jul 16, 2020 at 12:27

1 Answer 1

2

Your code calls UseSerilog() before Serilog's configuration. This means the application ends up with a default, unconfigured logger. You can avoid this by configuring Serilog using inline initialization with the UseSerilog overload that provides access to the HostingContext. From the linked docs:

.UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
    .ReadFrom.Configuration(hostingContext.Configuration)
    .Enrich.FromLogContext()
    .WriteTo.Console())

This reads Serilog's settings from configuration and adds a Console logger, ensuring you'll get log messages even if the configuration is incorrect.

There's no reason to create the configuration separately. CreateDefaultBuilder() sets the current directory as the root and adds the appsettings files. To extend this, use ConfigureHostConfiguration or ConfigureAppConfiguration after CreateDefaultBuilder().

CreateHostBuilder should change to :

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
        .UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
            .ReadFrom.Configuration(hostingContext.Configuration)
            .Enrich.FromLogContext()
            .WriteTo.Console());

and Main to just :

public static void Main(string[] args)
{
    CreateHostBuilder(args).Run();
}

If you want to use the logger before building the host, you should create it before calling UseSerilog() :

public static void Main(string[] args)
{
    Log.Logger = new LoggerConfiguration()
            .Enrich.FromLogContext()
            .ReadFrom.Configuration(configuration)
            .WriteTo.Console()
            .CreateLogger();

    try
    {
        CreateHostBuilder(args).Run();
    }
    catch (Exception exception)
    {
        Log.Fatal(exception, "Error starting");
    }
    finally
    {
        Log.CloseAndFlush();
    }
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
        .UseSerilog()
Sign up to request clarification or add additional context in comments.

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.