2
\$\begingroup\$

I've been using this extension in almost all of my projects. What's your opinion? Do you think there is something else to add or to be improved? The idea is to ignore all default ASP.NET messages that are there by default and if optionally to override stuff via configuration. I actually override Microsoft.AspNetCore.Hosting.Diagnostics and Microsoft.AspNetCore.Routing.EndpointMiddleware via appsettings.

public static class LoggingExtensions
{
    private const string SectionName = "Serilog";

    public static IHostBuilder AddCustomLogging(
        this IHostBuilder builder,
        IConfiguration configuration,
        LogEventLevel minLevelLocal = LogEventLevel.Information)
    {
        const string outputTemplate = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}";

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Is(minLevelLocal)
            .MinimumLevel.Override("System", LogEventLevel.Error)
            .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
            .ReadFrom.Configuration(configuration, SectionName)
            .Enrich.FromLogContext()
            .Enrich.WithMachineName()
            .Enrich.WithProcessName()
            .Enrich.WithMemoryUsage()
            .WriteTo.Console(outputTemplate: outputTemplate)
            .CreateLogger();

        return builder.UseSerilog();
    }
}
{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore.Hosting.Diagnostics": "Debug",
        "Microsoft.AspNetCore.Routing.EndpointMiddleware": "Debug"
      }
    }
  }
}
<ItemGroup>
  <PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
  <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
  <PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
  <PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
  <PackageReference Include="Serilog.Enrichers.Memory" Version="1.0.4" />
  <PackageReference Include="Serilog.Enrichers.Process" Version="2.0.2" />
</ItemGroup>
\$\endgroup\$
5
  • 1
    \$\begingroup\$ I don't see any correlation or trace id. Is it on purpose or left out for brevity? \$\endgroup\$ Feb 1, 2023 at 16:04
  • \$\begingroup\$ @PeterCsala, haven't really used them. I'm reading code4it.dev/blog/serilog-correlation-id right now. \$\endgroup\$
    – nop
    Feb 1, 2023 at 16:13
  • \$\begingroup\$ @PeterCsala, I published this extension as a private NuGet package and I technically do builder.Host.AddCustomLogging(builder.Configuration); in every single API that I work on, it's more like a shared business logic between multiple projects. \$\endgroup\$
    – nop
    Feb 1, 2023 at 16:16
  • 1
    \$\begingroup\$ Ohh okay, so you don't want to do distributed tracing to correlate separate log entries. \$\endgroup\$ Feb 1, 2023 at 16:30
  • \$\begingroup\$ @PeterCsala, yeah, at least not at this point \$\endgroup\$
    – nop
    Feb 1, 2023 at 16:30

1 Answer 1

1
\$\begingroup\$

constants of LoggingExtensions

  • I don't know why did you declare SectionName on class level whereas the outputTemplate inside the AddCustomLogging method
  • I think both could be defined on class level
const string SectionName = "Serilog";
const string OutputTemplate = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}";

AddCustomLogging's parameters

  • As I stated earlier I don't think the configuration parameter is necessary since you can reach it through the builder parameter
  • For me this minLevelLocal name seems a bit weird
    • What does local mean in this context?
  • Allowing the user to specify the default log level seems odd to me
    • Either allow to specify all three log levels
    • Or do not allow any of them, since you can set them via the json config

UseSerilog

  • It seems a really strict restriction to use only serilog
  • In order to allow flexibility I would suggest to add an other method which would register serilog as one of the log providers (AddSerilog)
public static IHostBuilder RegisterSerilogCustomLogging(this IHostBuilder builder, IConfiguration configuration)
public static IHostBuilder AddSerilogCustomLogging(this IHostBuilder builder, IConfiguration configuration)

Enrichers, Filters or sinks

  • Your current design does not allow the user to add something to the predefined setup
  • If you want to allow that flexibility then you can do the following:
public static IHostBuilder RegisterSerilogCustomLogging(
    this IHostBuilder builder, 
    IConfiguration configuration, 
    Action<LoggerConfiguration>? configureLogger = null) 

{
    ...
    var loggerConfig = new LoggerConfiguration()
      ...
      .WriteTo.Console(outputTemplate: outputTemplate);
    
    configureLogger?.Invoke(loggerConfig);
    
    Log.Logger = loggerConfig.CreateLogger();
    builder.UseSerilog();
}
\$\endgroup\$
7
  • 1
    \$\begingroup\$ @nop Ohhh... apologize you are right. I've just overlooked this part: the AddCustomLogging is called on builder.Host, not the builder itself. \$\endgroup\$ Feb 2, 2023 at 14:44
  • 1
    \$\begingroup\$ pastebin.com/B7bQ5GDN this is how it looks like after the updates but I wonder about a good way to make IConfiguration parameter optional \$\endgroup\$
    – nop
    Feb 2, 2023 at 14:46
  • 1
    \$\begingroup\$ @nop Well the UseSerilog has an overload where you can provide a configureLogger action. This action receives a WebHostBuilderContext parameter which has access to the Configuration. I'm not sure that this can be helpful in this case. \$\endgroup\$ Feb 2, 2023 at 14:51
  • 1
    \$\begingroup\$ pastebin.com/PVHhfGnb this but dunno if it's good. \$\endgroup\$
    – nop
    Feb 2, 2023 at 16:15
  • 1
    \$\begingroup\$ @nop It seems good to me, but you have to give it a try ;) \$\endgroup\$ Feb 2, 2023 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.