Git是个很好的源码管理系统,你可以瞬间切换为任何历史版本。为了更好的解析NLog这个组件,我们将时钟倒拨回2004年。(注意:NLog v0.9 has been released 是在2005-06-09)

架构

首先主体项目的代码结构是这个样子的:

逻辑上是这个样子的:

测试

这个时候,代码还没有很多的test case,处于相当的简单粗暴阶段。

static void Main(string[] args)
{
    var l = LogManager.GetLogger("Aaa");
    var l2 = LogManager.GetLogger("Bbb");

    l.Debug("to jest debug");
    l.Info("to jest info");
    l.Warn("to jest warning");
    l2.Debug("to jest debug");
    l2.Info("to jest info");
    l2.Warn("to jest warning");
    l.Error("to jest error");
    l.Fatal("to jest fatal");
    l2.Error("to jest error");
    l2.Fatal("to jest fatal");
    ....
}

GetLogger

入口显然还是LogManager的GetLogger。

    public static Logger GetLogger(string name)
    {
        if (ReloadConfigOnNextLog)
            ReloadConfig();

        lock (typeof(LogManager))
        {

            object l = _loggerCache[name];
            if (l != null)
                return (Logger)l;

            ArrayList[] appendersByLevel = GetAppendersByLevelForLogger(name, Configuration);

            Logger newLogger = new LoggerImpl(name, appendersByLevel);
            _loggerCache[name] = newLogger;
            return newLogger;
        }
    }

这里采用经典的hashtable去储存这些logger实例,以name为key。

Configuration

第一步,从appconfig里面取。

lock (typeof(LogManager))
{
    if (_configLoaded)
        return _config;

    if (_config == null)
    {
        // try to load default configuration
        _config = XmlLoggingConfiguration.AppConfig;
    }

第二步,从一些约定的位置去取,这里我把所有的nlog修改成了mlog是为了方便识别变化点。

private static IEnumerable<string> GetCandidateConfigFileNames()
{
    var currentAppDomain = AppDomain.CurrentDomain;

    // mLog.config from application directory
    yield return Path.Combine(currentAppDomain.BaseDirectory, "mLog.config");

    // Current config file with .config renamed to .nlog
    string cf = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
    if (cf != null)
    {
        yield return Path.ChangeExtension(cf, ".mlog");

        // .nlog file based on the non-vshost version of the current config file
        const string vshostSubStr = ".vshost.";
        if (cf.Contains(vshostSubStr))
        {
            yield return Path.ChangeExtension(cf.Replace(vshostSubStr, "."), ".mlog");
        }
    }
}

顺序总结下来,如下图所示:

拿到配置后,这里使用XmlLoggingConfiguration来读取xml格式的配置。

public class XmlLoggingConfiguration : LoggingConfiguration

最后,如果成功的取到了配置,将会实时监控改配置文件的变化

if (_config != null)
    {
        _watcher.Watch(_config.FileNamesToWatch);
    }

当配置改变时候触发标志位的变化:

private static void ConfigFileChanged(object sender, EventArgs args)
{
    // Console.WriteLine("ConfigFileChanged!!!");
    ReloadConfigOnNextLog = true;
}

在每一次write之前,会依据该标志位的变化重载配置文件。

private void WriteToAppenders(LogLevel level, ArrayList appenders, IFormatProvider formatProvider, string message, object[] args) {
        if (LogManager.ReloadConfigOnNextLog)
            LogManager.ReloadConfig();

这个就是所谓的配置文件修改后立即热刷新的实现,我们在写自己的组件的时候可以参考下。

つづく

.NET NLog 详解(二)的更多相关文章

  1. .NET DLL 保护措施详解(二)关于性能的测试

    先说结果: 加了缓存的结果与C#原生代码差异不大了 我对三种方式进行了测试: 第一种,每次调用均动态编译 第二种,缓存编译好的对象 第三种,直接调用原生C#代码 .net dll保护系列 ------ ...

  2. PopUpWindow使用详解(二)——进阶及答疑

      相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  3. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  4. logback -- 配置详解 -- 二 -- <appender>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  5. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  6. [转]文件IO详解(二)---文件描述符(fd)和inode号的关系

    原文:https://www.cnblogs.com/frank-yxs/p/5925563.html 文件IO详解(二)---文件描述符(fd)和inode号的关系 ---------------- ...

  7. Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)

    View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇  ...

  8. HTTPS详解二:SSL / TLS 工作原理和详细握手过程

    HTTPS 详解一:附带最精美详尽的 HTTPS 原理图 HTTPS详解二:SSL / TLS 工作原理和详细握手过程 在上篇文章HTTPS详解一中,我已经为大家介绍了 HTTPS 的详细原理和通信流 ...

  9. Linux dts 设备树详解(二) 动手编写设备树dts

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 前言 硬件结构 设备树dts文件 前言 在简单了解概念之后,我们可以开始尝试写一个 ...

随机推荐

  1. JS插件之——ztree

    很牛逼的一个树形菜单,树形下拉框插件.一年前用过,很好用.今天又有机会拿过来用,温故一下基本点,nice!! 官方文档说明的非常详细,按照API慢慢看,耐心解读,自然就可以解惑了. 官方文档及其源码下 ...

  2. Oracle语句优化之一

    public List<TdDepartment> createZtreeDep(String compId) { List<TdDepartment> dd = new Ar ...

  3. C#之常见数组编码错误

    摘抄自C#本质论(第四版,P55) 常见错误 错误描述 改正后的代码 int numbers[] 用于声明数组的方括号放在数据类型之后,而不是在变量标识符之后 int[] numbers; int[] ...

  4. ACM/ICPC 之 平面几何-两直线关系(POJ 1269)

    题意:给定四点的坐标(x,y),分别确定两直线,求出其交点,若重合or平行则输出相应信息 用四个点的坐标算出直线通式(ax+by+c=0)中的a,b,c,然后利用a,b,c计算出交点坐标(其他公式不够 ...

  5. java Thread和Runnable区别

    ①Thread类实现了Runnable接口,主要构造方法为Thread(Runnable target).Thread(Runnable target,String name).Thread(Stri ...

  6. 【编程题目】请修改 append 函数,利用这个函数实现两个非降序链表的并集

    42.请修改 append 函数,利用这个函数实现(链表):两个非降序链表的并集,1->2->3 和 2->3->5 并为 1->2->3->5另外只能输出结 ...

  7. HDU 4314 Save the dwarfs (DP) ---转载

    题目:传送门. 这个是DP,比赛的时候用贪心写了好久没写出来. 题意: 有n个矮人被困在深度为h的井中,每个矮人都ai(脚到肩膀的高度)和bi(手臂长度), 当存在a1 + a2 + ... + ak ...

  8. 在JAVA中如何跳出当前的多重嵌套循环

    可以使用return,但使用return后,会跳出整个函数,多重循环后面的代码无法执行. public static void main(String[] args) { // TODO Auto-g ...

  9. centos 6.5 配置LDAP服务器+客户端!

    各种度娘!各种歌哥!网上教程参差不齐,历时1天,终于完成,不敢独享,遂,总结分享之,有问题可以留言,知无不言...开始吧 Note: 本次配置的服务器环境是<redhat enterprise ...

  10. HTML标记语法之图片Img元素

    语法:<img src=”xxx.jpg”alt=”xxx”title=”xxx”> 属性可取值如下: 属性名称 属性值 说明 src URL 图片路径 alt 文本 图片无法显示时的文本 ...