How to register a custom ILogger so that all Unhandled Exceptions get logged

2020-03-26 c# asp.net blazor blazor-client-side

As described [here][1] Blazor uses configured ILogger instances to log all unhandled Exceptions. However I can not get it to work. Searching the web I found sites using an ILoggerProvider or an ILoggerFactory which adds to my confusion.

Which services do I have to configure how to log unhandled Exceptions?

Update: I want to add a second non-console logger and I cannot get that second one to work. The built in console logger from Blazor works fine

Update 2:

Here is a list of everything I tried so far. None of the following worked and sent Unhandled exceptions to MyLogger (In some cases I got all other Messages forwarded to MyLogger)

I tried to register the Logger:

public static void ConfigureServices(IServiceCollection services)  {
    services.AddSingleton<ILogger, MyLogger>();
    services.AddSingleton(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(MyLogger<>)));

I tried to register the Provider:

services.AddSingleton(ServiceDescriptor.Singleton<ILoggerProvider, MyLoggerProvider>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, MyLoggerProvider>());
services.AddSingleton<ILoggerProvider, MyLoggerProvider>();

I tried to register the Provider with the existing ILoggerFactory:

host.Services.GetService<ILoggerFactory>().AddProvider(new MyLoggerProvider());

I tried to register my MyLoggerFactory:

services.AddSingleton<ILoggerFactory, MyLoggerFactory>();

My implementation of ILogger:

public class MyLogger : ILogger
{
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        Debug.WriteLine($"MyLogger.exception='{exception}'");
    }

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

    public IDisposable BeginScope<TState>(TState state)
    {
        return new EmptyDisposable();
    }

    internal class EmptyDisposable : IDisposable 
    {
        public void Dispose()
        {
        }
    }
}

public class MyLogger<T> : ILogger<T>
{
    public void Log<TState>(
        LogLevel logLevel,
        EventId eventId,
        TState state,
        Exception exception,
        Func<TState, Exception, string> formatter)
    {
        Debug.WriteLine($"MyLogger<generic>.exception='{exception}'");
    }

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

    public IDisposable BeginScope<TState>(TState state)
    {
        return new MyLogger.EmptyDisposable();
    }
}

My Implementation of ILoggerProvider

public class MyLoggerProvider: ILoggerProvider
{
    public void Dispose()
    {

    }

    public ILogger CreateLogger(string categoryName)
    {
        Debug.WriteLine($"MyLoggerProvider.categoryName='{categoryName}'");
        return new MyLogger();
    }
}

My Implementation of ILoggerFactory

public class MyLoggerFactory : ILoggerFactory
{
    public MyLoggerFactory()
    {
        Debug.WriteLine($"MyLoggerFactory.ctor");
    }

    public void Dispose()
    {
    }

    public ILogger CreateLogger(string categoryName)
    {
        Debug.WriteLine($"MyLoggerFactory.categoryName='{categoryName}'");
        return new MyLogger();
    }

    public void AddProvider(ILoggerProvider provider)
    {
        Debug.WriteLine($"MyLoggerFactory.AddProvider");
    }
}

Answers

Related