Access To LoggerProvider From Inside A HostedService (ServiceHost)

Thomas Gössi 1 Reputation point
2021-03-17T17:36:31.767+00:00

In .Net 5.0, logs are handled by ILogger and LoggerProvider. I have created a LoggerProvider, which writes logs into a memory list eg. stringlist. Now I want to access to this memory from within the hosted service.
How can I access to the LoggerProvider instance, so that I can access the log list inside by a property.

My LoggerProvider is:

public class MyLoggerProvider : ILoggerProvider
{   
    private List<string> _logList = new List<string>();

    public List<string> LogList
    {
        get
        {
            return _logList;
        }
    }

        public MyLoggerProvider()
        {
            _logList = new List<string>();
        }

        public ILogger CreateLogger(string className)
        {
            return new ServiceLogger(this, className);
        }

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

        public void AddLogEntry(string logMessage)
        {
        _logList.Add( $"{DateTime.Now:f} :: {logMessage}" );
        }

        public void Dispose()
        {
        _logList~.Clear
        }
    }

And I initialize the ServiceHost with:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().RunAsync();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<ServiceHost>();
            services.Configure<HostOptions>((option) =>
            {
                option.ShutdownTimeout = TimeSpan.FromMinutes(10);
            });
        })
        .ConfigureLogging((hostContext, logging) =>
        {
            logging.AddProvider(new GuiLoggerProvider());
        })
        .UseWindowsService();

Then I want to access the LogList within the ServiceHost, which is:

public class ServiceHost : IHostedService
{
    private readonly IHost _host;
    private readonly IHostApplicationLifetime _hostApplicationLifetime;
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;
    private readonly ServiceWorker _serviceWorker;

    public ServiceHost(IHost host, IHostApplicationLifetime hostApplicationLifetime, IConfiguration configuration, ILoggerFactory logger)
    {
        _host = host;
        _hostApplicationLifetime = hostApplicationLifetime;
        _configuration = configuration;
        _logger = logger.CreateLogger(_configuration["AppSettings:ApplicationName"]);
        _serviceWorker = new ServiceWorker(_logger);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        myLoggerProvider =     /* Here I want to access to myLoggerProvider instance */
        List<string> myLogList = myLoggerProvider.LogList;
    }
}

How can I access the MyLoggerProvider instance ?
Is that possible over the IHost _host or should I use the ILogger _logger ?

Windows for business Windows Server User experience Other
Developer technologies C#
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Duane Arnold 3,216 Reputation points
    2021-03-18T05:47:22.493+00:00

    _logger = logger.CreateLogger(_configuration["AppSettings:ApplicationName"]);

    It is the only instance of a logger object in your code you are talking about. You should set a debug breakpoint just after the line and use debug Quickwtatch to look at the content of _logger object and see what is in it.

    0 comments No comments

  2. Thomas Gössi 1 Reputation point
    2021-03-18T17:12:11.28+00:00

    Yes, I only have one logger instance created within my hosted service, but there are also other loggers instantiated namely the standard loggers of the MS-hosted server.
    I may also have multiple logger providers in my project in the future, but I only have to acces the one with the memory.

    However, I checked, what's in the logger instance. There are 3 Logger arrays:

    - Loggers  (of type LoggerInformation)
    - MessageLoggers (of type MessageLogger)
    - ScopeLoggers (of type ScopeLogger)
    

    Within the Loggers I have 6 items, which I think, are the loggers of the project, also built ins like console logger, debug logger, etc.
    Within the MessageLoggers, I also have 6 loggers, however, I could find myLoggerProvider in this list.
    ScopeLoggers are for Scope, however, I also find my provider in that list, as I use scope.

    That's, OK

    But as these properties are not accessable by standard, I should use reflection to access it as well as I have to loop through all items to find MyLoggerProvider.

    Do you have an idea if there is another, simpler way to access MyLogerProvider?

    Eg. I have to use the right type of _logger to make these properties accessible.


  3. Duane Arnold 3,216 Reputation points
    2021-03-19T16:41:08.637+00:00

    var data = _logger.MessageLoggers[4].Logger._className;

    OR example --- _logger.MessageLoggers[4].Logger._loggerProvider.

    I can't see any properties for _loggerProvider in the screen shot.

    ============================================

    foreach (var item in_logger.MessageLoggers)
    {
    var data = item.Logger._className;
    }

    ===================================

    for(int i = 0; i <_logger.MessageLoggers.Count(); i++)
    {
    var data = _logger.MessageLoggers[i].className;
    }

    It's just a strong typed collection within ._logger


  4. Duane Arnold 3,216 Reputation points
    2021-03-23T15:12:25.757+00:00

    But how can I access to MessageLoggers or _logger.MessageLoggers respectively. The _logger is of type ILogger.
    To which type Have I to cast ?

    You can use var and let the compiler to the cast to a type

    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var

    var data = _logger.MessageLoggers[4].Logger._className;

    The data is going to be of type string.

    You can use var in the local scope and the complier will to the cast.

    You can stop on a line in the debugger and use the mouse pointer and hover over a var and Visual Stuido will tell you the type. You can use the type shown and make a cast to the type if you need to do it manually for some reason.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.