Microsoft.Extensions.Logging, ILogger, get a count of errors?

37 views Asked by At

When using Microsoft.Extensions.Logging in a .NET application, is there a way to get the current count of errors that have been written to the log?

I figure I can probably implement a custom ILogger that tracks the error count, but if this already exists out-of-the-box, I*d much prefer that.

1

There are 1 answers

2
Sigurd Garshol On

It seems like this is where I'll need a custom StatisticsLogger:

Note: The intended use for this is in a simple console app that's going to run as a single instance. No attempt has been made to accomodate multi-threading!

public class StatisticsLogger : ILogger
{
    public int CriticalsCount { get; private set; } = 0;
    public int ErrorsCount { get; private set; } = 0;
    public int WarningsCount { get; private set; } = 0;

    public IDisposable BeginScope<TState>(TState state) where TState : notnull
    {
        return null;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (logLevel == LogLevel.Critical)
        {
            CriticalsCount++;
        }

        if (logLevel == LogLevel.Error)
        {
            ErrorsCount++;
        }

        if (logLevel == LogLevel.Warning)
        {
            ErrorsCount++;
        }
    }
}

A logger provider that retains the instance of the StatisticsLogger:

public class StatisticsLoggerProvider : ILoggerProvider
{
    public StatisticsLogger Logger {get; private set;}

    public StatisticsLoggerProvider()
    {
        Logger = new StatisticsLogger();
    }

    public ILogger CreateLogger(string categoryName)
    {
        return Logger;
    }

    public void Dispose()
    {
    }
}

A helper for adding this to the ApplicationHostBuilder:

public static class HostApplicationBuilderExtensions
{
    public static HostApplicationBuilder AddCustomLoggers(this HostApplicationBuilder builder)
    {
        // Adding custom loggers on the builder instead of builder.Logging allows access to builder.Configuration :)
        builder.Logging.AddProvider(new StatisticsLoggerProvider());

        return builder;
    }
}

And using it in the Program Main

class Program
{
    static async Task Main(string[] args)
    {
        var builder = Host.CreateApplicationBuilder(args);

        builder.Services.AddSingleton<Batch>();

        builder.Logging
            .SetMinimumLevel(LogLevel.Trace)
            .AddConsole();

        builder.AddCustomLoggers();

        var host = builder.Build();

        // This could maybe be handled better...
        var statisticsLoggerProvider = host.Services.GetServices<ILoggerProvider>()
            .First(x => x is StatisticsLoggerProvider) as StatisticsLoggerProvider;

        var statisticsLogger = statisticsLoggerProvider.Logger;

        var criticalsCount = statisticsLogger.CriticalsCount;

        var errorsCount = statisticsLogger.ErrorsCount;

        var warningsCount = statisticsLogger.WarningsCount;
    }
}