4
votes

I have set up my solution and serilog reads the values from appsettings.json

public void Configure(IApplicationBuilder application, IHostingEnvironment environment, ILoggerFactory loggerFactory)
{
     Logger log = new LoggerConfiguration()
            .ReadFrom.Configuration(Configuration)
            .CreateLogger();
     loggerFactory.AddSerilog(log);

And the appsettings looks like this:

 "Serilog": {
    "Using": [ "Serilog.Sinks.Slack", "Serilog.Sinks.ApplicationInsights" ],
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Error",
        "System": "Error"
      }

    },
    "WriteTo": [
      {
        "Name": "Slack",
        "Args": {
          "WebHookUrl": "https://hooks.slack.com/services/xxx/yyy/zzz",
          "CustomChannel": "#channel"
        }
      },
      {
        "Name": "ApplicationInsights",
        "Args": {
          "InstrumentationKey": "xxx-xxx-xxx-xxx-xxx",
          "restrictedToMinimumLevel": "Information",
          "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
        }
      }
    ]
  }

So everything is fine til here, but I don't want to store secrets like webhook and InstrumentationKey in my repository. I want to read them from a safe place like user-secrets on development environment and Key-vault on prouction. How do I change it to replace the values from usersecrets?

https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.2&tabs=windows

Is there anyways the config get overriten automatically?

If not, I know I can read my configuration from secrets let's say like

  webHookUrl = Configuration["Serilog:WriteTo:Slack:WebHookUrl"];

But then how do I apply it on the loggerConfig? I mean, the writeTo part is dynamic from the settings, should I then add it in code instead? :\

Update

Since many people have asked, in my program.cs I have:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseApplicationInsights()
                .UseStartup<Startup>();

And based on the Microsoft documentation, everything should work because I have CreateDefaultBuilder and I am running .net core 2.2. https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.2&tabs=windows#access-a-secret

In ASP.NET Core 2.0 or later, the user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults. CreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development.

When CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets in the Startup constructor. Call AddUserSecrets only when the app runs in the Development environment

3
The thing about .Net Core configuration is that it doesn't matter where a setting comes from, as long as one of the providers has ingested a setting it will be available to configuration in general. You can put the serilog settings in any provider like the keyvault provider, environment variables, etc. If you are in an Azure App Service I suggest the service's Application Settings.Crowcoder
@Crowcoder thanks for the reply. I have copied the same exact settings in my secrets and removed it from my appsettings but now I am not receiving any logs. Am I missing something?Ashkan Sirous
How are you setting up the configuration builder? Are you using builder.AddUserSecrets<Startup>();?ESG
@ESG no, because I am on .net core 2.2 so I should be fine with WebHost.CreateDefaultBuilder(args). Shouldn't I?Ashkan Sirous
@AshkanSirous No, secrets are only loaded on demand (and typically only in dev envionrments)ESG

3 Answers

1
votes

This is what I'm currently using for my ASP.NET Core 3.1 web applications. It supports appsettings.json (for all environments) and Visual Studio's User Secrets (secrets.json) without having to write any sensible info (such as the user secret's unique ID) the code.

Program.cs file's Main() method:

public static void Main(string[] args)
{
    var configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json",
            optional: false,
            reloadOnChange: true)
        .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", 
            optional: true,
            reloadOnChange: true)
        .AddUserSecrets<Startup>(optional: true, reloadOnChange: true)
        .Build();

    Log.Logger = new LoggerConfiguration()
        .WriteTo.MariaDB(
            restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information,
            connectionString: configuration.GetConnectionString("DefaultConnection"),
            tableName: "Logs",
            autoCreateTable: false,
            useBulkInsert: false,
            options: new MariaDBSinkOptions() 
            { 
                LogRecordsExpiration = new TimeSpan(90, 0, 0, 0, 0) 
            })
        .CreateLogger();

    try
    {
        Log.Information("Starting the HostBuilder...");
        CreateWebHostBuilder(args).Build().Run();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "The HostBuilder terminated unexpectedly");
    }
    finally
    {
        Log.CloseAndFlush();
    }
}

Program.cs file's CreateWebHostBuilder() method:

public static IHostBuilder CreateWebHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        })
        .UseSerilog();

If you need additional info, take a look at this post on my blog.

0
votes

I have copied the same exact settings in my secrets and removed it from my appsettings but now I am not receiving any logs. Am I missing something?

If you move your serilog configurations from appsettings.json to secrets.json, you need to modify the ReadFrom.Configuration() in Configure to read from secrets.json.

var configuration = new ConfigurationBuilder()
          .AddJsonFile("C:\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\UserSecrets\\aspnet-SerilogCore\\secrets.json")
          .Build();//Replace above with path of your secrets.json

Logger log = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .CreateLogger();
loggerFactory.AddSerilog(log);
0
votes

I believe that @Crowcoder is correct in his 1st comment to the OP. Therefore, what you need to do is "dupliclate" the structure and part of the configuration from your appsettings.json into the secrets.json file in your home directory

So in your case, you would do something like this:

    "Serilog": {

    "WriteTo": [
      {
        "Name": "Slack",
        "Args": {
          "WebHookUrl": "https://hooks.slack.com/services/xxx/yyy/zzz"
        }
      },
      {
        "Name": "ApplicationInsights",
        "Args": {
          "InstrumentationKey": "xxx-xxx-xxx-xxx-xxx"
        }
      }
    ]
  }

So that only the secret information is present.