【问题标题】:Implementation and usage of logger wrapper for Microsoft.Extensions.LoggingMicrosoft.Extensions.Logging 记录器包装器的实现和使用
【发布时间】:2017-01-29 07:41:33
【问题描述】:

此问题与Steven 的答案-here 有关。他提出了一个非常好的记录器包装器。我将他的代码粘贴在下面:

public interface ILogger
{
    void Log(LogEntry entry);
}

public static class LoggerExtensions
{
    public static void Log(this ILogger logger, string message)
    {
        logger.Log(new LogEntry(LoggingEventType.Information,
            message, null));
    }

    public static void Log(this ILogger logger, Exception exception)
    {
        logger.Log(new LogEntry(LoggingEventType.Error, 
            exception.Message, exception));
    }

    // More methods here.
}

所以,我的问题是创建代理 Microsoft.Extensions.Logging 的实现的正确方法是什么 以及 稍后在代码中使用它的最佳方法是什么?

注意:此问题是 this question about log4net 的副本,但现在特定于 Microsoft.Extensions.Logging。

【问题讨论】:

    标签: c# .net logging microsoft-extensions-logging


    【解决方案1】:

    这是我的解决方案。和史蒂文的不太一样。但并不完全喜欢。我倾向于 dotNetCore,但同样的事情可以在 dotnetFW 中完成。

    DotNetCoreLogger 是“MY”ILogger 的具体化。我将“microsoft”ILogger (Microsoft.Extensions.Logging.ILogger) 注入“My”具体记录器。

    还有另一个 SOF 答案“启发”了“我的”日志抽象......并且在从 DotNetFramework(经典)转到 DotNotCore 之后,我很高兴我做了一个“我的”ILogger 抽象。

    using System;
    
    namespace MyApplication.Infrastructure.Logging.LoggingAbstractBase
    {
        public interface ILogger
        {
            void Log(LogEntry entry);
            void Log(string message);
            void Log(Exception exception);
        }
    }
    
    
    namespace MyApplication.Infrastructure.Logging.LoggingAbstractBase
    {
        public enum LoggingEventTypeEnum
        {
            Debug,
            Information,
            Warning,
            Error,
            Fatal
        };
    }
    
    
    
    using System;
    
    namespace MyApplication.Infrastructure.Logging.LoggingAbstractBase
    {
        public class LogEntry
        {
            public readonly LoggingEventTypeEnum Severity;
            public readonly string Message;
            public readonly Exception Exception;
    
            public LogEntry(LoggingEventTypeEnum severity, string message, Exception exception = null)
            {
                if (message == null) throw new ArgumentNullException("message");
                if (message == string.Empty) throw new ArgumentException("empty", "message");
    
                this.Severity = severity;
                this.Message = message;
                this.Exception = exception;
            }
        }
    }
    
    
    
    using System;
    using Microsoft.Extensions.Logging;
    
    namespace MyApplication.Infrastructure.Logging.LoggingCoreConcrete
    {
        public class DotNetCoreLogger<T> : MyApplication.Infrastructure.Logging.LoggingAbstractBase.ILogger
        {
            private readonly ILogger<T> concreteLogger;
    
            public DotNetCoreLogger(Microsoft.Extensions.Logging.ILogger<T> concreteLgr)
            {
                this.concreteLogger = concreteLgr ?? throw new ArgumentNullException("Microsoft.Extensions.Logging.ILogger is null");
            }
    
            public void Log(MyApplication.Infrastructure.Logging.LoggingAbstractBase.LogEntry entry)
            {
                if (null == entry)
                {
                    throw new ArgumentNullException("LogEntry is null");
                }
                else
                {
                    switch (entry.Severity)
                    {
                        case LoggingAbstractBase.LoggingEventTypeEnum.Debug:
                            this.concreteLogger.LogDebug(entry.Message);
                            break;
                        case LoggingAbstractBase.LoggingEventTypeEnum.Information:
                            this.concreteLogger.LogInformation(entry.Message);
                            break;
                        case LoggingAbstractBase.LoggingEventTypeEnum.Warning:
                            this.concreteLogger.LogWarning(entry.Message);
                            break;
                        case LoggingAbstractBase.LoggingEventTypeEnum.Error:
                            this.concreteLogger.LogError(entry.Message, entry.Exception);
                            break;
                        case LoggingAbstractBase.LoggingEventTypeEnum.Fatal:
                            this.concreteLogger.LogCritical(entry.Message, entry.Exception);
                            break;
                        default:
                            throw new ArgumentOutOfRangeException(string.Format("LogEntry.Severity out of range. (Severity='{0}')", entry.Severity));
                    }
                }
            }
    
            public void Log(string message)
            {
                this.concreteLogger.LogInformation(message);
            }
    
            public void Log(Exception exception)
            {
            /* "Always pass exception as first parameter" from https://blog.rsuter.com/logging-with-ilogger-recommendations-and-best-practices/ */
    
    
            /* there is an issue with https://github.com/aspnet/Logging/blob/master/src/Microsoft.Extensions.Logging.Abstractions/LoggerExtensions.cs
             * the default MessageFormatter (for the extension methods) is not doing anything with the "error".  this plays out as not getting full exception information when using extension methods.  :(
             * 
             *         private static string MessageFormatter(FormattedLogValues state, Exception error)
             *         {
             *                  return state.ToString();
             *         }
             *          
             * Below code/implementation is purposely NOT using any extension method(s) to bypass the above MessageFormatter mishap.
             * 
             * */
    
                this.concreteLogger.Log(LogLevel.Error, exception, exception.Message);
            }
        }
    }
    
    
    
    /* IoC/DI below */
    
    
            private static System.IServiceProvider BuildDi(Microsoft.Extensions.Configuration.IConfiguration config)
            {
                //setup our DI
                IServiceProvider serviceProvider = new ServiceCollection()
                    .AddLogging()
                    .AddSingleton<IConfiguration>(config)
                    .AddSingleton<MyApplication.Infrastructure.Logging.LoggingAbstractBase.ILogger, MyApplication.Infrastructure.Logging.LoggingCoreConcrete.DotNetCoreLogger<Program>>()
                    .BuildServiceProvider();
    
                //configure console logging
                serviceProvider
                    .GetService<ILoggerFactory>()
                    .AddConsole(LogLevel.Debug);
    
                return serviceProvider;
            }
    

    【讨论】:

    【解决方案2】:

    那么,我的问题是创建代理 Microsoft.Extensions.ILogger 的实现的正确方法是什么?

    你应该创建类似的东西:

    public sealed class MicrosoftLoggingAdapter  : ILogger
    {
        private readonly Microsoft.Extensions.ILogger adaptee;
    
        public MicrosoftLoggingAdapter (Microsoft.Extensions.ILogger adaptee) =>
            this.adaptee = adaptee;
    
        public void Log(LogEntry e) =>
            adaptee.Log(ToLevel(e.Severity), 0, e.Message, e.Exception, (s, _) => s);       
    
        private static LogLevel ToLevel(LoggingEventType s) =>
            s == LoggingEventType.Debug ? LogLevel.Debug  :
            s == LoggingEventType.Information ? LogLevel.Information :
            s == LoggingEventType.Warning ? LogLevel.Warning :
            s == LoggingEventType.Error ? LogLevel.Error :
            LogLevel.Critical;      
    }
    

    稍后在代码中使用它的最佳方式是什么?

    如果您使用的是 DI 容器,则只需使用 DI 容器将 ILogger 映射到 MicrosoftLoggingAdapter。您还需要注册Microsoft.Extensions.ILogger,或者只是将一个 MS 记录器实例提供给 DI 容器,以将其注入 MicrosoftLoggingAdapter 构造函数。

    如果你不使用 DI 容器,即使用Pure DI,那么你可以这样做:

    var logger = loggerFactory.CreateLogger("Application");
    
    ILogger logging_adapter = new MicrosoftLoggingAdapter(logger);
    
    var myobject = new MyClass(other_dependencies_here, logging_adapter);
    

    【讨论】:

    • 那么,这个适配器继承自的ILogger 是来自:stackoverflow.com/questions/5646820/… 的那个?抱歉,有三个不同的帖子:这个主题,我正在努力解决所有问题。
    • 你无处不在,史蒂文!!!这是(最佳)接受的答案........我的答案只是显示了我使用的内容.......也许有帮助,也许没有。
    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 2010-12-18
    • 1970-01-01
    • 2019-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多