Skip to content

Logging

Anrijs Vitolins edited this page Jan 29, 2022 · 1 revision

Package uses logging in Command Handler component to output its work on commands and parameter parsing. When using Host-based template, logging is added automatically via Microsoft.Extensions.Logging package of .Net.

By default Console (output log statements to console screen) and Debug (Output log statements to Visual Studion Output window) providers are added. To avoid flooding console screen, you have to clear providers and add only necessary. This is done when building up Host with this code:

IHost? host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        // Remove auto-added loggers
        logging.ClearProviders();
#if DEBUG
        // This will show logging statements when run in Visual Studio in Output window.
        logging.AddDebug();
        logging.SetMinimumLevel(LogLevel.Debug);
#else                
        // For release only Warnings and Errors are in Log, but they are swallowed as no provider is given.
        logging.SetMinimumLevel(LogLevel.Warning);
#endif
    })

Unfortunately Microsoft does not provide logging to file or any other logging statement sink, so if you want to use logging in your application and to have it written to some file, you should use 3rd party package or write provider yourself.

Currently the best logging package to use is Serilog, which has capability to write logs to almost anywhere (files, databases, logging services etc.)

Use Serilog

Here is example on how to add logging to file (auto-named based on startup time). If you want to have logging somewhere else - explore Serilog Sinks packages and use the one you need.

First, add Serilog.Extensions.Hosting and Serilog.Sinks.File NuGet packages to your application.

Then add and configure Serilog in Main method of Program.cs before Host setup.

Log.Logger = new LoggerConfiguration()
    .WriteTo.File("MyLog.txt", LogEventLevel.Verbose, buffered: true, rollingInterval: RollingInterval.Minute)
    .MinimumLevel.Verbose()
    .Enrich.FromLogContext()
    .CreateLogger();

// First Log statement written to file.
Log.Information("Application starting.");

Then extend Host setup to indicate you will be using Serilog for logging:

var host = Host.CreateDefaultBuilder(args)
    .UseConsoleLifetime()
    .ConfigureServices((context, collection) => SetupContainer(context, collection, configuration))
    .UseSerilog() // <-- This must be added, which wires Serilog to ILogger
    .Build();

After that you can still use Microsoft.Extensions.Logging interface ILogger<T> to inject into commands or your additional business logic classes and use it to write log statements to file.

public class ConsoleCommand : IConsoleOperation
{
    private readonly ILogger<ConsoleCommand> _logger;

    // Inject logger in cosntructor
    public GenerateCode(ILogger<ConsoleCommand> logger) => _logger = logger
    
    // ... More code, then in some method use logging
    _logger.LogInformation("Some operation is doing {0}.", operationWork);
}