Sharing logger between different .NET frameworks
Asked Answered
P

1

8

I am creating an application framework that can be shared between .Net Core 1.2, .Net Core 2.0 and .NET Framework 4.6+. So I choose the target framework of my project as .NET Standard. In my framework project I have factory class that is used to send a text message or email. On application startup, each application configures the factory with the supported services as singleton instance with DI framework.

public class MyFactory : IMyFactory
{
      private ILogger _logger;
      private IDictionary<string,IMyService> _container = new Dictionary<string,IMyService>();

    // this method is called on application startup to configure supported services
    public void Configure(string[] keys, ILogger logger)
    {  
        foreach(var key in keys)
        {
             if(key == "text")
             {
                 container.Add(key,new TextMessageService());
             }   

             if(key == "email")
             {
                 container.Add(key,new EmailService());
             }
        }
    }

    //application call this method to send message
    public bool SendMessage(string key, string message)
    {
         // we don't want application to stop when publish fail, so we add try-catch and log the message
         var flag = false;

         try
         {
             var service= container[key];
             service.Publish(message);
             flag = true;
         }
         class(Exception ex)
         {
            _logger.Error(ex);
         }

         return flag;
    }
}

Issue: the publish method could fail for any reason. And in such case I don't want application to stop, instead the framework should log the error message. My problem is since the framework can be shared between different .NET frameworks, I don't know which type of ILooger I should be using that can be shared between .NET Core and .NET Full.

I am trying to avoid creating my own ILogger interface. Also currently all applications are using Serilog but in future that could change.

Can Microsoft.Extensions.Logging be used here?

Pen answered 21/3, 2018 at 16:17 Comment(2)
Did you try using Microsoft.Extensions.Logging?Frulla
Huh? ILogger is not some sort of language feature. There's various logging frameworks and fascades that expose an ILogger interface. You only need that library to be usable by all three targets. That should actually be the case for just about any logging framework out there.Gypsy
C
8

Yes it can. If you have to support netcore 1, then

Install-Package Microsoft.Extensions.Logging -Version 1.1.2 

would work:

But better still your reusable component only need rely on the Abstractions:

Install-Package Microsoft.Extensions.Logging.Abstractions -Version 1.1.2 

Your component only need reference ILogger, and the applications that use your component are not tied to using the MS extensions logger. In particular, if you look at the dependencies for

Serilog.Extensions.Logging -Version 2.0.2 

At https://www.nuget.org/packages/Serilog.Extensions.Logging/ , you can see that it depends on Abstractions but doesn't depend on the MS Extensions logger. Serilog does depend on netstandard1.3. But again the netstandard version page tells you all your targets support it.

The applications using your framework can then carry on using Serilog, so long as they know how to wrap a serilogger as a MS.Extensions ILogger. the SerilogLoggerProvider in Serilog.Extensions.Logging does the trick:

var msFrameworkLogger= new SerilogLoggerProvider(myExistingSerilog).CreateLogger("name");
Cr answered 22/3, 2018 at 13:48 Comment(6)
Thanks..This what i needed.. I wasn't sure if i use Microsoft.Extensions.Logging.ILogger in NET Standard Framework project and application is using Serilog how types are going to matchPen
So any of your applications using Serilog would want to add a dependency to the Serilog.Extensions package which handles "adapt-Serilog-to-MS.ILogger" ; but that should be acceptable. Inside your shared component, you only get access to the basic ILogger interface – but that's all a component wants.Cr
So how do i adapt-Serilog-to-MS.ILogger. Do i explicitly call any method in application that will create instance of Microsoft.Extensions.Logging.ILogger? Currently i am getting error InvalidOperationException - The current type, Microsoft.Extensions.Logging.ILogger1[XXXX.Common.FW.MyFactory], is an interface and cannot be constructed. Are you missing a type mapping?`Pen
The simple thing, for an application that uses Serilog is, add the Serilog.Extensions.Logging nuget package and then var msFrameworkLogger= new SerilogLoggerProvider(theExistingSerilogger).CreateLogger(); There is also var msframeworklogger= new LoggerFactory().AddSerilog().CreateLogger(); which does the same thing. There's an example in the SetUp method of github.com/chrisfcarroll/DotNetCoreTemplates/blob/master/…Cr
I have configured serilog. Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(Configuration).CreateLogger(); and its been working. Would that also configures the instance of Microsoft.Extensions.Logging.ILogger for DI to work? Note the constructor of the MyFactory class takes Microsoft.Extensions.Logging.ILoggerPen
never mind i found it how you are doing it in your test.Pen

© 2022 - 2024 — McMap. All rights reserved.