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. ubuntu14.04 archive sources.list

    deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe multiverse deb http://archive. ...

  2. Access an instance through a console

    VNC or SPICE is used to view the console output of an instance, regardless of whether or not the con ...

  3. git cherry-pick简介

    本文编辑整理自: http://sg552.iteye.com/blog/1300713 http://web.mit.edu/bitbucket/git-doc/git-cherry-pick.tx ...

  4. shiro学习中报错解决方法

    [1] 最近在学习shiro,在学习过程中出现了一个问题,报错如下: org.apache.shiro.UnavailableSecurityManagerException: No Security ...

  5. 【leetcode】Substring with Concatenation of All Words

    Substring with Concatenation of All Words You are given a string, S, and a list of words, L, that ar ...

  6. 【leetcode】Maximum Subarray

    Maximum Subarray Find the contiguous subarray within an array (containing at least one number) which ...

  7. 1.把二元查找树转变成排序的双向链表[BST2DoubleLinkedList]

    [题目]:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树 . 10 / \ 6 14 / \ / \ 4 8 12 16 转 ...

  8. Angular中使用Rainbow

    在使用js类库和框架的时候,大家都习惯于编写自己的使用示例,如果能将示例中的html,js和css 进行展示, 并进行高亮显示,效果会很棒,例如在html高亮显示jquery代码 上面的示例是使用ra ...

  9. codeforces 338(Div 2) B. Longtail Hedgehog 解题报告

    题目链接:http://codeforces.com/problemset/problem/615/B 题目意思:要画一只 hedgehog,由 tail 和 spines 组成.我们要求得 beau ...

  10. 【QT】视频播放

    在网上没找到,在书上也没有.后来突然想直接在官网的类里面找Video 居然就有了. 把http://qt-project.org/doc/qt-5/qmediaplayer.html的例子补充完整后就 ...