zoukankan      html  css  js  c++  java
  • LibLog 类库 分析

    前期思考:

    1. Microsoft.Logging 是否可用?

    2. 是否需要提供默认的 Logger 实现? 不需要。1,用户自己开启日志功能,设置开启属性,即可打印出相应的日志。

    LibLog 类库分析:

    类库设计方只需要安装好相应的包,然后在自己的日志类中 添加如下字段。

    private static readonly ILog logger = LogProvider.GetCurrentClassLogger()

    或者

    private static readonly ILog Logger = LogProvider.For<YOUR_CLASS>()

    无需安装其他第三方的类库,在记录日志时,只需调用 logger.Info 或者 logger.Error 这时类库的设计就算完成了。当然类库设计方可以提供给客户端一个接口假设为 EnableLogger()

    客户端上,用户只需调用这个接口,即可实现类库日志的自动记录,而无需多余操作。

    这里面实现的原理是什么,在客户端侧,除了调用类库的一个开启日志功能的接口,其他没有任何操作。

    其实可以分析一下我们集成时的类库设计,首先是初始化 Logger 对象

    // GetCurrentClassLogger
    static ILog GetCurrentClassLogger()
    {
        var stackFrame = new StackFrame(1, false);
        return GetLogger(stackFrame.GetMethod().DeclaringType);
    }
    

    获取当前类的日志, 初始化一个 StackFrame,这个应该是 Call Stack 中的Record Frame。下面给出官网上的描述:

    A StackFrame is created and pushed on the call stack for every function call made during the execution of a thread.

    然后进行 GetLogger()

    static ILog GetLogger(string name)
    {
        var logProvider = CurrentLogProvider ?? ResolveLogProvider();
        return logProvider == null
            ? NoOpLogger.Instance
            : (ILog)new LoggerExecutionWrapper(logProvider.GetLogger(name), () => IsDisabled);
    }
    

    重点关注 ResolveLogProvider 的这个方法,首先是用到了 Lazy Initialization

    private static readonly Lazy ResolvedLogProvider = new Lazy(ForceResolveLogProvider);

    然后关注这个 ForceResolveLogProvider,Lazy 方法接收的参数类型为 Func 的委托类型,也就是说,接收一个返回值为 ILogProvider 的方法。

    internal static ILogProvider ForceResolveLogProvider()
    {
        try
        {
            foreach (var providerResolver in LogProviderResolvers)
            {
                if (providerResolver.Item1())
                {
                    return providerResolver.Item2();
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(
                "Exception occurred resolving a log provider. Logging for this assembly {0} is disabled. {1}",
                typeof(LogProvider).Assembly.FullName,
                ex);
        }
        return null;
    }
    

    该方法主要是查找当前进程中是否已经初始化某个日志类了,如果有,则放回这个类。若没有,则抛出异常。重点关注的是 LogProviderResolvers ,这是一个元祖类型 ,定义如下:

    static readonly List<Tuple<IsLoggerAvailable, CreateLogProvider>> LogProviderResolvers =
                    new List<Tuple<IsLoggerAvailable, CreateLogProvider>>
            {
                new Tuple<IsLoggerAvailable, CreateLogProvider>(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()),
                new Tuple<IsLoggerAvailable, CreateLogProvider>(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()),
                new Tuple<IsLoggerAvailable, CreateLogProvider>(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()),
                new Tuple<IsLoggerAvailable, CreateLogProvider>(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()),
            };
    

    配置完 Provider 之后,其实类库已经获取到你本地配置的日志类了,当类库中需要打印日志的需求的话,通过反射来找到项目中的日志类,然后初始化来执行相关的操作。

    DEMO样例:

    类库:https://github.com/doublnt/dotnetcore/blob/master/LibLogSample/CommonLibLog.cs

    客户端:https://github.com/doublnt/dotnetcore/blob/master/CSharpFundamental/LibLog/ConsumerLibLog.cs

  • 相关阅读:
    Log4Net 配置详解
    .Net Core 获取应用物理路径的常见问题
    Js/Jquery获取iframe中的元素
    Ztree树使用详解
    【解决】nginx + socket.io ,能连接但不响应事件
    基础文档官方链接
    位运算
    Java基础之集合框架--Collections.reverse()方法
    Android动画攻略—帧动画、补间动画、属性动画
    [转]京东mPaaS移动日志建设与应用
  • 原文地址:https://www.cnblogs.com/xiyin/p/11093238.html
Copyright © 2011-2022 走看看