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 Server
Windows Server
A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.
12,122 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,237 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Duane Arnold 3,211 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,211 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,211 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.